There are several ways to "program" the Emacs Calculator, depending on the nature of the problem you need to solve.
EvalRules
, they will be applied automatically to all Calc
results in just the same way as an internal "rule" is applied to
evaluate `sqrt(9)' to 3 and so on. See section Automatic Rewrites.
Programming features are available through the z and Z
prefix keys. New commands that you define are two-key sequences
beginning with z. Commands for managing these definitions
use the shift-Z prefix. (The Z T (calc-timing
)
command is described elsewhere; see section Troubleshooting Commands.
The Z C (calc-user-define-composition
) command is also
described elsewhere; see section User-Defined Compositions.)
Any Calculator command may be bound to a key using the Z D
(calc-user-define
) command. Actually, it is bound to a two-key
sequence beginning with the lower-case z prefix.
The Z D command first prompts for the key to define. For example,
press Z D a to define the new key sequence z a. You are then
prompted for the name of the Calculator command that this key should
run. For example, the calc-sincos
command is not normally
available on a key. Typing Z D s sincos RET programs the
z s key sequence to run calc-sincos
. This definition will remain
in effect for the rest of this Emacs session, or until you redefine
z s to be something else.
You can actually bind any Emacs command to a z key sequence by backspacing over the `calc-' when you are prompted for the command name.
As with any other prefix key, you can type z ? to see a list of all the two-key sequences you have defined that start with z. Initially, no z sequences (except z ? itself) are defined.
User keys are typically letters, but may in fact be any key. (META-keys are not permitted, nor are a terminal's special function keys which generate multi-character sequences when pressed.) You can define different commands on the shifted and unshifted versions of a letter if you wish.
The Z U (calc-user-undefine
) command unbinds a user key.
For example, the key sequence Z U s will undefine the sincos
key we defined above.
The Z P (calc-user-define-permanent
) command makes a key
binding permanent so that it will remain in effect even in future Emacs
sessions. (It does this by adding a suitable bit of Lisp code into
your `.emacs' file.) For example, Z P s would register
our sincos
command permanently. If you later wish to unregister
this command you must edit your `.emacs' file by hand.
(See section General Mode Commands, for a way to tell Calc to use a
different file instead of `.emacs'.)
The Z P command also saves the user definition, if any, for the command bound to the key. After Z F and Z C, a given user key could invoke a command, which in turn calls an algebraic function, which might have one or more special display formats. A single Z P command will save all of these definitions.
To save a command or function without its key binding (or if there is no key binding for the command or function), type ' (the apostrophe) when prompted for a key. Then, type the function name, or backspace to change the `calcFunc-' prefix to `calc-' and enter a command name. (If the command you give implies a function, the function will be saved, and if the function has any display formats, those will be saved, but not the other way around: Saving a function will not save any commands or key bindings associated with the function.)
The Z E (calc-user-define-edit
) command edits the definition
of a user key. This works for keys that have been defined by either
keyboard macros or formulas; further details are contained in the relevant
following sections.
The easiest way to "program" the Emacs Calculator is to use standard keyboard macros. Press C-x ( to begin recording a macro. From this point on, keystrokes you type will be saved away as well as performing their usual functions. Press C-x ) to end recording. Press shift-X (or the standard Emacs key sequence C-x e) to execute your keyboard macro by replaying the recorded keystrokes. See section `Keyboard Macros' in the Emacs Manual, for further information.
When you use X to invoke a keyboard macro, the entire macro is
treated as a single command by the undo and trail features. The stack
display buffer is not updated during macro execution, but is instead
fixed up once the macro completes. Thus, commands defined with keyboard
macros are convenient and efficient. The C-x e command, on the
other hand, invokes the keyboard macro with no special treatment: Each
command in the macro will record its own undo information and trail entry,
and update the stack buffer accordingly. If your macro uses features
outside of Calc's control to operate on the contents of the Calc stack
buffer, or if it includes Undo, Redo, or last-arguments commands, you
must use C-x e to make sure the buffer and undo list are up-to-date
at all times. You could also consider using K (calc-keep-args
)
instead of M-RET (calc-last-args
).
Calc extends the standard Emacs keyboard macros in several ways. Keyboard macros can be used to create user-defined commands. Keyboard macros can include conditional and iteration structures, somewhat analogous to those provided by a traditional programmable calculator.
Once you have defined a keyboard macro, you can bind it to a z
key sequence with the Z K (calc-user-define-kbd-macro
) command.
This command prompts first for a key, then for a command name. For
example, if you type C-x ( n TAB n TAB C-x ) you will
define a keyboard macro which negates the top two numbers on the stack
(TAB swaps the top two stack elements). Now you can type
Z K n RET to define this keyboard macro onto the z n key
sequence. The default command name (if you answer the second prompt with
just the RET key as in this example) will be something like
`calc-User-n'. The keyboard macro will now be available as both
z n and M-x calc-User-n. You can backspace and enter a more
descriptive command name if you wish.
Macros defined by Z K act like single commands; they are executed in the same way as by the X key. If you wish to define the macro as a standard no-frills Emacs macro (to be executed as if by C-x e), give a negative prefix argument to Z K.
Once you have bound your keyboard macro to a key, you can use Z P to register it permanently with Emacs. See section Creating User Keys.
The Z E (calc-user-define-edit
) command on a key that has
been defined by a keyboard macro tries to use the edit-kbd-macro
command to edit the macro. This command may be found in the
`macedit' package, a copy of which comes with Calc. It decomposes
the macro definition into full Emacs command names, like calc-pop
and calc-add
. Type M-# M-# to finish editing and update
the definition stored on the key, or, to cancel the edit, type
M-# x.
If you give a negative numeric prefix argument to Z E, the keyboard
macro is edited in spelled-out keystroke form. For example, the editing
buffer might contain the nine characters `1 RET 2 +'. When you press
M-# M-#, the read-kbd-macro
feature of the `macedit'
package is used to reinterpret these key names. The
notations RET
, LFD
, TAB
, SPC
, DEL
, and
NUL
must be written in all uppercase, as must the prefixes C-
and M-
. Spaces and line breaks are ignored. Other characters are
copied verbatim into the keyboard macro. Basically, the notation is the
same as is used in all of this manual's examples, except that the manual
takes some liberties with spaces: When we say ' [1 2 3] RET, we take
it for granted that it is clear we really mean ' [1 SPC 2 SPC 3] RET,
which is what read-kbd-macro
wants to see.
If `macedit' is not available, Z E edits the keyboard macro in "raw" form; the editing buffer simply contains characters like `1^M2+' (here `^M' represents the carriage-return character). Editing in this mode, you will have to use C-q to enter new control characters into the buffer.
The M-# m (read-kbd-macro
) command reads an Emacs "region"
of spelled-out keystrokes and defines it as the current keyboard macro.
It is a convenient way to define a keyboard macro that has been stored
in a file, or to define a macro without executing it at the same time.
The M-# m command works only if `macedit' is present.
The Z [ (calc-kbd-if
) and Z ] (calc-kbd-end-if
)
commands allow you to put simple tests in a keyboard macro. When Calc
sees the Z [, it pops an object from the stack and, if the object is
a non-zero value, continues executing keystrokes. But if the object is
zero, or if it is not provably nonzero, Calc skips ahead to the matching
Z ] keystroke. See section Logical Operations, for a set of commands for
performing tests which conveniently produce 1 for true and 0 for false.
For example, RET 0 a < Z [ n Z ] implements an absolute-value
function in the form of a keyboard macro. This macro duplicates the
number on the top of the stack, pushes zero and compares using a <
(calc-less-than
), then, if the number was less than zero,
executes n (calc-change-sign
). Otherwise, the change-sign
command is skipped.
To program this macro, type C-x (, type the above sequence of keystrokes, then type C-x ). Note that the keystrokes will be executed while you are making the definition as well as when you later re-execute the macro by typing X. Thus you should make sure a suitable number is on the stack before defining the macro so that you don't get a stack-underflow error during the definition process.
Conditionals can be nested arbitrarily. However, there should be exactly one Z ] for each Z [ in a keyboard macro.
The Z : (calc-kbd-else
) command allows you to choose between
two keystroke sequences. The general format is cond Z [
then-part Z : else-part Z ]. If cond is true
(i.e., if the top of stack contains a non-zero number after cond
has been executed), the then-part will be executed and the
else-part will be skipped. Otherwise, the then-part will
be skipped and the else-part will be executed.
The Z | (calc-kbd-else-if
) command allows you to choose
between any number of alternatives. For example,
cond1 Z [ part1 Z : cond2 Z | part2 Z :
part3 Z ] will execute part1 if cond1 is true,
otherwise it will execute part2 if cond2 is true, otherwise
it will execute part3.
More precisely, Z [ pops a number and conditionally skips to the next matching Z : or Z ] key. Z ] has no effect when actually executed. Z : skips to the next matching Z ]. Z | pops a number and conditionally skips to the next matching Z : or Z ]; thus, Z [ and Z | are functionally equivalent except that Z [ participates in nesting but Z | does not.
Calc's conditional and looping constructs work by scanning the keyboard macro for occurrences of character sequences like `Z:' and `Z]'. One side-effect of this is that if you use these constructs you must be careful that these character pairs do not occur by accident in other parts of the macros. Since Calc rarely uses shift-Z for any purpose except as a prefix character, this is not likely to be a problem. Another side-effect is that it will not work to define your own custom key bindings for these commands. Only the standard shift-Z bindings will work correctly.
If Calc gets stuck while skipping characters during the definition of a macro, type Z C-g to cancel the definition. (Typing plain C-g actually adds a C-g keystroke to the macro.)
The Z < (calc-kbd-repeat
) and Z >
(calc-kbd-end-repeat
) commands pop a number from the stack,
which must be an integer, then repeat the keystrokes between the brackets
the specified number of times. If the integer is zero or negative, the
body is skipped altogether. For example, 1 TAB Z < 2 * Z >
computes two to a nonnegative integer power. First, we push 1 on the
stack and then swap the integer argument back to the top. The Z <
pops that argument leaving the 1 back on top of the stack. Then, we
repeat a multiply-by-two step however many times.
Once again, the keyboard macro is executed as it is being entered.
In this case it is especially important to set up reasonable initial
conditions before making the definition: Suppose the integer 1000 just
happened to be sitting on the stack before we typed the above definition!
Another approach is to enter a harmless dummy definition for the macro,
then go back and edit in the real one with a Z E command. Yet
another approach is to type the macro as written-out keystroke names
in a buffer, then use M-# m (read-kbd-macro
) to read the
macro.
The Z / (calc-kbd-break
) command allows you to break out
of a keyboard macro loop prematurely. It pops an object from the stack;
if that object is true (a non-zero number), control jumps out of the
innermost enclosing Z < ... Z > loop and continues
after the Z >. If the object is false, the Z / has no
effect. Thus cond Z / is similar to `if (cond) break;'
in the C language.
The Z ( (calc-kbd-for
) and Z ) (calc-kbd-end-for
)
commands are similar to Z < and Z >, except that they make the
value of the counter available inside the loop. The general layout is
init final Z ( body step Z ). The Z (
command pops initial and final values from the stack. It then creates
a temporary internal counter and initializes it with the value init.
The Z ( command then repeatedly pushes the counter value onto the
stack and executes body and step, adding step to the
counter each time until the loop finishes.
By default, the loop finishes when the counter becomes greater than (or less than) final, assuming initial is less than (greater than) final. If initial is equal to final, the body executes exactly once. The body of the loop always executes at least once. For example, 0 1 10 Z ( 2 ^ + 1 Z ) computes the sum of the squares of the integers from 1 to 10, in steps of 1.
If you give a numeric prefix argument of 1 to Z (, the loop is forced to use upward-counting conventions. In this case, if initial is greater than final the body will not be executed at all. Note that step may still be negative in this loop; the prefix argument merely constrains the loop-finished test. Likewise, a prefix argument of -1 forces downward-counting conventions.
The Z { (calc-kbd-loop
) and Z }
(calc-kbd-end-loop
) commands are similar to Z < and
Z >, except that they do not pop a count from the stack--they
effectively create an infinite loop. Every Z { ... Z }
loop ought to include at least one Z / to make sure the loop
doesn't run forever. (If any error message occurs which causes Emacs
to beep, the keyboard macro will also be halted; this is a standard
feature of Emacs. You can also generally press C-g to halt a
running keyboard macro, although not all versions of Unix support
this feature.)
The conditional and looping constructs are not actually tied to keyboard macros, but they are most often used in that context. For example, the keystrokes 10 Z < 23 RET Z > push ten copies of 23 onto the stack. This can be typed "live" just as easily as in a macro definition.
See section Conditionals in Keyboard Macros, for some additional notes about conditional and looping commands.
Keyboard macros sometimes want to operate under known conditions without affecting surrounding conditions. For example, a keyboard macro may wish to turn on Fraction Mode, or set a particular precision, independent of the user's normal setting for those modes.
Macros also sometimes need to use local variables. Assignments to
local variables inside the macro should not affect any variables
outside the macro. The Z ` (calc-kbd-push
) and Z '
(calc-kbd-pop
) commands give you both of these capabilities.
When you type Z ` (with a backquote or accent grave character),
the values of various mode settings are saved away. The ten "quick"
variables q0
through q9
are also saved. When
you type Z ' (with an apostrophe), these values are restored.
Pairs of Z ` and Z ' commands may be nested.
If a keyboard macro halts due to an error in between a Z ` and a Z ', the saved values will be restored correctly even though the macro never reaches the Z ' command. Thus you can use Z ` and Z ' without having to worry about what happens in exceptional conditions.
If you type Z ` "live" (not in a keyboard macro), Calc puts you into a "recursive edit." You can tell you are in a recursive edit because there will be extra square brackets in the mode line, as in `[(Calculator)]'. These brackets will go away when you type the matching Z ' command. The modes and quick variables will be saved and restored in just the same way as if actual keyboard macros were involved.
The modes saved by Z ` and Z ' are the current precision and binary word size, the angular mode (Deg, Rad, or HMS), the simplification mode, Algebraic mode, Symbolic mode, Infinite mode, Matrix or Scalar mode, Fraction mode, and the current complex mode (Polar or Rectangular). The ten "quick" variables' values (or lack thereof) are also saved.
Most mode-setting commands act as toggles, but with a numeric prefix they force the mode either on (positive prefix) or off (negative or zero prefix). Since you don't know what the environment might be when you invoke your macro, it's best to use prefix arguments for all mode-setting commands inside the macro.
In fact, C-u Z ` is like Z ` except that it sets the modes listed above to their default values. As usual, the matching Z ' will restore the modes to their settings from before the C-u Z `. Also, Z ` with a negative prefix argument resets algebraic mode to its default (off) but leaves the other modes the same as they were outside the construct.
The contents of the stack and trail, values of non-quick variables, and other settings such as the language mode and the various display modes, are not affected by Z ` and Z '.
The Z = (calc-kbd-report
) command displays an informative
message including the value on the top of the stack. You are prompted
to enter a string. That string, along with the top-of-stack value,
is displayed unless m w (calc-working
) has been used
to turn such messages off.
The Z # (calc-kbd-query
) command displays a prompt message
(which you enter during macro definition), then does an algebraic entry
which takes its input from the keyboard, even during macro execution.
This command allows your keyboard macros to accept numbers or formulas
as interactive input. All the normal conventions of algebraic input,
including the use of $ characters, are supported.
See section `Kbd Macro Query' in the Emacs Manual, for a description of
C-x q (kbd-macro-query
), the standard Emacs way to accept
keyboard input during a keyboard macro. In particular, you can use
C-x q to enter a recursive edit, which allows the user to perform
any Calculator operations interactively before pressing C-M-c to
return control to the keyboard macro.
Calc provides one special keyboard macro, called up by M-# z
(calc-user-invocation
), that is intended to allow you to define
your own special way of starting Calc. To define this "invocation
macro," create the macro in the usual way with C-x ( and
C-x ), then type Z I (calc-user-define-invocation
).
There is only one invocation macro, so you don't need to type any
additional letters after Z I. From now on, you can type
M-# z at any time to execute your invocation macro.
For example, suppose you find yourself often grabbing rectangles of numbers into Calc and multiplying their columns. You can do this by typing M-# r to grab, and V R : * to multiply columns. To make this into an invocation macro, just type C-x ( M-# r V R : * C-x ), then Z I. Then, to multiply a rectangle of data, just mark the data in its buffer in the usual way and type M-# z.
Invocation macros are treated like regular Emacs keyboard macros; all the special features described above for Z K-style macros do not apply. M-# z is just like C-x e, except that it uses the macro that was last stored by Z I. (In fact, the macro does not even have to have anything to do with Calc!)
The m m command saves the last invocation macro defined by Z I along with all the other Calc mode settings. See section General Mode Commands.
Another way to create a new Calculator command uses algebraic formulas.
The Z F (calc-user-define-formula
) command stores the
formula at the top of the stack as the definition for a key. This
command prompts for five things: The key, the command name, the function
name, the argument list, and the behavior of the command when given
non-numeric arguments.
For example, suppose we type ' a+2b RET to push the formula
`a + 2*b' onto the stack. We now type Z F m to define this
formula on the z m key sequence. The next prompt is for a command
name, beginning with `calc-', which should be the long (M-x) form
for the new command. If you simply press RET, a default name like
calc-User-m
will be constructed. In our example, suppose we enter
spam RET to define the new command as calc-spam
.
If you want to give the formula a long-style name only, you can press SPC or RET when asked which single key to use. For example Z F RET spam RET defines the new command as M-x calc-spam, with no keyboard equivalent.
The third prompt is for a function name. The default is to use the same name as the command name but with `calcFunc-' in place of `calc-'. This is the name you will use if you want to enter your new function in an algebraic formula. Suppose we enter yow RET. Then the new function can be invoked by pushing two numbers on the stack and typing z m or x spam, or by entering the algebraic formula `yow(x,y)'.
The fourth prompt is for the function's argument list. This is used to associate values on the stack with the variables that appear in the formula. The default is a list of all variables which appear in the formula, sorted into alphabetical order. In our case, the default would be `(a b)'. This means that, when the user types z m, the Calculator will remove two numbers from the stack, substitute these numbers for `a' and `b' (respectively) in the formula, then simplify the formula and push the result on the stack. In other words, 10 RET 100 z m would replace the 10 and 100 on the stack with the number 210, which is a + 2 b with a=10 and b=100. Likewise, the formula `yow(10, 100)' will be evaluated by substituting a=10 and b=100 in the definition.
You can rearrange the order of the names before pressing RET to control which stack positions go to which variables in the formula. If you remove a variable from the argument list, that variable will be left in symbolic form by the command. Thus using an argument list of `(b)' for our function would cause 10 z m to replace the 10 on the stack with the formula `a + 20'. If we had used an argument list of `(b a)', the result with inputs 10 and 100 would have been 120.
You can also put a nameless function on the stack instead of just a formula, as in `<a, b : a + 2 b>'. See section Specifying Operators. In this example, the command will be defined by the formula `a + 2 b' using the argument list `(a b)'.
The final prompt is a y-or-n question concerning what to do if symbolic arguments are given to your function. If you answer y, then executing z m (using the original argument list `(a b)') with arguments 10 and x will leave the function in symbolic form, i.e., `yow(10,x)'. On the other hand, if you answer n, then the formula will always be expanded, even for non-constant arguments: `10 + 2 x'. If you never plan to feed algebraic formulas to your new function, it doesn't matter how you answer this question.
If you answered y to this question you can still cause a function
call to be expanded by typing a " (calc-expand-formula
).
Also, Calc will expand the function if necessary when you take a
derivative or integral or solve an equation involving the function.
Once you have defined a formula on a key, you can retrieve this formula
with the Z G (calc-user-define-get-defn
) command. Press a
key, and this command pushes the formula that was used to define that
key onto the stack. Actually, it pushes a nameless function that
specifies both the argument list and the defining formula. You will get
an error message if the key is undefined, or if the key was not defined
by a Z F command.
The Z E (calc-user-define-edit
) command on a key that has
been defined by a formula uses a variant of the calc-edit
command
to edit the defining formula. Press M-# M-# to finish editing and
store the new formula back in the definition, or M-# x to
cancel the edit. (The argument list and other properties of the
definition are unchanged; to adjust the argument list, you can use
Z G to grab the function onto the stack, edit with `, and
then re-execute the Z F command.)
As usual, the Z P command records your definition permanently. In this case it will permanently record all three of the relevant definitions: the key, the command, and the function.
You may find it useful to turn off the default simplifications with
m O (calc-no-simplify-mode
) when entering a formula to be
used as a function definition. For example, the formula `deriv(a^2,v)'
which might be used to define a new function `dsqr(a,v)' will be
"simplified" to 0 immediately upon entry since deriv
considers
a to be constant with respect to v. Turning off
default simplifications cures this problem: The definition will be stored
in symbolic form without ever activating the deriv
function. Press
m D to turn the default simplifications back on afterwards.
The Calculator can be programmed quite extensively in Lisp. All you
do is write a normal Lisp function definition, but with defmath
in place of defun
. This has the same form as defun
, but it
automagically replaces calls to standard Lisp functions like +
and
zerop
with calls to the corresponding functions in Calc's own library.
Thus you can write natural-looking Lisp code which operates on all of the
standard Calculator data types. You can then use Z D if you wish to
bind your new command to a z-prefix key sequence. The Z E command
will not edit a Lisp-based definition.
Emacs Lisp is described in the GNU Emacs Lisp Reference Manual. This section assumes a familiarity with Lisp programming concepts; if you do not know Lisp, you may find keyboard macros or rewrite rules to be an easier way to program the Calculator.
This section first discusses ways to write commands, functions, or small programs to be executed inside of Calc. Then it discusses how your own separate programs are able to call Calc from the outside. Finally, there is a list of internal Calc functions and data structures for the true Lisp enthusiast.
The defmath
function (actually a Lisp macro) is like defun
except that code in the body of the definition can make use of the full
range of Calculator data types. The prefix `calcFunc-' is added
to the specified name to get the actual Lisp function name. As a simple
example,
(defmath myfact (n) (if (> n 0) (* n (myfact (1- n))) 1))
This actually expands to the code,
(defun calcFunc-myfact (n) (if (math-posp n) (math-mul n (calcFunc-myfact (math-add n -1))) 1))
This function can be used in algebraic expressions, e.g., `myfact(5)'.
The `myfact' function as it is defined above has the bug that an
expression `myfact(a+b)' will be simplified to 1 because the
formula `a+b' is not considered to be posp
. A robust
factorial function would be written along the following lines:
(defmath myfact (n) (if (> n 0) (* n (myfact (1- n))) (if (= n 0) 1 nil))) ; this could be simplified as: (and (= n 0) 1)
If a function returns nil
, it is left unsimplified by the Calculator
(except that its arguments will be simplified). Thus, `myfact(a+1+2)'
will be simplified to `myfact(a+3)' but no further. Beware that every
time the Calculator reexamines this formula it will attempt to resimplify
it, so your function ought to detect the returning-nil
case as
efficiently as possible.
The following standard Lisp functions are treated by defmath
:
+
, -
, *
, /
, %
, ^
or
expt
, =
, <
, >
, <=
, >=
,
/=
, 1+
, 1-
, logand
, logior
, logxor
,
logandc2
, lognot
. Also, ~=
is an abbreviation for
math-nearly-equal
, which is useful in implementing Taylor series.
For other functions func, if a function by the name `calcFunc-func' exists it is used, otherwise if a function by the name `math-func' exists it is used, otherwise if func itself is defined as a function it is used, otherwise `calcFunc-func' is used on the assumption that this is a to-be-defined math function. Also, if the function name is quoted as in `('integerp a)' the function name is always used exactly as written (but not quoted).
Variable names have `var-' prepended to them unless they appear in
the function's argument list or in an enclosing let
, let*
,
for
, or foreach
form,
or their names already contain a `-' character. Thus a reference to
`foo' is the same as a reference to `var-foo'.
A few other Lisp extensions are available in defmath
definitions:
elt
function accepts any number of index variables.
Note that Calc vectors are stored as Lisp lists whose first
element is the symbol vec
; thus, `(elt v 2)' yields
the second element of vector v
, and `(elt m i j)'
yields one element of a Calc matrix.
setq
function has been extended to act like the Common
Lisp setf
function. (The name setf
is recognized as
a synonym of setq
.) Specifically, the first argument of
setq
can be an nth
, elt
, car
, or cdr
form,
in which case the effect is to store into the specified
element of a list. Thus, `(setq (elt m i j) x)' stores x
into one element of a matrix.
for
looping construct is available. For example,
`(for ((i 0 10)) body)' executes body
once for each
binding of i from zero to 10. This is like a let
form in that i is temporarily bound to the loop count
without disturbing its value outside the for
construct.
Nested loops, as in `(for ((i 0 10) (j 0 (1- i) 2)) body)',
are also available. For each value of i from zero to 10,
j counts from 0 to i-1 in steps of two. Note that
for
has the same general outline as let*
, except
that each element of the header is a list of three or four
things, not just two.
foreach
construct loops over elements of a list.
For example, `(foreach ((x (cdr v))) body)' executes
body
with x bound to each element of Calc vector
v in turn. The purpose of cdr
here is to skip over
the initial vec
symbol in the vector.
break
function breaks out of the innermost enclosing
while
, for
, or foreach
loop. If given a
value, as in `(break x)', this value is returned by the
loop. (Lisp loops otherwise always return nil
.)
return
function prematurely returns from the enclosing
function. For example, `(return (+ x y))' returns x+y
as the value of a function. You can use return
anywhere
inside the body of the function.
Non-integer numbers (and extremely large integers) cannot be included
directly into a defmath
definition. This is because the Lisp
reader will fail to parse them long before defmath
ever gets control.
Instead, use the notation, `:"3.1415"'. In fact, any algebraic
formula can go between the quotes. For example,
(defmath sqexp (x) ; sqexp(x) == sqrt(exp(x)) == exp(x*0.5) (and (numberp x) (exp :"x * 0.5")))
expands to
(defun calcFunc-sqexp (x) (and (math-numberp x) (calcFunc-exp (math-mul x '(float 5 -1)))))
Note the use of numberp
as a guard to ensure that the argument is
a number first, returning nil
if not. The exponential function
could itself have been included in the expression, if we had preferred:
`:"exp(x * 0.5)"'. As another example, the multiplication-and-recursion
step of myfact
could have been written
:"n * myfact(n-1)"
If a file named `.emacs' exists in your home directory, Emacs reads
and executes the Lisp forms in this file as it starts up. While it may
seem like a good idea to put your favorite defmath
commands here,
this has the unfortunate side-effect that parts of the Calculator must be
loaded in to process the defmath
commands whether or not you will
actually use the Calculator! A better effect can be had by writing
(put 'calc-define 'thing '(progn (defmath ... ) (defmath ... ) ))
The put
function adds a property to a symbol. Each Lisp
symbol has a list of properties associated with it. Here we add a
property with a name of thing
and a `(progn ...)' form as
its value. When Calc starts up, and at the start of every Calc command,
the property list for the symbol calc-define
is checked and the
values of any properties found are evaluated as Lisp forms. The
properties are removed as they are evaluated. The property names
(like thing
) are not used; you should choose something like the
name of your project so as not to conflict with other properties.
The net effect is that you can put the above code in your `.emacs' file and it will not be executed until Calc is loaded. Or, you can put that same code in another file which you load by hand either before or after Calc itself is loaded.
The properties of calc-define
are evaluated in the same order
that they were added. They can assume that the Calc modules `calc.el',
`calc-ext.el', and `calc-macs.el' have been fully loaded, and
that the `*Calculator*' buffer will be the current buffer.
If your calc-define
property only defines algebraic functions,
you can be sure that it will have been evaluated before Calc tries to
call your function, even if the file defining the property is loaded
after Calc is loaded. But if the property defines commands or key
sequences, it may not be evaluated soon enough. (Suppose it defines the
new command tweak-calc
; the user can load your file, then type
M-x tweak-calc before Calc has had chance to do anything.) To
protect against this situation, you can put
(run-hooks 'calc-check-defines)
at the end of your file. The calc-check-defines
function is what
looks for and evaluates properties on calc-define
; run-hooks
has the advantage that it is quietly ignored if calc-check-defines
is not yet defined because Calc has not yet been loaded.
Examples of things that ought to be enclosed in a calc-define
property are defmath
calls, define-key
calls that modify
the Calc key map, and any calls that redefine things defined inside Calc.
Ordinary defun
s need not be enclosed with calc-define
.
If a defmath
form contains an interactive
clause, it defines
a Calculator command. Actually such a defmath
results in two
function definitions: One, a `calcFunc-' function as was just described,
with the interactive
clause removed. Two, a `calc-' function
with a suitable interactive
clause and some sort of wrapper to make
the command work in the Calc environment.
In the simple case, the interactive
clause has the same form as
for normal Emacs Lisp commands:
(defmath increase-precision (delta) "Increase precision by DELTA." ; This is the "documentation string" (interactive "p") ; Register this as a M-x-able command (setq calc-internal-prec (+ calc-internal-prec delta)))
This expands to the pair of definitions,
(defun calc-increase-precision (delta) "Increase precision by DELTA." (interactive "p") (calc-wrapper (setq calc-internal-prec (math-add calc-internal-prec delta)))) (defun calcFunc-increase-precision (delta) "Increase precision by DELTA." (setq calc-internal-prec (math-add calc-internal-prec delta)))
where in this case the latter function would never really be used! Note
that since the Calculator stores small integers as plain Lisp integers,
the math-add
function will work just as well as the native
+
even when the intent is to operate on native Lisp integers.
The `calc-wrapper' call invokes a macro which surrounds the body of the function with code that looks roughly like this:
(let ((calc-command-flags nil)) (unwind-protect (save-excursion (calc-select-buffer) body of function renumber stack clear Working message) realign cursor and window clear Inverse, Hyperbolic, and Keep Args flags update Emacs mode line))
The calc-select-buffer
function selects the `*Calculator*'
buffer if necessary, say, because the command was invoked from inside
the `*Calc Trail*' window.
You can call, for example, (calc-set-command-flag 'no-align)
to set
the above-mentioned command flags. The following command flags are
recognized by Calc routines:
renum-stack
calc-push
.
clear-message
no-align
position-point
calc-position-point-line
and
calc-position-point-column
to position the cursor after
this command finishes.
keep-flags
calc-inverse-flag
, calc-hyperbolic-flag
,
and calc-keep-args-flag
at the end of this command.
do-edit
hold-trail
Calc reserves a special prefix key, shift-Y, for user-written
extensions to Calc. There are no built-in commands that work with
this prefix key; you must call define-key
from Lisp (probably
from inside a calc-define
property) to add to it. Initially only
Y ? is defined; it takes help messages from a list of strings
(initially nil
) in the variable calc-Y-help-msgs
. All
other undefined keys except for Y are reserved for use by
future versions of Calc.
If you are writing a Calc enhancement which you expect to give to others, it is best to minimize the number of Y-key sequences you use. In fact, if you have more than one key sequence you should consider defining three-key sequences with a Y, then a key that stands for your package, then a third key for the particular command within your package.
Users may wish to install several Calc enhancements, and it is possible
that several enhancements will choose to use the same key. In the
example below, a variable inc-prec-base-key
has been defined
to contain the key that identifies the inc-prec
package. Its
value is initially "P"
, but a user can change this variable
if necessary without having to modify the file.
Here is a complete file, `inc-prec.el', which makes a Y P I command that increases the precision, and a Y P D command that decreases the precision.
;;; Increase and decrease Calc precision. Dave Gillespie, 5/31/91. ;;; (Include copyright or copyleft stuff here.) (defvar inc-prec-base-key "P" "Base key for inc-prec.el commands.") (put 'calc-define 'inc-prec '(progn (define-key calc-mode-map (format "Y%sI" inc-prec-base-key) 'increase-precision) (define-key calc-mode-map (format "Y%sD" inc-prec-base-key) 'decrease-precision) (setq calc-Y-help-msgs (cons (format "%s + Inc-prec, Dec-prec" inc-prec-base-key) calc-Y-help-msgs)) (defmath increase-precision (delta) "Increase precision by DELTA." (interactive "p") (setq calc-internal-prec (+ calc-internal-prec delta))) (defmath decrease-precision (delta) "Decrease precision by DELTA." (interactive "p") (setq calc-internal-prec (- calc-internal-prec delta))) )) ; end of calc-define property (run-hooks 'calc-check-defines)
To define a new computational command which takes and/or leaves arguments
on the stack, a special form of interactive
clause is used.
(interactive num tag)
where num is an integer, and tag is a string. The effect is
to pop num values off the stack, resimplify them by calling
calc-normalize
, and hand them to your function according to the
function's argument list. Your function may include &optional
and
&rest
parameters, so long as calling the function with num
parameters is legal.
Your function must return either a number or a formula in a form
acceptable to Calc, or a list of such numbers or formulas. These value(s)
are pushed onto the stack when the function completes. They are also
recorded in the Calc Trail buffer on a line beginning with tag,
a string of (normally) four characters or less. If you omit tag
or use nil
as a tag, the result is not recorded in the trail.
As an example, the definition
(defmath myfact (n) "Compute the factorial of the integer at the top of the stack." (interactive 1 "fact") (if (> n 0) (* n (myfact (1- n))) (and (= n 0) 1)))
is a version of the factorial function shown previously which can be used as a command as well as an algebraic function. It expands to
(defun calc-myfact () "Compute the factorial of the integer at the top of the stack." (interactive) (calc-slow-wrapper (calc-enter-result 1 "fact" (cons 'calcFunc-myfact (calc-top-list-n 1))))) (defun calcFunc-myfact (n) "Compute the factorial of the integer at the top of the stack." (if (math-posp n) (math-mul n (calcFunc-myfact (math-add n -1))) (and (math-zerop n) 1)))
The calc-slow-wrapper
function is a version of calc-wrapper
that automatically puts up a `Working...' message before the
computation begins. (This message can be turned off by the user
with an m w (calc-working
) command.)
The calc-top-list-n
function returns a list of the specified number
of values from the top of the stack. It resimplifies each value by
calling calc-normalize
. If its argument is zero it returns an
empty list. It does not actually remove these values from the stack.
The calc-enter-result
function takes an integer num and string
tag as described above, plus a third argument which is either a
Calculator data object or a list of such objects. These objects are
resimplified and pushed onto the stack after popping the specified number
of values from the stack. If tag is non-nil
, the values
being pushed are also recorded in the trail.
Note that if calcFunc-myfact
returns nil
this represents
"leave the function in symbolic form." To return an actual empty list,
in the sense that calc-enter-result
will push zero elements back
onto the stack, you should return the special value `'(nil)', a list
containing the single symbol nil
.
The interactive
declaration can actually contain a limited
Emacs-style code string as well which comes just before num and
tag. Currently the only Emacs code supported is `"p"', as in
(defmath foo (a b &optional c) (interactive "p" 2 "foo") body)
In this example, the command calc-foo
will evaluate the expression
`foo(a,b)' if executed with no argument, or `foo(a,b,n)' if
executed with a numeric prefix argument of n.
The other code string allowed is `"m"' (unrelated to the usual `"m"'
code as used with defun
). It uses the numeric prefix argument as the
number of objects to remove from the stack and pass to the function.
In this case, the integer num serves as a default number of
arguments to be used when no prefix is supplied.
Anywhere a parameter name can appear in the parameter list you can also use an argument qualifier. Thus the general form of a definition is:
(defmath name (param param... &optional param param... &rest param) body)
where each param is either a symbol or a list of the form
(qual param)
The following qualifiers are recognized:
For example,
(defmath foo (a (constp (not-matrixp b)) &optional (float c) &rest (integer d)) body)
expands to
(defun calcFunc-foo (a b &optional c &rest d) (and (math-matrixp b) (math-reject-arg b 'not-matrixp)) (or (math-constp b) (math-reject-arg b 'constp)) (and c (setq c (math-check-float c))) (setq d (mapcar 'math-check-integer d)) body)
which performs the necessary checks and conversions before executing the body of the function.
This section includes some Lisp programming examples on a larger scale. These programs make use of some of the Calculator's internal functions; see section Calculator Internals.
Calc does not include a built-in function for counting the number of "one" bits in a binary integer. It's easy to invent one using b u to convert the integer to a set, and V # to count the elements of that set; let's write a function that counts the bits without having to create an intermediate set.
(defmath bcount ((natnum n)) (interactive 1 "bcnt") (let ((count 0)) (while (> n 0) (if (oddp n) (setq count (1+ count))) (setq n (lsh n -1))) count))
When this is expanded by defmath
, it will become the following
Emacs Lisp function:
(defun calcFunc-bcount (n) (setq n (math-check-natnum n)) (let ((count 0)) (while (math-posp n) (if (math-oddp n) (setq count (math-add count 1))) (setq n (calcFunc-lsh n -1))) count))
If the input numbers are large, this function involves a fair amount of arithmetic. A binary right shift is essentially a division by two; recall that Calc stores integers in decimal form so bit shifts must involve actual division.
To gain a bit more efficiency, we could divide the integer into n-bit chunks, each of which can be handled quickly because they fit into Lisp integers. It turns out that Calc's arithmetic routines are especially fast when dividing by an integer less than 1000, so we can set n = 9 bits and use repeated division by 512:
(defmath bcount ((natnum n)) (interactive 1 "bcnt") (let ((count 0)) (while (not (fixnump n)) (let ((qr (idivmod n 512))) (setq count (+ count (bcount-fixnum (cdr qr))) n (car qr)))) (+ count (bcount-fixnum n)))) (defun bcount-fixnum (n) (let ((count 0)) (while (> n 0) (setq count (+ count (logand n 1)) n (lsh n -1))) count))
Note that the second function uses defun
, not defmath
.
Because this function deals only with native Lisp integers ("fixnums"),
it can use the actual Emacs +
and related functions rather
than the slower but more general Calc equivalents which defmath
uses.
The idivmod
function does an integer division, returning both
the quotient and the remainder at once. Again, note that while it
might seem that `(logand n 511)' and `(lsh n -9)' are
more efficient ways to split off the bottom nine bits of n
,
actually they are less efficient because each operation is really
a division by 512 in disguise; idivmod
allows us to do the
same thing with a single division by 512.
A somewhat limited sine function could be defined as follows, using the well-known Taylor series expansion for @c{$\sin x$} `sin(x)':
(defmath mysin ((float (anglep x))) (interactive 1 "mysn") (setq x (to-radians x)) ; Convert from current angular mode. (let ((sum x) ; Initial term of Taylor expansion of sin. newsum (nfact 1) ; "nfact" equals "n" factorial at all times. (xnegsqr :"-(x^2)")) ; "xnegsqr" equals -x^2. (for ((n 3 100 2)) ; Upper limit of 100 is a good precaution. (working "mysin" sum) ; Display "Working" message, if enabled. (setq nfact (* nfact (1- n) n) x (* x xnegsqr) newsum (+ sum (/ x nfact))) (if (~= newsum sum) ; If newsum is "nearly equal to" sum, (break)) ; then we are done. (setq sum newsum)) sum))
The actual sin
function in Calc works by first reducing the problem
to a sine or cosine of a nonnegative number less than @c{$\pi \over 4$}
pi/4. This
ensures that the Taylor series will converge quickly. Also, the calculation
is carried out with two extra digits of precision to guard against cumulative
round-off in `sum'. Finally, complex arguments are allowed and handled
by a separate algorithm.
(defmath mysin ((float (scalarp x))) (interactive 1 "mysn") (setq x (to-radians x)) ; Convert from current angular mode. (with-extra-prec 2 ; Evaluate with extra precision. (cond ((complexp x) (mysin-complex x)) ((< x 0) (- (mysin-raw (- x))) ; Always call mysin-raw with x >= 0. (t (mysin-raw x)))))) (defmath mysin-raw (x) (cond ((>= x 7) (mysin-raw (% x (two-pi)))) ; Now x < 7. ((> x (pi-over-2)) (- (mysin-raw (- x (pi))))) ; Now -pi/2 <= x <= pi/2. ((> x (pi-over-4)) (mycos-raw (- x (pi-over-2)))) ; Now -pi/2 <= x <= pi/4. ((< x (- (pi-over-4))) (- (mycos-raw (+ x (pi-over-2))))) ; Now -pi/4 <= x <= pi/4, (t (mysin-series x)))) ; so the series will be efficient.
where mysin-complex
is an appropriate function to handle complex
numbers, mysin-series
is the routine to compute the sine Taylor
series as before, and mycos-raw
is a function analogous to
mysin-raw
for cosines.
The strategy is to ensure that x is nonnegative before calling
mysin-raw
. This function then recursively reduces its argument
to a suitable range, namely, plus-or-minus @c{$\pi \over 4$}
pi/4. Note that each
test, and particularly the first comparison against 7, is designed so
that small roundoff errors cannnot produce an infinite loop. (Suppose
we compared with `(two-pi)' instead; if due to roundoff problems
the modulo operator ever returned `(two-pi)' exactly, an infinite
recursion could result!) We use modulo only for arguments that will
clearly get reduced, knowing that the next rule will catch any reductions
that this rule misses.
If a program is being written for general use, it is important to code it carefully as shown in this second example. For quick-and-dirty programs, when you know that your own use of the sine function will never encounter a large argument, a simpler program like the first one shown is fine.
A later section (see section Calculator Internals) gives a full description of
Calc's internal Lisp functions. It's not hard to call Calc from
inside your programs, but the number of these functions can be daunting.
So Calc provides one special "programmer-friendly" function called
calc-eval
that can be made to do just about everything you
need. It's not as fast as the low-level Calc functions, but it's
much simpler to use!
It may seem that calc-eval
itself has a daunting number of
options, but they all stem from one simple operation.
In its simplest manifestation, `(calc-eval "1+2")' parses the
string "1+2"
as if it were a Calc algebraic entry and returns
the result formatted as a string: "3"
.
Since calc-eval
is on the list of recommended autoload
functions, you don't need to make any special preparations to load
Calc before calling calc-eval
the first time. Calc will be
loaded and initialized for you.
All the Calc modes that are currently in effect will be used when evaluating the expression and formatting the result.
calc-eval
If the input string parses to a list of expressions, Calc returns
the results separated by ", "
. You can specify a different
separator by giving a second string argument to calc-eval
:
`(calc-eval "1+2,3+4" ";")' returns "3;7"
.
The "separator" can also be any of several Lisp symbols which
request other behaviors from calc-eval
. These are discussed
one by one below.
You can give additional arguments to be substituted for
`$', `$$', and so on in the main expression. For
example, `(calc-eval "$/$$" nil "7" "1+1")' evaluates the
expression "7/(1+1)"
to yield the result "3.5"
(assuming Fraction mode is not in effect). Note the nil
used as a placeholder for the item-separator argument.
If calc-eval
encounters an error, it returns a list containing
the character position of the error, plus a suitable message as a
string. Note that `1 / 0' is not an error by Calc's
standards; it simply returns the string "1 / 0"
which is the
division left in symbolic form. But `(calc-eval "1/")' will
return the list `(2 "Expected a number")'.
If you bind the variable calc-eval-error
to t
using a let
form surrounding the call to calc-eval
,
errors instead call the Emacs error
function which aborts
to the Emacs command loop with a beep and an error message.
If you bind this variable to the symbol string
, error messages
are returned as strings instead of lists. The character position is
ignored.
As a courtesy to other Lisp code which may be using Calc, be sure
to bind calc-eval-error
using let
rather than changing
it permanently with setq
.
Sometimes it is preferable to treat `1 / 0' as an error
rather than returning a symbolic result. If you pass the symbol
num
as the second argument to calc-eval
, results
that are not constants are treated as errors. The error message
reported is the first calc-why
message if there is one,
or otherwise "Number expected."
A result is "constant" if it is a number, vector, or other object that does not include variables or function calls. If it is a vector, the components must themselves be constants.
If the first argument to calc-eval
is a list whose first
element is a formula string, then calc-eval
sets all the
various Calc modes to their default values while the formula is
evaluated and formatted. For example, the precision is set to 12
digits, digit grouping is turned off, and the normal language
mode is used.
This same principle applies to the other options discussed below. If the first argument would normally be x, then it can also be the list `(x)' to use the default mode settings.
If there are other elements in the list, they are taken as
variable-name/value pairs which override the default mode
settings. Look at the documentation at the front of the
`calc.el' file to find the names of the Lisp variables for
the various modes. The mode settings are restored to their
original values when calc-eval
is done.
For example, `(calc-eval '("$+$$" calc-internal-prec 8) 'num a b)' computes the sum of two numbers, requiring a numeric result, and using default mode settings except that the precision is 8 instead of the default of 12.
It's usually best to use this form of calc-eval
unless your
program actually considers the interaction with Calc's mode settings
to be a feature. This will avoid all sorts of potential "gotchas";
consider what happens with `(calc-eval "sqrt(2)" 'num)'
when the user has left Calc in symbolic mode or no-simplify mode.
As another example, `(equal (calc-eval '("$<$$") nil a b) "1")'
checks if the number in string a is less than the one in
string b. Without using a list, the integer 1 might
come out in a variety of formats which would be hard to test for
conveniently: "1"
, "8#1"
, "00001"
. (But
see "Predicates" mode, below.)
Normally all input and output for calc-eval
is done with strings.
You can do arithmetic with, say, `(calc-eval "$+$$" nil a b)'
in place of `(+ a b)', but this is very inefficient since the
numbers must be converted to and from string format as they are passed
from one calc-eval
to the next.
If the separator is the symbol raw
, the result will be returned
as a raw Calc data structure rather than a string. You can read about
how these objects look in the following sections, but usually you can
treat them as "black box" objects with no important internal
structure.
There is also a rawnum
symbol, which is a combination of
raw
(returning a raw Calc object) and num
(signalling
an error if that object is not a constant).
You can pass a raw Calc object to calc-eval
in place of a
string, either as the formula itself or as one of the `$'
arguments. Thus `(calc-eval "$+$$" 'raw a b)' is an
addition function that operates on raw Calc objects. Of course
in this case it would be easier to call the low-level math-add
function in Calc, if you can remember its name.
In particular, note that a plain Lisp integer is acceptable to Calc as a raw object. (All Lisp integers are accepted on input, but integers of more than six decimal digits are converted to "big-integer" form for output. See section Data Type Formats.)
When it comes time to display the object, just use `(calc-eval a)' to format it as a string.
It is an error if the input expression evaluates to a list of
values. The separator symbol list
is like raw
except that it returns a list of one or more raw Calc objects.
Note that a Lisp string is not a valid Calc object, nor is a list containing a string. Thus you can still safely distinguish all the various kinds of error returns discussed above.
If the separator symbol is pred
, the result of the formula is
treated as a true/false value; calc-eval
returns t
or
nil
, respectively. A value is considered "true" if it is a
non-zero number, or false if it is zero or if it is not a number.
For example, `(calc-eval "$<$$" 'pred a b)' tests whether one value is less than another.
As usual, it is also possible for calc-eval
to return one of
the error indicators described above. Lisp will interpret such an
indicator as "true" if you don't check for it explicitly. If you
wish to have an error register as "false", use something like
`(eq (calc-eval ...) t)'.
Variables in the formula passed to calc-eval
are not normally
replaced by their values. If you wish this, you can use the
evalv
function (see section Algebraic Manipulation). For example,
if 4 is stored in Calc variable a
(i.e., in Lisp variable
var-a
), then `(calc-eval "a+pi")' will return the
formula "a + pi"
, but `(calc-eval "evalv(a+pi)")'
will return "7.14159265359"
.
To store in a Calc variable, just use setq
to store in the
corresponding Lisp variable. (This is obtained by prepending
`var-' to the Calc variable name.) Calc routines will
understand either string or raw form values stored in variables,
although raw data objects are much more efficient. For example,
to increment the Calc variable a
:
(setq var-a (calc-eval "evalv(a+1)" 'raw))
If the separator symbol is push
, the formula argument is
evaluated (with possible `$' expansions, as usual). The
result is pushed onto the Calc stack. The return value is nil
(unless there is an error from evaluating the formula, in which
case the return value depends on calc-eval-error
in the
usual way).
If the separator symbol is pop
, the first argument to
calc-eval
must be an integer instead of a string. That
many values are popped from the stack and thrown away. A negative
argument deletes the entry at that stack level. The return value
is the number of elements remaining in the stack after popping;
`(calc-eval 0 'pop)' is a good way to measure the size of
the stack.
If the separator symbol is top
, the first argument to
calc-eval
must again be an integer. The value at that
stack level is formatted as a string and returned. Thus
`(calc-eval 1 'top)' returns the top-of-stack value. If the
integer is out of range, nil
is returned.
The separator symbol rawtop
is just like top
except
that the stack entry is returned as a raw Calc object instead of
as a string.
In all of these cases the first argument can be made a list in order to force the default mode settings, as described above. Thus `(calc-eval '(2 calc-number-radix 16) 'top)' returns the second-to-top stack entry, formatted as a string using the default instead of current display modes, except that the radix is hexadecimal instead of decimal.
It is, of course, polite to put the Calc stack back the way you found it when you are done, unless the user of your program is actually expecting it to affect the stack.
Note that you do not actually have to switch into the `*Calculator*'
buffer in order to use calc-eval
; it temporarily switches into
the stack buffer if necessary.
If the separator symbol is macro
, the first argument must be a
string of characters which Calc can execute as a sequence of keystrokes.
This switches into the Calc buffer for the duration of the macro.
For example, `(calc-eval "vx5\rVR+" 'macro)' pushes the
vector `[1,2,3,4,5]' on the stack and then replaces it
with the sum of those numbers. Note that `\r' is the Lisp
notation for the carriage-return, RET, character.
If your keyboard macro wishes to pop the stack, `\C-d' is safer than `\177' (the DEL character) because some installations may have switched the meanings of DEL and C-h. Calc always interprets C-d as a synonym for "pop-stack" regardless of key mapping.
If you provide a third argument to calc-eval
, evaluation
of the keyboard macro will leave a record in the Trail using
that argument as a tag string. Normally the Trail is unaffected.
The return value in this case is always nil
.
Finally, if the separator symbol is eval
, then the Lisp
eval
function is called on the first argument, which must
be a Lisp expression rather than a Calc formula. Remember to
quote the expression so that it is not evaluated until inside
calc-eval
.
The difference from plain eval
is that calc-eval
switches to the Calc buffer before evaluating the expression.
For example, `(calc-eval '(setq calc-internal-prec 17) 'eval)'
will correctly affect the buffer-local Calc precision variable.
An alternative would be `(calc-eval '(calc-precision 17) 'eval)'.
This is evaluating a call to the function that is normally invoked
by the p key, giving it 17 as its "numeric prefix argument."
Note that this function will leave a message in the echo area as
a side effect. Also, all Calc functions switch to the Calc buffer
automatically if not invoked from there, so the above call is
also equivalent to `(calc-precision 17)' by itself.
In all cases, Calc uses save-excursion
to switch back to
your original buffer when it is done.
As usual the first argument can be a list that begins with a Lisp expression to use default instead of current mode settings.
The result of calc-eval
in this usage is just the result
returned by the evaluated Lisp expression.
Here is a sample Emacs command that uses calc-eval
. Suppose
you have a document with lots of references to temperatures on the
Fahrenheit scale, say "98.6 F", and you wish to convert these
references to Centigrade. The following command does this conversion.
Place the Emacs cursor right after the letter "F" and invoke the
command to change "98.6 F" to "37 C". Or, if the temperature is
already in Centigrade form, the command changes it back to Fahrenheit.
(defun convert-temp () (interactive) (save-excursion (re-search-backward "[^-.0-9]\\([-.0-9]+\\) *\\([FC]\\)") (let* ((top1 (match-beginning 1)) (bot1 (match-end 1)) (number (buffer-substring top1 bot1)) (top2 (match-beginning 2)) (bot2 (match-end 2)) (type (buffer-substring top2 bot2))) (if (equal type "F") (setq type "C" number (calc-eval "($ - 32)*5/9" nil number)) (setq type "F" number (calc-eval "$*9/5 + 32" nil number))) (goto-char top2) (delete-region top2 bot2) (insert-before-markers type) (goto-char top1) (delete-region top1 bot1) (if (string-match "\\.$" number) ; change "37." to "37" (setq number (substring number 0 -1))) (insert number))))
Note the use of insert-before-markers
when changing between
"F" and "C", so that the character winds up before the cursor
instead of after it.
This section describes the Lisp functions defined by the Calculator that
may be of use to user-written Calculator programs (as described in the
rest of this chapter). These functions are shown by their names as they
conventionally appear in defmath
. Their full Lisp names are
generally gotten by prepending `calcFunc-' or `math-' to their
apparent names. (Names that begin with `calc-' are already in
their full Lisp form.) You can use the actual full names instead if you
prefer them, or if you are calling these functions from regular Lisp.
The functions described here are scattered throughout the various
Calc component files. Note that `calc.el' includes autoload
s
for only a few component files; when Calc wants to call an advanced
function it calls `(calc-extensions)' first; this function
autoloads `calc-ext.el', which in turn autoloads all the functions
in the remaining component files.
Because defmath
itself uses the extensions, user-written code
generally always executes with the extensions already loaded, so
normally you can use any Calc function and be confident that it will
be autoloaded for you when necessary. If you are doing something
special, check carefully to make sure each function you are using is
from `calc.el' or its components, and call `(calc-extensions)'
before using any function based in `calc-ext.el' if you can't
prove this file will already be loaded.
Integers are stored in either of two ways, depending on their magnitude. Integers less than one million in absolute value are stored as standard Lisp integers. This is the only storage format for Calc data objects which is not a Lisp list.
Large integers are stored as lists of the form `(bigpos d0 d1 d2 ...)' for positive integers 1000000 or more, or `(bigneg d0 d1 d2 ...)' for negative integers -1000000 or less. Each d is a base-1000 "digit," a Lisp integer from 0 to 999. The least significant digit is d0; the last digit, dn, which is always nonzero, is the most significant digit. For example, the integer -12345678 is stored as `(bigneg 678 345 12)'.
The distinction between small and large integers is entirely hidden from
the user. In defmath
definitions, the Lisp predicate integerp
returns true for either kind of integer, and in general both big and small
integers are accepted anywhere the word "integer" is used in this manual.
If the distinction must be made, native Lisp integers are called fixnums
and large integers are called bignums.
Fractions are stored as a list of the form, `(frac n d)' where n is an integer (big or small) numerator, d is an integer denominator greater than one, and n and d are relatively prime. Note that fractions where d is one are automatically converted to plain integers by all math routines; fractions where d is negative are normalized by negating the numerator and denominator.
Floating-point numbers are stored in the form, `(float mant exp)', where mant (the "mantissa") is an integer less than `10^p' in absolute value (p represents the current precision), and exp (the "exponent") is a fixnum. The value of the float is `mant * 10^exp'. For example, the number -3.14 is stored as `(float -314 -2) = -314*10^-2'. Other constraints are that the number 0.0 is always stored as `(float 0 0)', and, except for the 0.0 case, the rightmost base-10 digit of mant is always nonzero. (If the rightmost digit is zero, the number is rearranged by dividing mant by ten and incrementing exp.)
Rectangular complex numbers are stored in the form `(cplx re im)', where re and im are each real numbers, either integers, fractions, or floats. The value is `re + imi'. The im part is nonzero; complex numbers with zero imaginary components are converted to real numbers automatically.
Polar complex numbers are stored in the form `(polar r theta)', where r is a positive real value and theta is a real value or HMS form representing an angle. This angle is usually normalized to lie in the interval `(-180 .. 180)' degrees, or `(-pi .. pi)' radians, according to the current angular mode. If the angle is 0 the value is converted to a real number automatically. (If the angle is 180 degrees, the value is usually also converted to a negative real number.)
Hours-minutes-seconds forms are stored as `(hms h m s)', where h is an integer or an integer-valued float (i.e., a float with `exp >= 0'), m is an integer or integer-valued float in the range `[0 .. 60)', and s is any real number in the range `[0 .. 60)'.
Date forms are stored as `(date n)', where n is a real number that counts days since midnight on the morning of January 1, 1 AD. If n is an integer, this is a pure date form. If n is a fraction or float, this is a date/time form.
Modulo forms are stored as `(mod n m)', where m is a positive real number or HMS form, and n is a real number or HMS form in the range `[0 .. m)'.
Error forms are stored as `(sdev x sigma)', where x is the mean value and sigma is the standard deviation. Each component is either a number, an HMS form, or a symbolic object (a variable or function call). If sigma is zero, the value is converted to a plain real number. If sigma is negative or complex, it is automatically normalized to be a positive real.
Interval forms are stored as `(intv mask lo hi)', where mask is one of the integers 0, 1, 2, or 3, and lo and hi are real numbers, HMS forms, or symbolic objects. The mask is a binary integer where 1 represents the fact that the interval is closed on the high end, and 2 represents the fact that it is closed on the low end. (Thus 3 represents a fully closed interval.) The interval `(intv 3 x x)' is converted to the plain number x; intervals `(intv mask x x)' for any other mask represent empty intervals. If hi is less than lo, the interval is converted to a standard empty interval by replacing hi with lo.
Vectors are stored as `(vec v1 v2 ...)', where v1 is the first element of the vector, v2 is the second, and so on. An empty vector is stored as `(vec)'. A matrix is simply a vector where all v's are themselves vectors of equal lengths. Note that Calc vectors are unrelated to the Emacs Lisp "vector" type, which is generally unused by Calc data structures.
Variables are stored as `(var name sym)', where
name is a Lisp symbol whose print name is used as the visible name
of the variable, and sym is a Lisp symbol in which the variable's
value is actually stored. Thus, `(var pi var-pi)' represents the
special constant `pi'. Almost always, the form is `(var
v var-v)'. If the variable name was entered with #
signs (which are converted to hyphens internally), the form is
`(var u v)', where u is a symbol whose name
contains #
characters, and v is a symbol that contains
-
characters instead. The value of a variable is the Calc
object stored in its sym symbol's value cell. If the symbol's
value cell is void or if it contains nil
, the variable has no
value. Special constants have the form `(special-const
value)' stored in their value cell, where value is a formula
which is evaluated when the constant's value is requested. Variables
which represent units are not stored in any special way; they are units
only because their names appear in the units table. If the value
cell contains a string, it is parsed to get the variable's value when
the variable is used.
A Lisp list with any other symbol as the first element is a function call.
The symbols +
, -
, *
, /
, %
, ^
,
and |
represent special binary operators; these lists are always
of the form `(op lhs rhs)' where lhs is the
sub-formula on the lefthand side and rhs is the sub-formula on the
right. The symbol neg
represents unary negation; this list is always
of the form `(neg arg)'. Any other symbol func represents a
function that would be displayed in function-call notation; the symbol
func is in general always of the form `calcFunc-name'.
The function cell of the symbol func should contain a Lisp function
for evaluating a call to func. This function is passed the remaining
elements of the list (themselves already evaluated) as arguments; such
functions should return nil
or call reject-arg
to signify
that they should be left in symbolic form, or they should return a Calc
object which represents their value, or a list of such objects if they
wish to return multiple values. (The latter case is allowed only for
functions which are the outer-level call in an expression whose value is
about to be pushed on the stack; this feature is considered obsolete
and is not used by any built-in Calc functions.)
The functions described here are used in implementing interactive Calc commands. Note that this list is not exhaustive! If there is an existing command that behaves similarly to the one you want to define, you may find helpful tricks by checking the source code for that command.
calc-command-flags
, unless it is already
there. See section Defining New Simple Commands.
calc-record-undo
, so the kinds of undo records
you might need to create take the form `(set sym value)',
which says that the Lisp variable sym was changed and had previously
contained value; `(store var value)' which says that
the Calc variable var (a string which is the name of the symbol that
contains the variable's value) was stored and its previous value was
value (either a Calc data object, or nil
if the variable was
previously void); or `(eval undo redo args ...)',
which means that to undo requires calling the function `(undo
args ...)' and, if the undo is later redone, calling
`(redo args ...)'.
calc-why
);
if the message string begins with a `*', it is considered important
enough to display even if the user doesn't type w. If one or more
args are present, the displayed message will be of the form,
`msg: arg1, arg2, ...', where the arguments are
formatted on the assumption that they are either strings or Calc objects of
some sort. If msg is a symbol, it is the name of a Calc predicate
(such as integerp
or numvecp
) which the arguments did not
satisfy; it is expanded to a suitable string such as "Expected an
integer." The reject-arg
function calls calc-record-why
automatically; see section Predicates.
The functions described here perform various operations on the Calc stack and trail. They are to be used in interactive Calc commands.
The stack elements are pushed without any sub-formula selections.
You can give an optional third argument to this function, which must
be a list the same size as vals of selections. Each selection
must be eq
to some sub-formula of the corresponding formula
in vals, or nil
if that formula should have no selection.
If any stack elements contain selections, and selections have not
been disabled by the j e (calc-enable-selections
) command,
this function returns the selected portions rather than the entire
stack elements. It can be given a third "selection-mode" argument
which selects other behaviors. If it is the symbol t
, then
a selection in any of the requested stack elements produces an
"illegal operation on selections" error. If it is the symbol full
,
the whole stack entry is always returned regardless of selections.
If it is the symbol sel
, the selected portion is always returned,
or nil
if there is no selection. (This mode ignores the j e
command.) If the symbol is entry
, the complete stack entry in
list form is returned; the first element of this list will be the whole
formula, and the third element will be the selection (or nil
).
calc-top-list
. The return
value of calc-pop-stack
is uninteresting.
If there are any selected sub-formulas among the popped elements, and
j e has not been used to disable selections, this produces an
error without changing the stack. If you supply an optional third
argument of t
, the stack elements are popped even if they
contain selections.
calc-top-list
, except that it calls
calc-normalize
on the values that it takes from the stack. They
are also passed through check-complete
, so that incomplete
objects will be rejected with an error message. All computational
commands should use this in preference to calc-top-list
; the only
standard Calc commands that operate on the stack without normalizing
are stack management commands like calc-enter
and calc-roll-up
.
This function accepts the same optional selection-mode argument as
calc-top-list
.
calc-top-list-n
in which only
a single element of the stack is taken and returned, rather than a list
of elements. This also accepts an optional selection-mode argument.
nil
, the normalized objects are also recorded in the trail.
A typical stack-based computational command would take the form,
(calc-enter-result n tag (cons 'calcFunc-func (calc-top-list-n n)))
If any of the n stack elements replaced contain sub-formula
selections, and selections have not been disabled by j e,
this function takes one of two courses of action. If n is
equal to the number of elements in vals, then each element of
vals is spliced into the corresponding selection; this is what
happens when you use the TAB key, or when you use a unary
arithmetic operation like sqrt
. If vals has only one
element but n is greater than one, there must be only one
selection among the top n stack elements; the element from
vals is spliced into that selection. This is what happens when
you use a binary arithmetic operation like +. Any other
combination of n and vals is an error when selections
are present.
nil
, this uses calc-enter-result
as outlined above. Otherwise, it maps the function over several stack
elements; see section Numeric Prefix Arguments. For example,
(defun calc-zeta (arg) (interactive "P") (calc-unary-op "zeta" 'calcFunc-zeta arg))
calc-unary-op
. The optional ident and unary
arguments specify the behavior when the prefix argument is zero or
one, respectively. If the prefix is zero, the value ident
is pushed onto the stack, if specified, otherwise an error message
is displayed. If the prefix is one, the unary function unary
is applied to the top stack element, or, if unary is not
specified, nothing happens. When the argument is two or more,
the binary function func is reduced across the top arg
stack elements; when the argument is negative, the function is
mapped between the next-to-top -arg stack elements and the
top element.
*Calculator*
buffer and reformat its contents from memory.
This must be called after changing any parameter, such as the current
display radix, which might change the appearance of existing stack
entries. (During a keyboard macro invoked by the X key, refreshing
is suppressed, but a flag is set so that the entire stack will be refreshed
rather than just the top few elements when the macro finishes.)
The functions described here are predicates, that is, they return a
true/false value where nil
means false and anything else means
true. These predicates are expanded by defmath
, for example,
from zerop
to math-zerop
. In many cases they correspond
to native Lisp functions by the same name, but are extended to cover
the full range of Calc data types.
defmath
, the expression
`(= x 0)' will automatically be converted to `(math-zerop x)',
and `(/= x 0)' will be converted to `(not (math-zerop x))'.
defmath
, the expression
`(< x 0)' will automatically be converted to `(math-negp x)',
and `(>= x 0)' will be converted to `(not (math-negp x))'.
(- x)
.
num-integerp
if it is integerp
or
messy-integerp
(but it is never both at once).
vec
).
constp
below.)
objectp
).
objectp
types except error forms
and intervals.
constp
.
negp
. In
defmath
, the expression `(< x y)' will automatically be
converted to `(lessp x y)'; expressions involving >
, <=
,
and >=
are similarly converted in terms of lessp
.
lessp
. But whereas lessp
considers
other types of objects to be unordered, beforep
puts any two
objects into a definite, consistent order. The beforep
function is used by the V S vector-sorting command, and also
by a s to put the terms of a product into canonical order:
This allows `x y + y x' to be simplified easily to `2 x y'.
equal
predicate; it returns true if
x and y are structurally identical. This is the usual way
to compare numbers for equality, but note that equal
will treat
0 and 0.0 as different.
equal
, or because their difference is zerop
. In
defmath
, the expression `(= x y)' will automatically be
converted to `(math-equal x y)'.
defmath
in place of the more general math-equal
whenever possible.
with-extra-prec
to evaluate the
series with 2 extra digits of precision, then use nearly-equal
to decide when the series has converged; this guards against cumulative
error in the series evaluation without doing extra work which would be
lost when the result is rounded back down to the current precision.
In defmath
, this can be written `(~= x y)'.
The x and y can be numbers of any kind, including complex.
nearly-equal
to y itself, to within the current precision, in other words,
if adding x to y would have a negligible effect on y
due to roundoff error. X may be a real or complex number, but
y must be real.
normalize
will trap. The net effect is that the
function call which led here will be left in symbolic form.
normalize
to leave the formula in symbolic form, with the message
"Inexact result." (This function has no effect when not in Symbolic Mode.)
Note that if your function calls `(sin 5)' in Symbolic Mode, the
sin
function will call inexact-value
, which will cause your
function to be left unsimplified. You may instead wish to call
`(normalize (list 'calcFunc-sin 5))', which in Symbolic Mode will
return the formula `sin(5)' to your function.
The functions described here do the actual computational work of the
Calculator. In addition to these, note that any function described in
the main body of this manual may be called from Lisp; for example, if
the documentation refers to the calc-sqrt
[sqrt
] command,
this means calc-sqrt
is an interactive stack-based square-root
command and sqrt
(which defmath
expands to calcFunc-sqrt
)
is the actual Lisp function for taking square roots.
The functions math-add
, math-sub
, math-mul
,
math-div
, math-mod
, and math-neg
are not included
in this list, since defmath
allows you to write native Lisp
+
, -
, *
, /
, %
, and unary -
,
respectively, instead.
math-normalize
.)
Reduce the value val to standard form. For example, if val
is a fixnum, it will be converted to a bignum if it is too large, and
if val is a bignum it will be normalized by clipping off trailing
(i.e., most-significant) zero digits and converting to a fixnum if it is
small. All the various data types are similarly converted to their standard
forms. Variables are left alone, but function calls are actually evaluated
in formulas. For example, normalizing `(+ 2 (calcFunc-abs -4))' will
return 6.
If a function call fails, because the function is void or has the wrong
number of parameters, or because it returns nil
or calls
reject-arg
or inexact-result
, normalize
returns
the formula still in symbolic form.
If the current Simplification Mode is "none" or "numeric arguments
only," normalize
will act appropriately. However, the more
powerful simplification modes (like algebraic simplification) are
not handled by normalize
. They are handled by calc-normalize
,
which calls normalize
and possibly some other routines, such
as simplify
or simplify-units
. Programs generally will
never call calc-normalize
except when popping or pushing values
on the stack.
normalize
to simplify the result. This is what happens
when you press the = key interactively.
(math-normalize (let ((calc-internal-prec (+ calc-internal-prec n))) body))
The surrounding call to math-normalize
causes a floating-point
result to be rounded down to the original precision afterwards. This
is important because some arithmetic operations assume a number's
mantissa contains no more digits than the current precision allows.
reject-arg
.
reject-arg
if lo or hi is unsuitable.
make-intv
, except that if
lo is less than hi they are simply exchanged, and the
bits of mask are swapped accordingly.
makemod
, the algebraic version of this function.
reject-arg
.
scale-int
, except that a right shift rounds to the nearest
integer rather than truncating.
quotient
function, otherwise it computes
`floor(x/y)'. Thus the result is well-defined but
slower than for quotient
.
quotient
, this works only for
integer arguments and is not well-defined for negative arguments.
For a more well-defined result, use `(% x y)'.
car
is `(quotient x y)' and whose cdr
is `(imod x y)'.
defmath
code, this can
also be written `(^ x y)' or
`(expt x y)'.
two-pi
,
pi-over-2
, pi-over-4
, pi-over-180
, sqrt-two-pi
,
e
, sqrt-e
, ln-2
, and ln-10
. Each function
returns a floating-point value in the current precision, and each uses
caching so that all calls after the first are essentially free.
defun
or
defvar
, defines a new cached constant analogous to pi
, etc.
It defines a function func
which returns the requested value;
if initial is non-nil
it must be a `(float ...)'
form which serves as an initial value for the cache. If func
is called when the cache is empty or does not have enough digits to
satisfy the current precision, the Lisp expression form is evaluated
with the current precision increased by four, and the result minus its
two least significant digits is stored in the cache. For example,
calling `(pi)' with a precision of 30 computes `pi' to 34
digits, rounds it down to 32 digits for future use, then rounds it
again to 30 digits for use in the present request.half-circle
and quarter-circle
.
nil
.
nil
if
there is no solution, or if any of the arguments are not integers.
deg
or rad
. Otherwise, the current angular mode is used. If a
is already an HMS form it is returned as-is.
to-radians
, except that in Symbolic Mode a degrees to
radians conversion yields a formula like `a*pi/180'.
from-radians
, except that in Symbolic Mode a radians to
degrees conversion yields a formula like `a*180/pi'.
prime-test
returns "maybe,"
you can call it again with the same n to get a greater certainty;
prime-test
remembers where it left off.
frac
, and can be rather slow.
nil
.
The functions described here perform various operations on vectors and matrices.
reject-arg
.
defmath
does not expand function names everywhere,
just where they are in the function position of a Lisp expression.
mrow
.
(See section Extracting Vector Elements.)
copy-sequence
over the rows of m; in Lisp terms, each
element of the result matrix will be eq
to the corresponding
element of m, but none of the cons
cells that make up
the structure of the matrix will be eq
. If m is a plain
vector, this is the same as copy-sequence
.
The functions described here operate on symbolic formulas in the Calculator.
calc-selection-cache-num
contains the number of
the stack entry involved (equal to num if you specified it);
calc-selection-cache-entry
contains the stack entry as a
list (such as calc-top-list
would return with entry
as the selection mode); and calc-selection-cache-comp
contains
a special "tagged" composition (see section I/O and Formatting Functions)
which allows Calc to relate cursor positions in the buffer with
their corresponding sub-formulas.
A slight complication arises in the selection mechanism because
formulas may contain small integers. For example, in the vector
`[1, 2, 1]' the first and last elements are eq
to each
other; selections are recorded as the actual Lisp object that
appears somewhere in the tree of the whole formula, but storing
1
would falsely select both 1
's in the vector. So
calc-prepare-selection
also checks the stack entry and
replaces any plain integers with "complex number" lists of the form
`(cplx n 0)'. This list will be displayed the same as a
plain n and the change will be completely invisible to the
user, but it will guarantee that no two sub-formulas of the stack
entry will be eq
to each other. Next time the stack entry
is involved in a computation, calc-normalize
will replace
these lists with plain numbers again, again invisibly to the user.
setcar
to modify
the formula in-place.
calc-prepare-selection
has been
called already. If the cursor is not actually on any part of the
formula, this returns nil
.
eq
to some sub-formula
of the stack element, or nil
to unselect the formula.
The stack element's appearance in the Calc buffer is adjusted
to reflect the new selection.
calc-find-nth-part
with
n equal to four will return `d'.
eq
to the `c+1' term of expr, then this function
will return `(c+1)*d'. If part turns out not to be a
sub-formula of expr, the function returns nil
. If
part is eq
to expr, the function returns t
.
This function does not take associativity into account.
calc-find-parent-formula
, except that
(unless j b has been used) it continues widening the selection
to contain a complete level of the formula. Given `a' from
`((a + b) - c) + d', calc-find-parent-formula
will
return `a + b' but calc-find-assoc-parent-formula
will
return the whole expression.
nil
.
If part is eq
to expr, it returns t
. This
function does not take associativity into account.
eq
to old replaced by new.
calc-simplify
) command uses. This
always returns a copy of the expression; the structure expr points
to remains unchanged in memory.
More precisely, here is what simplify
does: The expression is
first normalized and evaluated by calling normalize
. If any
AlgSimpRules
have been defined, they are then applied. Then
the expression is traversed in a depth-first, bottom-up fashion; at
each level, any simplifications that can be made are made until no
further changes are possible. Once the entire formula has been
traversed in this way, it is compared with the original formula (from
before the call to normalize
) and, if it has changed,
the entire procedure is repeated (starting with normalize
)
until no further changes occur. Usually only two iterations are
needed: one to simplify the formula, and another to verify that no
further simplifications were possible.
math-living-dangerously
to t
(using a let
form) and calling simplify
.
Dangerous simplification rules are written to check this variable
before taking any action.
math-simplifying-units
to t
while calling simplify
.
defun
or defmath
. If funcs is a symbol
(like +
or calcFunc-sqrt
), this simplification rule is
applied to the formulas which are calls to the specified function. Or,
funcs can be a list of such symbols; the rule applies to all
functions on the list. The body is written like the body of a
function with a single argument called expr
. The body will be
executed with expr
bound to a formula which is a call to one of
the functions funcs. If the function body returns nil
, or
if it returns a result equal
to the original expr
, it is
ignored and Calc goes on to try the next simplification rule that applies.
If the function body returns something different, that new formula is
substituted for expr in the original formula.
At each point in the formula, rules are tried in the order of the
original calls to math-defsimplify
; the search stops after the
first rule that makes a change. Thus later rules for that same
function will not have a chance to trigger until the next iteration
of the main simplify
loop.
Note that, since defmath
is not being used here, body must
be written in true Lisp code without the conveniences that defmath
provides. If you prefer, you can have body simply call another
function (defined with defmath
) which does the real work.
The arguments of a function call will already have been simplified before any rules for the call itself are invoked. Since a new argument list is consed up when this happens, this means that the rule's body is allowed to rearrange the function's arguments destructively if that is convenient. Here is a typical example of a simplification rule:
(math-defsimplify calcFunc-arcsinh (or (and (math-looks-negp (nth 1 expr)) (math-neg (list 'calcFunc-arcsinh (math-neg (nth 1 expr))))) (and (eq (car-safe (nth 1 expr)) 'calcFunc-sinh) (or math-living-dangerously (math-known-realp (nth 1 (nth 1 expr)))) (nth 1 (nth 1 expr)))))
This is really a pair of rules written with one math-defsimplify
for convenience; the first replaces `arcsinh(-x)' with
`-arcsinh(x)', and the second, which is safe only for real `x',
replaces `arcsinh(sinh(x))' with `x'.
nil
.
For example, if called on `6x + 9y + 12z', it would return 3, since
3 is a common factor of all the terms.
(math-defsimplify calcFunc-sqrt (let ((fac (math-common-constant-factor (nth 1 expr)))) (and fac (not (eq fac 1)) (math-mul (math-normalize (list 'calcFunc-sqrt fac)) (math-normalize (list 'calcFunc-sqrt (math-cancel-common-factor (nth 1 expr) fac)))))))
common-constant-factor
. Note that the standard
gcd
function uses the LCM to combine the denominators.
equal
to
expr, apply func again until eventually it does return
expr with no changes. Then, if expr is a function call,
recursively apply func to each of the arguments. This keeps going
until no changes occur anywhere in the expression; this final expression
is returned by map-tree
. Note that, unlike simplification rules,
func functions may not make destructive changes to
expr. If a third argument many is provided, it is an
integer which says how many times func may be applied; the
default, as described above, is infinitely many times.
compile-rules
calls
for that same variable can return immediately. If there are problems
with the rules, this function calls error
with a suitable
message.
nil
if no rules
matched, or if the only rules that matched did not actually change
the expression. The heads argument is optional; if is given,
it should be a list of all function names that (may) appear in
expr. The rewrite compiler tags each rule with the
rarest-looking function name in the rule; if you specify heads,
apply-rewrites
can use this information to narrow its search
down to just a few rules in the rule set.
apply-rewrites
, as discussed above.
map-tree
to apply the
rules throughout expr up to many (default infinity)
times.
nil
) match any of the patterns in pat.
nil
, the presence of undifferentiable
functions in expr instead cancels the whole differentiation, and
deriv
returns nil
instead.
Derivatives of an n-argument function can be defined by
adding a math-derivative-n
property to the property list
of the symbol for the function's derivative, which will be the
function name followed by an apostrophe. The value of the property
should be a Lisp function; it is called with the same arguments as the
original function call that is being differentiated. It should return
a formula for the derivative. For example, the derivative of ln
is defined by
(put 'calcFunc-ln\' 'math-derivative-1 (function (lambda (u) (math-div 1 u))))
The two-argument log
function has two derivatives,
(put 'calcFunc-log\' 'math-derivative-2 ; d(log(x,b)) / dx (function (lambda (x b) ... ))) (put 'calcFunc-log\'2 'math-derivative-2 ; d(log(x,b)) / db (function (lambda (x b) ... )))
deriv
, except that variables other than var are not
assumed to be constant with respect to var.
math-defsimplify
.
The main difference is that here body is the body of a function
with a single argument u
which is bound to the argument to the
function being integrated, not the function call itself. Also, the
variable of integration is available as math-integ-var
. If
evaluation of the integral requires doing further integrals, the body
should call `(math-integral x)' to find the integral of
x with respect to math-integ-var
; this function returns
nil
if the integral could not be done. Some examples:
(math-defintegral calcFunc-conj (let ((int (math-integral u))) (and int (list 'calcFunc-conj int)))) (math-defintegral calcFunc-cos (and (equal u math-integ-var) (math-from-radians-2 (list 'calcFunc-sin u))))
In the cos
example, we define only the integral of `cos(x) dx',
relying on the general integration-by-substitution facility to handle
cosines of more complicated arguments. An integration rule should return
nil
if it can't do the integral; if several rules are defined for
the same function, they are tried in order until one returns a non-nil
result.
math-defintegral
, except that body
is written as the body of a function with two arguments, u and
v.
nil
if the equation cannot be solved. The variable
var must appear at least once in lhs or rhs. Note that
the return value is a formula which does not contain var; this is
different from the user-level solve
and finv
functions,
which return a rearranged equation or a functional inverse, respectively.
If full is non-nil
, a full solution including dummy signs
and dummy integers will be produced. User-defined inverses are provided
as properties in a manner similar to derivatives:
(put 'calcFunc-ln 'math-inverse (function (lambda (x) (list 'calcFunc-exp x))))
This function can call `(math-solve-get-sign x)' to create a new arbitrary sign variable, returning x times that sign, and `(math-solve-get-int x)' to create a new arbitrary integer variable multiplied by x. These functions simply return x if the caller requested a non-"full" solution.
solve-for
takes an expression which will
typically be an equation or inequality. (If it is not, it will be
interpreted as the equation `expr = 0'.) It returns an
equation or inequality, or nil
if no solution could be found.
nil
value if var occurs as a subexpression
of expr.
This function might seem at first to be identical to
calc-find-sub-formula
. The key difference is that
expr-contains
uses equal
to test for matches, whereas
calc-find-sub-formula
uses eq
. In the formula
`f(a, a)', the two `a's will be equal
but not
eq
to each other.
nil
if there are no occurrences.
nil
if expr
contains only constants and functions with constant arguments.
lambda
forms specially with respect
to the dummy argument variables, so that the effect is always to return
expr evaluated at old = new.
expr-subst
, except that old and new
are lists of expressions to be substituted simultaneously. If one
list is shorter than the other, trailing elements of the longer list
are ignored.
nil
unless expr, when expanded out by a x
(calc-expand
), would consist of a sum of terms in which var
appears only raised to nonnegative integer powers. Note that if
var does not occur in expr, then expr is considered
a polynomial of degree 0.
nil
if expr is not a polynomial in var. If degree is
specified, this will not consider polynomials of degree higher than that
value. This is a good precaution because otherwise an input of
`(x+1)^1000' will cause a huge coefficient list to be built. If
loose is non-nil
, then a looser definition of a polynomial
is used in which coefficients are no longer required not to depend on
var, but are only required not to take the form of polynomials
themselves. For example, `sin(x) x^2 + cos(x)' is a loose
polynomial with coefficients `((calcFunc-cos x) 0 (calcFunc-sin
x))'. The result will never be nil
in loose mode, since any
expression can be interpreted as a "constant" loose polynomial.
mpb-top-expr
(a global name for
the original expr) is a suitable polynomial in subexpr.
The default predicate uses `(polynomial-p mpb-top-expr subexpr)';
you can use pred to specify additional conditions. Or, you could
have pred build up a list of every suitable subexpr that
is found.
is-polynomial
) in a linear combination with coefficient expressions
ac and bc. The result is a (not necessarily simplified)
polynomial list representing `ac a + bc b'.
calc-collect
) command uses is-polynomial
to turn an
expression into a coefficient list, then build-polynomial-expr
to turn the list back into an expression in regular form.
nil
.
t
, the entire
expression is searched. If sub-exprs is nil
, this
checks whether expr is directly a units expression.
nil
. If expr contains
two or more units, return the symbol wrong
.
nil
, use Calc's native base units. Otherwise, which
can specify a units system, which is a list of two-element lists,
where the first element is a Calc base symbol name and the second
is an expression to substitute for it.
The functions described here are responsible for parsing and formatting Calc numbers and formulas.
nil
.
nil
if the user presses Return with a blank line. If initial is
given, it is a string which the minibuffer will initially contain.
If prompt is given, it is the prompt string to use; the default
is "Algebraic:". If no-norm is t
, the formulas will
be returned exactly as parsed; otherwise, they will be passed through
calc-normalize
first.
To support the use of $ characters in the algebraic entry, use
let
to bind calc-dollar-values
to a list of the values
to be substituted for $, $$, and so on, and bind
calc-dollar-used
to 0. Upon return, calc-dollar-used
will have been changed to the highest number of consecutive $s
that actually appeared in the input.
calc-edit
command.
This is a simple format designed
mostly to guarantee the string is of a form that can be re-parsed by
read-expr
. Most formatting modes, such as digit grouping,
complex number format, and point character, are ignored to ensure the
result will be re-readable. The prec parameter is normally 0; if
you pass a large integer like 1000 instead, the expression will be
surrounded by parentheses unless it is a plain number or variable name.
format-flat-expr
(with prec equal to 0),
except that newlines will be inserted to keep lines down to the
specified width, and vectors that look like matrices or rewrite
rules are written in a pseudo-matrix format. The calc-edit
command uses this when only one stack entry is being edited.
read-expr
, for example, because of digit
grouping. Multi-line objects like matrices produce strings that
contain newline characters to separate the lines. The w
parameter, if given, is the target window size for which to format
the expressions. If w is omitted, the width of the Calculator
window is used.
math-compose-lang
property on the function's symbol,
whose value is a Lisp function that takes a and prec as
arguments and returns a composition. Here lang is a language
mode name, one of normal
, big
, c
, pascal
,
fortran
, tex
, eqn
, math
, or maple
.
In Big mode, Calc actually tries math-compose-big
first, then
tries math-compose-normal
. If this property does not exist,
or if the function returns nil
, the function is written in the
normal function-call notation for that language.
compose-expr
into
a string. Multi-line compositions convert to strings containing
newline characters. The target window size is given by w.
The format-value
function basically calls compose-expr
followed by composition-to-string
.
nil
.
nil
.
Hooks are variables which contain Lisp functions (or lists of functions)
which are called at various times. Calc defines a number of hooks
that help you to customize it in various ways. Calc uses the Lisp
function run-hooks
to invoke the hooks shown below. Several
other customization-related variables are also described here.
calc-mode-map
and similar variables have been set up.
calc-refresh
operation, set up the mode line display, then
evaluate any deferred calc-define
properties that have not
been evaluated yet.
calc-mode-hook
, this will normally happen only once
per Emacs session.
calc-quit
, generally because the user
presses q or M-# c while in Calc. The Calc buffer will
be the current buffer. The hook is called as the very first
step, before the Calc window is destroyed.
split-window
, set-window-buffer
,
and select-window
to create the Calc window.
calc-trail-buffer
will contain the buffer
which the window should use. Unlike calc-window-hook
,
this hook must not switch into the new window.
calc-edit
(and the other "edit"
commands) when the temporary editing buffer is being created.
The buffer will have been selected and set up to be in
calc-edit-mode
, but will not yet have been filled with
text. (In fact it may still have leftover text from a previous
calc-edit
command.)
calc-save-modes
command,
after Calc's own mode features have been inserted into the
`.emacs' buffer and just before the "End of mode settings"
message is inserted.
calc-reset
) has
reset all modes. The Calc buffer will be the current buffer.
nil
by default.
calc-mode-hook
. If the
Calc extensions package (`calc-ext.el') has not yet been
loaded, many of these keys will be bound to calc-missing-key
,
which is a command that loads the extensions package and
"retypes" the key. If your calc-mode-hook
rebinds
one of these keys, it will probably be overridden when the
extensions are loaded.
calcDigit-nondigit
which generally calls
exit-minibuffer
and "retypes" the key.
minibuffer-local-map
.
calc-store
and calc-recall
. This is
mostly a copy of minibuffer-local-completion-map
.
calc-edit
and other
temporary editing commands. It binds RET, LFD,
and C-c C-c to calc-edit-finish
.
calc-save-modes
.
Each entry is a list of two items, the variable (as a Lisp symbol)
and its default value. When modes are being saved, each variable
is compared with its default value (using equal
) and any
non-default variables are written out.
calc
and calc-quit
commands; see section Multiple Calculators.
Since calc-mode-hook
is called after this list has been
used the first time, your hook should add a variable to the
list and also call make-local-variable
itself.