[comp.sources.misc] v13i044: Emacs Calculator 1.01, part 18/19

daveg@csvax.caltech.edu (David Gillespie) (06/06/90)

Posting-number: Volume 13, Issue 44
Submitted-by: daveg@csvax.caltech.edu (David Gillespie)
Archive-name: gmcalc/part18

---- Cut Here and unpack ----
#!/bin/sh
# this is part 18 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file calc.texinfo continued
#
CurArch=18
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file calc.texinfo"
sed 's/^X//' << 'SHAR_EOF' >> calc.texinfo
XPairs of @kbd{Z `} and @kbd{Z '} characters may be nested.
X
XIf a keyboard macro halts due to an error in between a @kbd{Z `} and
X@kbd{Z '}, the saved values will be restored correctly even though
Xthe macro never reaches the @kbd{Z '} command.  Thus you can use
X@kbd{Z `} and @kbd{Z '} without having to worry about what happens
Xin exceptional conditions.
X
XIf you type @kbd{Z `} ``live'' (not in a keyboard macro), Calc puts
Xyou into a ``recursive edit.''  You can tell you are in a recursive
Xedit because there will be extra square brackets in the mode line,
Xas in @samp{[(Calculator)]}.  These brackets will go away when you
Xtype the matching @kbd{Z '} command.  The modes and quick variables
Xwill be saved and restored in just the same way as if actual keyboard
Xmacros were involved.
X
XThe modes saved by @kbd{Z `} and @kbd{Z '} are the current precision
Xand word size, the angular mode (Deg, Rad, or HMS), the simplification
Xmode, the matrix mapping direction, Algebraic mode, Symbolic mode,
XFraction mode, and the current complex mode (Polar or Rectangular).
XThe ten ``quick'' variables' values (or lack thereof) are also saved.
X
XMost mode-setting commands act as toggles, but with a numeric prefix
Xthey force the mode either on (positive prefix) or off (negative
Xor zero prefix).  Since you don't know what the environment might
Xbe when you invoke your macro, it's best to use prefix arguments
Xfor all mode-setting commands inside the macro.
X
XThe contents of the stack and trail, values of non-quick variables, and
Xother settings such as the various display modes, are @emph{not}
Xaffected by @kbd{Z `} and @kbd{Z '}.
X
X@node Queries in Macros, , Local Values in Macros, Keyboard Macros
X@subsection Queries in Keyboard Macros
X
X@kindex Z =
X@pindex calc-kbd-report
XThe @kbd{Z =} (@code{calc-kbd-report}) command displays an informative
Xmessage including the value on the top of the stack.  You are prompted
Xto enter a string.  That string, along with the top-of-stack value,
Xis displayed unless @kbd{m w} (@code{calc-working}) has been used
Xto turn such messages off.
X
X@kindex Z #
X@pindex calc-kbd-query
XThe @kbd{Z #} (@code{calc-kbd-query}) command displays a prompt message
X(which you enter during macro definition), then does an algebraic entry
Xwhich takes its input from the keyboard, even during macro execution.
XThis command allows your keyboard macros to accept numbers or formulas
Xas interactive input.  All the normal conventions of algebraic input,
Xincluding the use of @kbd{$} characters, are supported.
X@xref{Kbd Macro Query, , , emacs, the Emacs manual}, for a description of
X@kbd{C-x q} (@code{kbd-macro-query}), the standard Emacs way to accept
Xkeyboard input during a keyboard macro.  In particular, you can use
X@kbd{C-x q} to enter a recursive edit, which allows the user to perform
Xany Calculator operations interactively before pressing @kbd{C-M-c} to
Xreturn control to the keyboard macro.
X
X@node Algebraic Definitions, Lisp Definitions, Keyboard Macros, Programming
X@section Programming with Algebraic Formulas
X
X@kindex Z F
X@pindex calc-user-define-formula
X@cindex Programming with algebraic formulas
XAnother way to create a new Calculator command uses algebraic formulas.
XThe @kbd{Z F} (@code{calc-user-define-formula}) command stores the
Xformula at the top of the stack as the definition for a key.  This
Xcommand prompts for five things: The key, the command name, the function
Xname, the argument list, and the behavior of the command when given
Xnon-numeric arguments.
X
XFor example, suppose we type @kbd{' a+2b @key{RET}} to push the formula
X@samp{a + 2*b} onto the stack.  We now type @kbd{Z F m} to define this
Xformula on the @kbd{z m} key sequence.  The next prompt is for a command
Xname, beginning with @samp{calc-}, which should be the long (@kbd{M-x}) form
Xfor the new command.  If you simply press @key{RET}, a default name like
X@code{calc-User-m} will be constructed.  In our example, suppose we enter
X@kbd{spam @key{RET}} to define the new command as @code{calc-spam}.
X
XIf you want to give the formula a long-style name only, you can press
X@key{SPC} or @key{RET} when asked which single key to use.  For example
X@kbd{Z F @key{RET} spam @key{RET}} defines the new command as @code{calc-spam},
Xwith no keyboard equivalent.
X
XThe third prompt is for a function name.  The default is to use the same
Xname as the command name but with @samp{calcFunc-} in place of
X@samp{calc-}.  This is the name you will use if you want to enter your
Xnew function in an algebraic formula.  Suppose we enter @kbd{yow @key{RET}}.
XThen the new function can be invoked by pushing two numbers on the
Xstack and typing @kbd{z m} or @kbd{x spam}, or by entering the algebraic
Xformula @samp{yow(x,y)}.@refill
X
XThe fourth prompt is for the function's argument list.  This is used to
Xassociate values on the stack with the variables that appear in the formula.
XThe default is a list of all variables which appear in the formula, sorted
Xinto alphabetical order.  In our case, the default would be @samp{(a b)}.
XThis means that, when the user types @kbd{z m}, the Calculator will remove
Xtwo numbers from the stack, substitute these numbers for @samp{a} and
X@samp{b} (respectively) in the formula, then simplify the formula and
Xpush the result on the stack.  In other words, @kbd{10 @key{RET} 100 z m}
Xwould replace the 10 and 100 on the stack with the number 210, which is
X@samp{a + 2*b} with @samp{a=10} and @samp{b=100}.  Likewise, the formula
X@samp{yow(10, 100)} will be evaluated by substituting @samp{a=10} and
X@samp{b=100} in the definition.
X
XYou can rearrange the order of the names before pressing @key{RET} to
Xcontrol which stack positions go to which variables in the formula.  If
Xyou remove a variable from the argument list, that variable will be left
Xin symbolic form by the command.  Thus using an argument list of @samp{(b)}
Xfor our function would cause @kbd{10 z m} to replace the 10 on the stack
Xwith the formula @samp{a + 20}.  If we had used an argument list of
X@samp{(b a)}, the result with inputs 10 and 100 would have been 120.
X
XThe final prompt is a y-or-n question concerning what to do if symbolic
Xarguments are given to your function.  If you answer @kbd{y}, then
Xexecuting @kbd{z m} (using the original argument list @samp{(a b)}) with
Xarguments @samp{10} and @samp{x} will leave the function in symbolic
Xform, i.e., @samp{yow(10,x)}.  On the other hand, if you answer @kbd{n},
Xthen the formula will always be expanded, even for non-constant
Xarguments: @samp{10 + 2 * x}.  If you never plan to feed algebraic
Xformulas to your new function, it doesn't matter how you answer this
Xquestion.@refill
X
X@kindex Z G
X@pindex calc-get-user-defn
XOnce you have defined a formula on a key, you can retrieve this formula
Xwith the @kbd{Z G} (@code{calc-user-define-get-defn}) command.  Press a
Xkey, and this command pushes the formula that was used to define that
Xkey onto the stack.  You will get an error message if the key is undefined,
Xor if the key was not defined by a @kbd{Z F} command.@refill
X
XThe @kbd{Z E} (@code{calc-user-define-edit}) command on a key that has
Xbeen defined by a formula uses a variant of the @code{calc-edit} command
Xto edit the defining formula.  Press @kbd{C-c C-c} to finish editing and
Xstore the new formula back in the definition, or kill the formula-editing
Xbuffer with @kbd{C-x k} to cancel the edit.  (The argument list and other
Xproperties of the definition are unchanged; to adjust the argument list,
Xyou must use @kbd{Z G} to grab the formula onto the stack and then
Xre-execute the @kbd{Z F} command.)
X
XAs usual, the @kbd{Z P} command records your definition permanently.
XIn this case it will permanently record all three of the relevant
Xdefinitions: the key, the command, and the function.
X
XYou may find it useful to turn off the default simplifications with
X@kbd{m O} (@code{calc-no-simplify-mode}) when entering a formula to be
Xused as a function definition.  For example, the formula @samp{deriv(a^2,v)}
Xwhich might be used to define a new function @samp{dsqr(a,v)} will be
X``simplified'' to 0 immediately upon entry since @code{deriv} considers
X@samp{a} to be constant with respect to @samp{v}.  Turning off
Xdefault simplifications cures this problem: the definition will be stored
Xin symbolic form without ever activating the @code{deriv} function.  Press
X@kbd{m D} to turn the default simplifications back on afterwards.
X
X@node Lisp Definitions, , Algebraic Definitions, Programming
X@section Programming with Lisp
X
XThe Calculator can be programmed quite extensively in Lisp.  All you
Xdo is write a normal Lisp function definition, but with @code{defmath}
Xin place of @code{defun}.  This has the same form as @code{defun}, but it
Xautomagically replaces calls to standard Lisp functions like @code{+} and
X@code{zerop} with calls to the corresponding functions in Calc's own library.
XThus you can write natural-looking Lisp code which operates on all of the
Xstandard Calculator data types.  You can then use @kbd{Z D} if you wish to
Xbind your new command to a @kbd{z}-prefix key sequence.  The @kbd{Z E} command
Xwill not edit a Lisp-based definition.
X
XEmacs Lisp is described in the Emacs Lisp Reference Manual.  This section
Xassumes a familiarity with Lisp programming concepts; if you do not know
XLisp, you may find keyboard macros to be an easier way to program the
XCalculator.
X
X@menu
X* Defining Functions::
X* Defining Simple Commands::
X* Defining Stack Commands::
X* Argument Qualifiers::
X* Example Definitions::
X* Internals::
X@end menu
X
X@node Defining Functions, Defining Simple Commands, Lisp Definitions, Lisp Definitions
X@subsection Defining New Functions
X
X@findex defmath
XThe @code{defmath} function (actually a Lisp macro) is like @code{defun}
Xexcept that code in the body of the definition can make use of the full
Xrange of Calculator data types.  The prefix @samp{calcFunc-} is added
Xto the specified name to get the actual Lisp function name.  As a simple
Xexample,
X
X@example
X(defmath myfact (n)
X  (if (> n 0)
X      (* n (myfact (1- n)))
X    1))
X@end example
X
X@noindent
XThis actually expands to the code,
X
X@example
X(defun calcFunc-myfact (n)
X  (if (math-posp n)
X      (math-mul n (calcFunc-myfact (math-add n -1)))
X    1))
X@end example
X
X@noindent
XThis function can be used in algebraic expressions, e.g., @samp{myfact(5)}.
X
XThe @samp{myfact} function as it is defined above has the bug that an
Xexpression @samp{myfact(a+b)} will be simplified to 1 because the
Xformula @samp{a+b} is not considered to be @code{posp}.  A robust
Xfactorial function would be written along the following lines:
X
X@example
X(defmath myfact (n)
X  (if (> n 0)
X      (* (myfact (1- n)))
X    (if (= n 0)
X        1
X      nil)))    ; this could be simplified as: (and (= n 0) 1)
X@end example
X
XIf a function returns @code{nil}, it is left unsimplified by the Calculator
X(except that its arguments will be simplified).  Thus, @samp{myfact(a+1+2)}
Xwill be simplified to @samp{myfact(a+3)} but no further.  Beware that every
Xtime the Calculator reexamines this formula it will attempt to resimplify
Xit, so your function ought to detect the returning-@code{nil} case as
Xefficiently as possible.
X
XThe following standard Lisp functions are treated by @code{defmath}:
X@code{+}, @code{-}, @code{*}, @code{/}, @code{%}, @code{^} or
X@code{expt}, @code{=}, @code{<}, @code{>}, @code{<=}, @code{>=},
X@code{/=}, @code{1+}, @code{1-}, @code{logand}, @code{logior}, @code{logxor},
X@code{logandc2}, @code{lognot}.  Also, @code{~=} is an abbreviation for
X@code{math-nearly-equal}, which is useful in implementing Taylor series.@refill
X
XFor other functions @var{func}, if a function by the name
X@samp{calcFunc-@var{func}} exists it is used, otherwise if a function by the
Xname @samp{math-@var{func}} exists it is used, otherwise if @var{func} itself
Xis defined as a function it is used, otherwise @samp{calcFunc-@var{func}} is
Xused on the assumption that this is a to-be-defined math function.  Also, if
Xthe function name is quoted as in @samp{('integerp a)} the function name is
Xalways used exactly as written.@refill
X
XVariable names have @samp{var-} prepended to them unless they appear in
Xthe function's argument list or in an enclosing @code{let}, @code{let*},
X@code{for}, or @code{foreach} form,
Xor their names already contain a @samp{-} character.  Thus a reference to
X@samp{foo} is the same as a reference to @samp{var-foo}.@refill
X
XA few other Lisp extensions are available in @code{defmath} definitions:
X
X@itemize @bullet
X@item
XThe @code{elt} function accepts any number of index variables.
XNote that Calc vectors are stored as Lisp lists whose first
Xelement is the symbol @code{vec}; thus, @samp{(elt v 2)} yields
Xthe second element of vector @code{v}, and @samp{(elt m i j)}
Xyields one element of a Calc matrix.
X
X@item
XThe @code{setq} function has been extended to act like the Common
XLisp @code{setf} function.  (The name @code{setf} is recognized as
Xa synonym of @code{setq}.)  Specifically, the first argument of
X@code{setq} can be an @code{nth}, @code{elt}, @code{car}, or @code{cdr} form,
Xin which case the effect is to store into the specified
Xelement of a list.  Thus, @samp{(setq (elt m i j) x)} stores @code{x}
Xinto one element of a matrix.
X
X@item
XA @code{for} looping construct is available.  For example,
X@samp{(for ((i 0 10)) body)} executes @code{body} once for each
Xbinding of @code{i} from zero to 10.  This is like a @code{let}
Xform in that @code{i} is temporarily bound to the loop count
Xwithout disturbing its value outside the @code{for} construct.
XNested loops, as in @samp{(for ((i 0 10) (j 0 (1- i) 2)) body)},
Xare also available.  For each value of @code{i} from zero to 10,
X@code{j} counts from 0 to @samp{i-1} in steps of two.  Note that
X@code{for} has the same general outline as @code{let}, except
Xthat each element of the header is a list of three or four
Xthings, not just two.
X
X@item
XThe @code{foreach} construct loops over elements of a list.
XFor example, @samp{(foreach ((x (cdr v))) body)} executes
X@code{body} with @code{x} bound to each element of Calc vector
X@code{v} in turn.  The purpose of @code{cdr} here is to skip over
Xthe initial @code{vec} symbol in the vector.
X
X@item
XThe @code{break} function breaks out of the innermost enclosing
X@code{while}, @code{for}, or @code{foreach} loop.  If given a
Xvalue, as in @samp{(break x)}, this value is returned by the
Xloop.  (Lisp loops otherwise always return @code{nil}.)
X
X@item
XThe @code{return} function prematurely returns from the enclosing
Xfunction.  For example, @samp{(return (+ x y))} returns @samp{x+y}
Xas the value of a function.  You can use @code{return} anywhere
Xinside the body of the function.
X@end itemize
X
XNon-integer numbers (and extremely large integers) cannot be included
Xdirectly into a @code{defmath} definition.  This is because the Lisp
Xreader will fail to parse them long before @code{defmath} ever gets control.
XInstead, use the notation, @samp{:"3.1415"}.  In fact, any algebraic
Xformula can go between the quotes.  For example,
X
X@example
X(defmath sqexp (x)     ; sqexp(x) == sqrt(exp(x)) == exp(x*0.5)
X  (and (numberp x)
X       (exp :"x * 0.5")))
X@end example
X
Xexpands to
X
X@example
X(defun calcFunc-sqexp (x)
X  (and (math-numberp x)
X       (calcFunc-exp (math-mul x '(float 5 -1)))))
X@end example
X
XNote the use of @code{numberp} as a guard to ensure that the argument is
Xa number first, returning @code{nil} if not.  The exponential function
Xcould itself have been included in the expression, if we had preferred:
X@samp{:"exp(x * 0.5)"}.  As another example, the multiplication-and-recursion
Xstep of @code{myfact} could have been written
X
X@example
X:"n * myfact(n-1)"
X@end example
X
XIf a file named @file{.emacs} exists in your home directory, Emacs reads
Xand executes the Lisp forms in this file as it starts up.  While it may
Xseem like a good idea to put your favorite @code{defmath} commands here,
Xthis has the unfortunate side-effect that the entire Calculator must be
Xloaded in to process the @code{defmath} commands whether or not you will
Xactually use the Calculator!  A better effect can be had by writing
X
X@example
X(setq calc-defs '(
X  (defmath ... )
X  (defmath ... )
X))
X@end example
X
X@noindent
X@vindex calc-defs
XIf the @code{calc-defs} variable contains a list of Lisp expressions
Xwhen the Calculator is started, those expressions will be executed and the
X@code{calc-defs} variable cleared.  Thus your @code{defmath} commands will
Xbe executed only once, and only when the Calculator is first used.  If you
Xmust edit these definitions, simply re-execute the @code{setq} command
Xusing @kbd{C-x C-e} and restart the Calculator with @kbd{M-x calc}.
X
X@node Defining Simple Commands, Defining Stack Commands, Defining Functions, Lisp Definitions
X@subsection Defining New Simple Commands
X
X@findex interactive
XIf a @code{defmath} form contains an @code{interactive} clause, it defines
Xa Calculator command.  Actually such a @code{defmath} results in @emph{two}
Xfunction definitions:  One, a @samp{calcFunc-} function as was just described,
Xwith the @code{interactive} clause removed.  Two, a @samp{calc-} function
Xwith a suitable @code{interactive} clause and some sort of wrapper to make
Xthe command work in the Calc environment.
X
XIn the simple case, the @code{interactive} clause has the same form as
Xfor normal Emacs Lisp commands:
X
X@example
X(defmath increase-precision (delta)
X  "Increase precision by DELTA."     ; This is the "documentation string"
X  (interactive "p")                  ; Register this as a M-x-able command
X  (setq calc-internal-prec (+ calc-internal-prec delta)))
X@end example
X
XThis expands to the pair of definitions,
X
X@example
X(defun calc-increase-precision (delta)
X  "Increase precision by DELTA."
X  (interactive "p")
X  (calc-wrapper
X   (setq calc-internal-prec (math-add calc-internal-prec delta))))
X
X(defun calcFunc-increase-precision (delta)
X  "Increase precision by DELTA."
X  (setq calc-internal-prec (math-add calc-internal-prec delta)))
X@end example
X
X@noindent
Xwhere in this case the latter function would never really be used!  Note
Xthat since the Calculator stores small integers as plain Lisp integers,
Xthe @code{math-add} function will work just as well as the native
X@code{+} even when the intent is to operate on native Lisp integers.
X
X@findex calc-wrapper
XThe @samp{calc-wrapper} call invokes a macro which surrounds the body of
Xthe function with code that looks like this:
X
X@example
X  (let ((calc-command-flags nil))
X    (unwind-protect
X        (progn
X          (save-excursion
X            (calc-select-buffer)
X            @emph{body of function})
X          (calc-finish-command))
X      (calc-cleanup-command)))
X@end example
X
X@findex calc-select-buffer
XThe @code{calc-select-buffer} function selects the @samp{*Calculator*}
Xbuffer if necessary, say, because the command was invoked from inside
Xthe @samp{*Calc Trail*} window.
X
X@findex calc-finish-command
XThe @code{calc-finish-command} function recomputes the line numbers
Xfor all stack entries if they have been changed.
XAlso, if the @code{clear-message} flag is set
Xit executes @samp{(message "")} to clear any lingering ``Working'' message
Xout of the echo area.@refill
X
X@findex calc-cleanup-command
XThe @code{calc-cleanup-command} function normally aligns the stack window
Xso that the top element of the stack is visible at the
Xbottom of the window, and moves the cursor down to the bottom line.
XThis can be suppressed by setting the @code{no-align}
Xflag as described below.  Also, it clears the Inverse and Hyperbolic
Xflags (unless the @code{keep-flags} flag has been set), and updates the
Xdisplay of the mode line.@refill
X
X@findex calc-set-command-flag
XYou can call, for example, @code{(calc-set-command-flag 'no-align)} to set
Xthe above-mentioned command flags.
X
X@node Defining Stack Commands, Argument Qualifiers, Defining Simple Commands, Lisp Definitions
X@subsection Defining New Stack-Based Commands
X
XTo define a new computational command which takes and/or leaves arguments
Xon the stack, a special form of @code{interactive} clause is used.
X
X@example
X(interactive @var{num} @var{tag})
X@end example
X
X@noindent
Xwhere @var{num} is an integer, and @var{tag} is a string.  The effect is
Xto pop @var{num} values off the stack, resimplify them by calling
X@code{calc-normalize}, and hand them to your function according to the
Xfunction's argument list.  Your function may include @code{&optional} and
X@code{&rest} parameters, so long as calling the function with @var{num}
Xparameters is legal.
X
XYour function must return either a number or a formula in a form
Xacceptable to Calc, or a list of such numbers or formulas.  These value(s)
Xare pushed onto the stack when the function completes.  They are also
Xrecorded in the Calc Trail buffer on a line beginning with @var{tag},
Xa string of (normally) four characters or less.  If you omit @var{tag}
Xor use @code{nil} as a tag, the result is not recorded in the trail.
X
XAs an example, the definition
X
X@example
X(defmath myfact (n)
X  "Compute the factorial of the integer at the top of the stack."
X  (interactive 1 "fact")
X  (if (> n 0)
X      (* (myfact (1- n)))
X    (and (= n 0) 1)))
X@end example
X
X@noindent
Xis a version of the factorial function shown previously which can be used
Xas a command as well as an algebraic function.  It expands to
X
X@example
X(defun calc-myfact ()
X  "Compute the factorial of the integer at the top of the stack."
X  (interactive)
X  (calc-slow-wrapper
X   (calc-enter-result 1 "fact"
X     (cons 'calcFunc-myfact (calc-top-list-n 1)))))
X
X(defun calcFunc-myfact (n)
X  "Compute the factorial of the integer at the top of the stack."
X  (if (math-posp n)
X      (math-mul n (calcFunc-myfact (math-add n -1)))
X    (and (math-zerop n) 1)))
X@end example
X
X@findex calc-slow-wrapper
XThe @code{calc-slow-wrapper} function is a version of @code{calc-wrapper}
Xthat automatically puts up a @samp{Working...} message before the
Xcomputation begins.  (This message can be turned off by the user
Xwith a @kbd{m w} (@code{calc-working}) command.)
X
X@findex calc-top-list-n
XThe @code{calc-top-list-n} function returns a list of the specified number
Xof values from the top of the stack.  It resimplifies each value by
Xcalling @code{calc-normalize}.  If its argument is zero it returns an
Xempty list.  It does not actually remove these values from the stack.
X
X@findex calc-enter-result
XThe @code{calc-enter-result} function takes an integer @var{num} and string
X@var{tag} as described above, plus a third argument which is either a
XCalculator data object or a list of such objects.  These objects are
Xresimplified and pushed onto the stack after popping the specified number
Xof values from the stack.  If @var{tag} is non-@code{nil}, the values
Xbeing pushed are also recorded in the trail.
X
XNote that if @code{calcFunc-myfact} returns @code{nil} this represents
X``leave the function in symbolic form.''  To return an actual empty list,
Xin the sense that @code{calc-enter-result} will push zero elements back
Xonto the stack, you should return the special value @samp{'(nil)}, a list
Xcontaining the single symbol @code{nil}.
X
XThe @code{interactive} declaration can actually contain a limited
XEmacs-style code string as well which comes just before @var{num} and
X@var{tag}.  Currently only Emacs code supported is @samp{"p"}, as in
X
X@example
X(defmath foo (a b &optional c)
X  (interactive "p" 2 "foo")
X  @var{body})
X@end example
X
XIn this example, the command @code{calc-foo} will evaluate the expression
X@samp{foo(a,b)} if executed with no argument, or @samp{foo(a,b,n)} if
Xexecuted with a numeric prefix argument of @samp{n}.
X
XThe other code string allowed is @samp{"m"} (unrelated to the usual @samp{"m"}
Xcode as used with @code{defun}).  It uses the numeric prefix argument as the
Xnumber of objects to remove from the stack and pass to the function.
XIn this case, the integer @var{num} serves as a default number of
Xarguments to be used when no prefix is supplied.
X
X@node Argument Qualifiers, Example Definitions, Defining Stack Commands, Lisp Definitions
X@subsection Argument Qualifiers
X
XAnywhere a parameter name can appear in the parameter list you can also use
Xan @dfn{argument qualifier}.  Thus the general form of a definition is:
X
X@example
X(defmath @var{name} (@var{param} @var{param...}
X               &optional @var{param} @var{param...}
X               &rest @var{param})
X  @var{body})
X@end example
X
Xwhere each @var{param} is either a symbol or a list of the form
X
X@example
X(@var{qual} @var{param})
X@end example
X
XThe following qualifiers are recognized:
X
X@table @samp
X@item complete
X@findex complete
XThe argument must not be an incomplete vector, interval, or complex number.
X(This is rarely needed since the Calculator itself will never call your
Xfunction with an incomplete argument.  But there is nothing stopping your
Xown Lisp code from calling your function with an incomplete argument.)@refill
X
X@item integer
X@findex integer
XThe argument must be an integer.  If it is an integer-valued float
Xit will be accepted but converted to integer form.  Non-integers and
Xformulas are rejected.
X
X@item natnum
X@findex natnum
XLike @samp{integer}, but the argument must be non-negative.
X
X@item fixnum
X@findex fixnum
XLike @samp{integer}, but the argument must fit into a native Lisp integer,
Xwhich on most systems means less than 2^23 in absolute value.  The
Xargument is converted into Lisp-integer form if necessary.
X
X@item float
X@findex float
XThe argument is converted to floating-point format if it is a number or
Xvector.  If it is a formula it is left alone.  (The argument is never
Xactually rejected by this qualifier.)
X
X@item @var{pred}
XThe argument must satisfy predicate @var{pred}, which is one of the
Xstandard Calculator predicates.  @xref{Predicates}.
X
X@item not-@var{pred}
XThe argument must @emph{not} satisfy predicate @var{pred}.
X@end table
X
XFor example,
X
X@example
X(defmath foo (a (constp (not-matrixp b)) &optional (float c)
X              &rest (integer d))
X  @var{body})
X@end example
X
X@noindent
Xexpands to
X
X@example
X(defun calcFunc-foo (a b &optional c &rest d)
X  (and (math-matrixp b)
X       (math-reject-arg b 'not-matrixp))
X  (or (math-constp b)
X      (math-reject-arg b 'constp))
X  (and c (setq c (math-check-float c)))
X  (setq d (mapcar 'math-check-integer d))
X  @var{body})
X@end example
X
X@noindent
Xwhich performs the necessary checks and conversions before executing the
Xbody of the function.
X
X@node Example Definitions, Internals, Argument Qualifiers, Lisp Definitions
X@subsection Example Definitions
X
XThis section includes some Lisp programming examples on a larger scale.
XThese programs make use of many of the Calculator's internal functions
X(@pxref{Internals}).
X
X@menu
X* Sine Example::
X@end menu
X
X@node Sine Example, , Example Definitions, Example Definitions
X@subsubsection The Sine Function
X
XA somewhat limited sine function could be defined as follows, using the
Xwell-known Taylor series expansion for @samp{sin(x)}:
X
X@example
X(defmath mysin ((float (anglep x)))
X  (interactive 1 "mysn")
X  (setq x (to-radians x))    ; Convert from current angular mode.
X  (let ((sum x)              ; Initial term of Taylor expansion of sin.
X        newsum
X        (nfact 1)            ; "nfact" equals "n" factorial at all times.
X        (xnegsqr :"-(x^2)")) ; "xnegsqr" equals -x^2.
X    (for ((n 3 100 2))       ; Upper limit of 100 is a good precaution.
X         (working "mysin" sum)   ; Display "Working" message, if enabled.
X         (setq nfact (* nfact (1- n) n)
X               x (* x xnegsqr)
X               newsum (+ sum (/ x nfact)))
X         (if (~= newsum sum)     ; If newsum is "nearly equal to" sum,
X             (break))            ;  then we are done.
X         (setq sum newsum))
X    sum))
X@end example
X
XThe actual @code{sin} function in Calc works by first reducing the problem
Xto a sine or cosine of a nonnegative number less than @samp{pi/4}.  This
Xensures that the Taylor series will converge quickly.  Also, the calculation
Xis carried out with two extra digits of precision to guard against cumulative
Xround-off in @samp{sum}.  Finally, complex arguments are allowed and handled
Xby a separate algorithm.
X
X@example
X(defmath mysin ((float (scalarp x)))
X  (interactive 1 "mysn")
X  (setq x (to-radians x))    ; Convert from current angular mode.
X  (with-extra-prec 2         ; Evaluate with extra precision.
X    (cond ((complexp x)
X           (mysin-complex x))
X          ((< x 0)
X           (- (mysin-raw (- x)))    ; Always call mysin-raw with x >= 0.
X          (t (mysin-raw x))))))
X
X(defmath mysin-raw (x)
X  (cond ((>= x 7)
X         (mysin-raw (% x (two-pi))))     ; Now x < 7.
X        ((> x (pi-over-2))
X         (- (mysin-raw (- x (pi)))))     ; Now -pi/2 <= x <= pi/2.
X        ((> x (pi-over-4))
X         (mycos-raw (- x (pi-over-2))))  ; Now -pi/2 <= x <= pi/4.
X        ((< x (- (pi-over-4)))
X         (- (mycos-raw (+ x (pi-over-2)))))  ; Now -pi/4 <= x <= pi/4,
X        (t (mysin-series x))))           ; so the series will be efficient.
X@end example
X
X@noindent
Xwhere @code{mysin-complex} is an appropriate function to handle complex
Xnumbers, @code{mysin-series} is the routine to compute the sine Taylor
Xseries as before, and @code{mycos-raw} is a function analogous to
X@code{mysin-raw} for cosines.
X
XThe strategy is to ensure that @samp{x} is nonnegative before calling
X@code{mysin-raw}.  This function then recursively reduces its argument
Xto a suitable range, namely, plus-or-minus @samp{pi/4}.  Note that each
Xtest, and particularly the first comparison against 7, is designed so
Xthat small roundoff errors cannnot produce an infinite loop.  (Suppose
Xwe compared with @samp{(two-pi)} instead; if due to roundoff problems
Xthe modulo operator ever returned @samp{(two-pi)} exactly, an infinite
Xrecursion could result!)  We use modulo only for arguments that will
Xclearly get reduced, knowing that the next rule will catch any reductions
Xthat this rule misses.
X
XIf a program is being written for general use, it is important to code
Xit carefully as shown in this second example.  For quick-and-dirty programs,
Xwhen you know that your own use of the sine function will never encounter
Xa large argument, a simpler program like the first one shown is fine.
X
X@node Internals, , Example Definitions, Lisp Definitions
X@subsection Calculator Internals
X
XThis chapter describes the Lisp functions defined by the Calculator that
Xmay be of use to user-written Calculator programs (as described in the
Xrest of this chapter).  These functions are shown by their names as they
Xconventionally appear in @code{defmath}.  Their full Lisp names are
Xgenerally gotten by prepending @samp{calcFunc-} or @samp{math-} to their
Xapparent names.  (Names that begin with @samp{calc-} are already in
Xtheir full Lisp form.)  You can use the actual full names instead if you
Xprefer them, or if you are calling these functions from regular Lisp.
X
XLittle distinction is made here between functions in the main Calc
Xbody and functions in the extensions module.  Because @code{defmath}
Xitself is in the extensions, user-written code generally always
Xexecutes with the extensions already loaded, so this is not an issue.
XIf you are doing something special, check carefully to make sure each
Xfunction you are using is from the main body; be sure to call
X@samp{(calc-extensions)} before using any function from the extensions
Xpackage if you can't prove the extensions will already have been loaded.
X
X@menu
X* Data Type Formats::
X* Interactive Lisp Functions::
X* Stack Lisp Functions::
X* Predicates::
X* Computational Lisp Functions::
X* Vector Lisp Functions::
X* Symbolic Lisp Functions::
X* Formatting Lisp Functions::
X* Lisp Variables::
X* Hooks::
X@end menu
X
X@node Data Type Formats, Interactive Lisp Functions, Internals, Internals
X@subsubsection Data Type Formats
X
XIntegers are stored in either of two ways, depending on their magnitude.
XIntegers less than one million in absolute value are stored as standard
XLisp integers.  This is the only storage format for Calc data objects
Xwhich is not a Lisp list.
X
XLarge integers are stored as a list of the form @samp{(bigpos @var{d0}
X@var{d1} @var{d2} @dots{}} for positive integers 1000000 or more, or
X@samp{(bigneg @var{d0} @var{d1} @var{d2} @dots{}} for negative integers
X-1000000 or less.  Each @var{d} is a base-1000 ``digit,'' a Lisp integer
Xfrom 0 to 999.  The least significant digit is @var{d0}; the last digit,
X@var{dn}, which is always nonzero, is the most significant digit.  For
Xexample, the integer -12345678 is stored as @samp{(bigneg 678 345 12)}.
X
XThe distinction between small and large integers is entirely hidden from
Xthe user.  In @code{defmath} definitions, the Lisp predicate @code{integerp}
Xreturns true for either kind of integer, and in general both big and small
Xintegers are accepted anywhere the word ``integer'' is used in this manual.
XIf the distinction must be made, native Lisp integers are called @dfn{fixnums}
Xand large integers are called @dfn{bignums}.
X
XFractions are stored as a list of the form, @samp{(frac @var{n} @var{d})}
Xwhere @var{n} is an integer (big or small) numerator, @var{d} is an
Xinteger denominator greater than one, and @var{n} and @var{d} are relatively
Xprime.  Note that fractions where @var{d} is one are automatically converted
Xto plain integers by all math routines; fractions where @var{d} is negative
Xare normalized by negating the numerator and denominator.
X
XFloating-point numbers are stored in the form, @samp{(float @var{mant}
X@var{exp})}, where @var{mant} (the ``mantissa'') is an integer less than
X@samp{10^@var{p}} in absolute value (@var{p} represents the current
Xprecision), and @var{exp} (the ``exponent'') is a fixnum.  The value of
Xthe float is @samp{@var{mant} * 10^@var{exp}}.  For example, the number
X-3.14 is stored as @samp{(float -314 -2) = -314*10^-2}.  Other constraints
Xare that the number 0.0 is always stored as @samp{(float 0 0)}, and,
Xexcept for the 0.0 case, the rightmost base-10 digit of @var{mant} is
Xalways nonzero.  (If the rightmost digit is zero, the number is
Xrearranged by dividing @var{mant} by ten and incrementing @var{exp}.)@refill
X
XRectangular complex numbers are stored in the form @samp{(cplx @var{re}
X@var{im})}, where @var{re} and @var{im} are each real numbers, either
Xintegers, fractions, or floats.  The value is @samp{@var{re} + @var{im}i}.
XThe @var{im} part is nonzero; complex numbers with zero imaginary
Xcomponents are converted to real numbers automatically.@refill
X
XPolar complex numbers are stored in the form @samp{(polar @var{r}
X@var{theta})}, where @var{r} is a positive real value and @var{theta}
Xis a real value or HMS form representing an angle.  This angle is
Xusually normalized to lie in the interval @samp{(-180 .. 180)} degrees,
Xor @samp{(-pi .. pi)} radians, according to the current angular mode.
XIf the angle is 0 the value is converted to a real number automatically.
X(If the angle is 180 degrees, the value is usually also converted to a
Xnegative real number.)@refill
X
XHours-minutes-seconds forms are stored as @samp{(hms @var{h} @var{m}
X@var{s})}, where @var{h} is an integer or an integer-valued float (i.e.,
Xa float with @samp{@var{exp} >= 0}), @var{m} is an integer or integer-valued
Xfloat in the range @samp{[0 .. 60)}, and @var{s} is any real number in the
Xrange @samp{[0 .. 60)}.@refill
X
XModulo forms are stored as @samp{(mod @var{n} @var{m})}, where @var{m} is a
Xpositive real number or HMS form, and @var{n} is a real number or HMS
Xform in the range @samp{[0 .. @var{m})}.
X
XError forms are stored as @samp{(sdev @var{x} @var{sigma})}, where @var{x}
Xis the mean value and @var{sigma} is the standard deviation.  Each
Xcomponent is either a real number, an HMS form, or a symbolic object
X(a variable or function call).  If @var{sigma} is zero, the value is
Xconverted to a plain real number.  If @var{sigma} is negative, it is
Xautomatically normalized to be positive.
X
XInterval forms are stored as @samp{(intv @var{mask} @var{lo} @var{hi})},
Xwhere @var{mask} is one of the integers 0, 1, 2, or 3, and @var{lo} and
X@var{hi} are real numbers, HMS forms, or symbolic objects.  The @var{mask}
Xis a binary integer where 1 represents the fact that the interval is
Xclosed on the high end, and 2 represents the fact that it is closed on
Xthe low end.  (Thus 3 represents a fully closed interval.)  The interval
X@samp{(intv 3 @var{x} @var{x})} is converted to the plain number @var{x};
Xintervals @samp{(intv @var{mask} @var{x} @var{x})} for any other @var{mask}
Xrepresent empty intervals.  If @var{hi} is less than @var{lo}, the interval
Xis converted to a standard empty interval by replacing @var{hi} with @var{lo}.
X
XVectors are stored as @samp{(vec @var{v1} @var{v2} @dots{})}, where @var{v1}
Xis the first element of the vector, @var{v2} is the second, and so on.
XAn empty vector is stored as @samp{(vec)}.  A matrix is simply a vector
Xwhere all @var{v}'s are themselves vectors of equal lengths.
X
XVariables are stored as @samp{(var @var{name} @var{sym})}, where
X@var{name} is a Lisp symbol whose print name is used as the visible name
Xof the variable, and @var{sym} is a Lisp symbol in which the variable's
Xvalue is actually stored.  Thus, @samp{(var pi var-pi)} represents the
Xspecial constant @samp{pi}.  Almost always, the form is @samp{(var
X@var{v} var-@var{v})}.  If the variable name was entered with
Xunderscores (which are converted to hyphens internally), the form is
X@samp{(var @var{v} @var{v})}.  The value of a variable is the Calc
Xobject stored in its @var{sym} symbol's value cell.  If the symbol's
Xvalue cell is void or if it contains @code{nil}, the variable has no
Xvalue.  Special constants have the form @samp{(special-const
X@var{value})} stored in their value cell, where @var{value} is a formula
Xwhich is evaluated when the constant's value is requested.  Variables
Xwhich represent units are not stored in any special way; they are units
Xonly because their names appear in the units table.@refill
X
XA Lisp list with any other symbol as the first element is a function call.
XThe symbols @code{+}, @code{-}, @code{*}, @code{/}, @code{%}, @code{^},
Xand @code{|} represent special binary operators; these lists are always
Xof the form @samp{(@var{op} @var{lhs} @var{rhs})} where @var{lhs} is the
Xsub-formula on the lefthand side and @var{rhs} is the sub-formula on the
Xright.  The symbol @code{neg} represents unary negation; this list is always
Xof the form @samp{(neg @var{arg})}.  Any other symbol @var{func} represents a
Xfunction that would be displayed in function-call notation; the symbol
X@var{func} is in general always of the form @samp{calcFunc-@var{name}}.
XThe function cell of the symbol @var{func} should contain a Lisp function
Xfor evaluating a call to @var{func}.  This function is passed the remaining
Xelements of the list (themselves already evaluated) as arguments; such
Xfunctions should return @code{nil} or call @code{reject-arg} to signify
Xthat they should be left in symbolic form, or they should return a Calc
Xobject which represents their value, or a list of such objects if they
Xwish to return multiple values.  (The latter case is allowed only for
Xfunctions which are the outer-level call in an expression whose value is
Xabout to be pushed on the stack.)@refill
X
X@node Interactive Lisp Functions, Stack Lisp Functions, Data Type Formats, Internals
X@subsubsection Interactive Functions
X
XThe functions described here are used in implementing interactive Calc
Xcommands.
X
X@defun calc-set-command-flag flag
XSet the command flag @var{flag}.  This is generally a Lisp symbol, but
Xmay in fact by anything.  The effect is to add @var{flag} to the list
Xstored in the variable @code{calc-command-flags}, unless it is already
Xthere.  @xref{Defining Simple Commands}.
X@end defun
X
X@defun calc-clear-command-flag flag
XIf @var{flag} appears among the list of currently-set command flags,
Xremove it from that list.
X@end defun
X
X@defun calc-record-undo rec
XAdd the ``undo record'' @var{rec} to the list of steps to take if the
Xcurrent operation should need to be undone.  Stack push and pop functions
Xautomatically call @code{calc-record-undo}, so the kinds of undo records
Xyou might need to create take the form @samp{(set @var{sym} @var{value})},
Xwhich says that the Lisp variable @var{sym} was changed and had previously
Xcontained @var{value}; @samp{(store @var{var} @var{value})} which says that
Xthe Calc variable @var{var} (a string which is the name of the symbol that
Xcontains the variable's value) was stored and its previous value was
X@var{value} (either a Calc data object, or @var{nil} if the variable was
Xpreviously void); or @samp{(eval @var{undo} @var{redo} @var{args} @dots{})},
Xwhich means that to undo requires calling the function @samp{(@var{undo}
X@var{args} @dots{})} and, if the undo is later redone, calling
X@samp{(@var{redo} @var{args} @dots{})}.@refill
X@end defun
X
X@defun calc-record-why msg args
XRecord the error or warning message @var{msg}, which is normally a string.
XThis message will be replayed if the user types @kbd{w} (@code{calc-why});
Xthe first such message recorded for a command will be replayed automatically
Xif the user has turned on @code{calc-auto-why} mode.  If one or more
X@var{args} are present, the displayed message will be of the form,
X@samp{@var{msg}: @var{arg1}, @var{arg2}, @dots{}}, where the arguments are
Xformatted on the assumption that they are either strings or Calc objects of
Xsome sort.  If @var{msg} is a symbol, it is the name of a Calc predicate
X(such as @code{integerp} or @code{numvecp}) which the arguments did not
Xsatisfy; it is expanded to a suitable string such as ``Expected an
Xinteger.''  The @code{reject-arg} function calls @code{calc-record-why}
Xautomatically; @pxref{Predicates}.@refill
X@end defun
X
X@defun calc-is-inverse
XThis predicate returns true if the current command is inverse,
Xi.e., if the Inverse (@kbd{I} key) flag was set.
X@end defun
X
X@defun calc-is-hyperbolic
XThis predicate is the analogous function for the @kbd{H} key.
X@end defun
X
X@node Stack Lisp Functions, Predicates, Interactive Lisp Functions, Internals
X@subsubsection Stack-Oriented Functions
X
XThe functions described here perform various operations on the Calc
Xstack and trail.  They are to be used in interactive Calc commands.
X
X@defun calc-push-list vals n
XPush the Calc objects in list @var{vals} onto the stack at stack level
X@var{n}.  If @var{n} is omitted it defaults to 1, so that the elements
Xare pushed at the top of the stack.  If @var{n} is greater than 1, the
Xelements will be inserted into the stack so that the last element will
Xend up at level @var{n}, the next-to-last at level @var{n}+1, etc.
XThe elements of @var{vals} are assumed to be valid Calc objects, and
Xare not evaluated or renormalized in any way.  If @var{vals} is an
Xempty list, nothing happens.@refill
X@end defun
X
X@defun calc-top-list n m
XReturn a list of the @var{n} objects starting at level @var{m} of the
Xstack.  If @var{m} is omitted it defaults to 1, so that the elements are
Xtaken from the top of the stack.  If @var{n} is omitted, it also
Xdefaults to 1, so that the top stack element (in the form of a
Xone-element list) is returned.  If @var{m} is greater than 1, the
X@var{m}th stack element will be at the end of the list, the @var{m}+1st
Xelement will be next-to-last, etc.  If @var{n} or @var{m} are out of
Xrange, the command is aborted with a suitable error message.  If @var{n}
Xis zero, the function returns an empty list.  The stack elements are not
Xevaluated or renormalized.@refill
X@end defun
X
X@defun calc-pop-stack n m
XRemove the specified elements from the stack.  The parameters @var{n}
Xand @var{m} are defined the same as for @code{calc-top-list}.  The return
Xvalue of @code{calc-pop-stack} is uninteresting.
X@end defun
X
X@defun calc-record-list vals tag
XThis function records one or more results in the trail.  The @var{vals}
Xare a list of strings or Calc objects.  The @var{tag} is the four-character
Xtag string to identify the values.  If @var{tag} is omitted, a blank tag
Xwill be used.
X@end defun
X
X@defun calc-normalize n
XThis function takes a Calc object and ``normalizes'' it.  At the very
Xleast this involves re-rounding floating-point values according to the
Xcurrent precision and other similar jobs.  Also, unless the user has
Xselected no-simplify mode (@pxref{Simplification Modes}), this involves
Xactually evaluating a formula object by executing the function calls
Xit contains.
X@end defun
X
X@defun calc-top-list-n n m
XThis function is identical to @code{calc-top-list}, except that it calls
X@code{calc-normalize} on the values that it takes from the stack.  They
Xare also passed through @code{check-complete}, so that incomplete
Xobjects will be rejected with an error message.  All computational
Xcommands should use this in preference to @code{calc-top-list}; the only
Xstandard Calc commands that operate on the stack without normalizing
Xare stack management commands like @code{calc-enter} and @code{calc-roll-up}.
X@end defun
X
X@defun calc-top-n m
XThis function is a convenient form of @code{calc-top-list-n} in which only
Xa single element of the stack is taken and returned, rather than a list
Xof elements.
X@end defun
X
X@defun calc-enter-result n tag vals
XThis function is a convenient interface to most of the above functions.
XThe @var{vals} argument should be either a single Calc object, or a list
Xof Calc objects; the object or objects are normalized, and the top @var{n}
Xstack entries are replaced by the normalized objects.  If @var{tag} is
Xnon-@code{nil}, the normalized objects are also recorded in the trail.
XA typical stack-based computational command would take the form,
X
X@example
X(calc-enter-result @var{n} @var{tag} (cons 'calcFunc-@var{func}
X                               (calc-top-list-n @var{n})))
X@end example
X@end defun
X
X@defun calc-unary-op tag func arg
XThis function implements a unary operator that allows a numeric prefix
Xargument to apply the operator over many stack entries.  If the prefix
Xargument @var{arg} is @code{nil}, this uses @code{calc-enter-result}
Xas outlined above.  Otherwise, it maps the function over several stack
Xelements; @pxref{Prefix Arguments}.  For example,@refill
X
X@example
X(defun calc-zeta (arg)
X  (interactive "P")
X  (calc-unary-op "zeta" 'calcFunc-zeta arg))
X@end example
X@end defun
X
X@defun calc-binary-op tag func arg ident unary
XThis function implements a binary operator, analogously to
X@code{calc-unary-op}.  The optional @var{ident} and @var{unary}
Xarguments specify the behavior when the prefix argument is zero or
Xone, respectively.  If the argument is zero, the value @var{ident}
Xis pushed onto the stack, if specified, otherwise an error message
Xis displayed.  If the argument is one, the unary function @var{unary}
Xis applied to the top stack element, or, if @var{unary} is not
Xspecified, nothing happens.  When the argument is two or more,
Xthe binary function @var{func} is reduced across the top @var{arg}
Xstack elements; when the argument is negative, the function is
Xmapped between the next-to-top -@var{arg} stack elements and the
Xtop element.@refill
X@end defun
X
X@defun calc-stack-size
XReturn the number of elements on the stack as an integer.  This count
Xdoes not include elements that have been temporarily hidden by stack
Xtruncation; @pxref{Truncating the Stack}.
X@end defun
X
X@defun calc-cursor-stack-index n
XMove the point to the @var{n}th stack entry.  If @var{n} is zero, this
Xwill be the @samp{.} line.  If @var{n} is from 1 to the current stack size,
Xthis will be the beginning of the first line of that stack entry's display.
XIf line numbers are enabled, this will move to the first character of the
Xline number, not the stack entry itself.@refill
X@end defun
X
X@defun calc-substack-height n
XReturn the number of lines between the beginning of the @var{n}th stack
Xentry and the bottom of the buffer.  If @var{n} is zero, this
Xwill be one (assuming no stack truncation).  If all stack entries are
Xone line long (i.e., no matrices are displayed), the return value will
Xbe equal @var{n}+1 as long as @var{n} is in range.@refill
X@end defun
X
X@defun calc-refresh
XErase the @code{*Calculator*} buffer and reformat its contents from memory.
XThis must be called after changing any parameter, such as the current
Xdisplay radix, which might change the appearance of existing stack
Xentries.  (During a keyboard macro invoked by the @kbd{K} key, refreshing
Xis suppressed, but a flag is set so that the entire stack will be refreshed
Xrather than just the top few elements when the macro finishes.)@refill
X@end defun
X
X@node Predicates, Computational Lisp Functions, Stack Lisp Functions, Internals
X@subsubsection Predicates
X
XThe functions described here are predicates, that is, they return a
Xtrue/false value where @code{nil} means false and anything else means
Xtrue.  These predicates are expanded by @code{defmath}, for example,
Xfrom @code{zerop} to @code{math-zerop}.  In many cases they correspond
Xto native Lisp functions by the same name, but are extended to cover
Xthe full range of Calc data types.
X
X@defun zerop x
XReturns true if @var{x} is numerically zero, in any of the Calc data
Xtypes.  (Note that for some types, such as error forms and intervals,
Xit never makes sense to return true.)  In @code{defmath}, the expression
X@samp{(= x 0)} will automatically be converted to @samp{(math-zerop x)},
Xand @samp{(/= x 0)} will be converted to @samp{(not (math-zerop x))}.
X@end defun
X
X@defun negp x
XReturns true if @var{x} is negative.  This accepts negative real numbers
Xof various types, negative HMS forms, and intervals in which all
Xincluded values are negative.  In @code{defmath}, the expression
X@samp{(< x 0)} will automatically be converted to @samp{(math-negp x)},
Xand @samp{(>= x 0)} will be converted to samp{(not (math-negp x))}.
X@end defun
X
X@defun posp x
XReturns true if @var{x} is positive (and non-zero).
X@end defun
X
X@defun looks-negp x
XReturns true if @var{x} is ``negative-looking.''  This returns true if
X@var{x} is a negative number, or a formula with a leading minus sign
Xsuch as @samp{-a/b}.  In other words, this is an object which can be
Xmade simpler by calling @code{(- @var{x})}.
X@end defun
X
X@defun integerp x
XReturns true if @var{x} is an integer of any size.
X@end defun
X
X@defun fixnump x
XReturns true if @var{x} is a native Lisp integer.
X@end defun
X
X@defun natnump x
XReturns true if @var{x} is a nonnegative integer of any size.
X@end defun
X
X@defun fixnatnump x
XReturns true if @var{x} is a nonnegative Lisp integer.
X@end defun
X
X@defun num-integerp x
XReturns true if @var{x} is numerically an integer, i.e., either a
Xtrue integer or a float with no significant digits to the right of
Xthe decimal point.
X@end defun
X
X@defun messy-integerp x
XReturns true if @var{x} is numerically, but not literally, an integer.
XA value is @code{num-integerp} if it is @code{integerp} or
X@code{messy-integerp} (but it is never both at once).
X@end defun
X
X@defun num-natnump x
XReturns true if @var{x} is numerically a nonnegative integer.
X@end defun
X
X@defun evenp x
XReturns true if @var{x} is an even integer.
X@end defun
X
X@defun looks-evenp x
XReturns true if @var{x} is an even integer, or a formula with a leading
Xmultiplicative coefficient which is an even integer.
X@end defun
X
X@defun oddp x
XReturns true if @var{x} is an odd integer.
X@end defun
X
X@defun provably-integerp x
XReturns true if @var{x} is an integer, or a formula whose result
Xis guaranteed to be an integer (such as a call to @code{floor}).
X@end defun
X
X@defun ratp x
XReturns true if @var{x} is a rational number, i.e., an integer or a
Xfraction.
X@end defun
X
X@defun realp x
XReturns true if @var{x} is a real number, i.e., an integer, fraction,
Xor floating-point number.
X@end defun
X
X@defun provably-realp x
XReturns true if @var{x} is a real number, or a formula whose result
Xis guaranteed to be real (such as a call to @code{abs}).
X@end defun
X
X@defun anglep x
XReturns true if @var{x} is a real number or HMS form.
X@end defun
X
X@defun floatp x
XReturns true if @var{x} is a float, or a complex number, error form,
Xinterval, or modulo form in which at least one component is a float.
X@end defun
X
X@defun complexp x
XReturns true if @var{x} is a rectangular or polar complex number
X(but not a real number).
X@end defun
X
X@defun rect-complexp x
XReturns true if @var{x} is a rectangular complex number.
X@end defun
X
X@defun polar-complexp x
XReturns true if @var{x} is a polar complex number.
X@end defun
X
X@defun numberp x
XReturns true if @var{x} is a real number or a complex number.
X@end defun
X
X@defun scalarp x
XReturns true if @var{x} is a real or complex number or an HMS form.
X@end defun
X
X@defun vectorp x
XReturns true if @var{x} is a vector (this simply checks if its argument
Xis a list whose first element is the symbol @code{vec}).
X@end defun
X
X@defun numvecp x
XReturns true if @var{x} is a number or vector.
X@end defun
X
X@defun matrixp x
XReturns true if @var{x} is a matrix, i.e., a vector of one or more vectors,
Xall of the same size.
X@end defun
X
X@defun square-matrixp x
XReturns true if @var{x} is a square matrix.
X@end defun
X
X@defun objectp x
XReturns true if @var{x} is any numeric Calc object, including real and
Xcomplex numbers, HMS forms, error forms, intervals, and modulo forms.
X(Note that error forms and intervals may include formulas as their
Xcomponents; see @code{constp} below.)
X@end defun
X
X@defun real-objectp x
XReturns true if @var{x} is any numeric Calc object, in the sense of
X@code{objectp}, except for a complex number.
X@end defun
X
X@defun objvecp x
XReturns true if @var{x} is an object or a vector.  This also accepts
Xincomplete objects, but it rejects variables and formulas (except as
Xmentioned above for @code{objectp}).
X@end defun
X
X@defun primp x
XReturns true if @var{x} is a ``primitive'' or ``atomic'' Calc object,
Xi.e., one whose components cannot be regarded as sub-formulas.  This
Xincludes variables, and all @code{objectp} types except error forms
Xand intervals.
X@end defun
X
X@defun constp x
XReturns true if @var{x} is constant, i.e., a real or complex number,
XHMS form, or error form, interval, or vector all of whose components
Xare @code{constp}.
X@end defun
X
X@defun lessp x y
XReturns true if @var{x} is numerically less than @var{y}.  Returns false
Xif @var{x} is greater than or equal to @var{y}, or if the order is
Xundefined or cannot be determined.  Generally speaking, this works
Xby checking whether @samp{@var{x} - @var{y}} is @code{negp}.  In
X@code{defmath}, the expression @samp{(< x y)} will automatically be
Xconverted to @samp{(lessp x y)}; expressions involving @code{>}, @code{<=},
Xand @code{>=} are similarly converted in terms of @code{lessp}.@refill
X@end defun
X
X@defun beforep x y
XReturns true if @var{x} comes before @var{y} in a canonical ordering
Xof Calc objects.  If @var{x} and @var{y} are both real numbers, this
Xwill be the same as @code{lessp}.  But whereas @code{lessp} considers
Xother types of objects to be unordered, @code{beforep} puts any two
Xobjects into a definite, consistent order.  One application of
X@code{beforep} is that algebraic simplification rearranges the terms
Xin a product into canonical order, so that @samp{x y + y x} can
Xcheaply be simplified to @samp{2 x y}.
X@end defun
X
X@defun equal x y
XThis is the standard Lisp @code{equal} predicate; it returns true if
X@var{x} and @var{y} are structurally identical.  This is the usual way
Xto compare numbers for equality, but note that @code{equal} will treat
X0 and 0.0 as different.
X@end defun
X
X@defun math-equal x y
XReturns true if @var{x} and @var{y} are numerically equal, either because
Xthey are @code{equal}, or because their difference is @code{zerop}.  In
X@code{defmath}, the expression @samp{(= x y)} will automatically be
Xconverted to @samp{(math-equal x y)}.
X@end defun
X
X@defun equal-int x n
XReturns true if @var{x} and @var{n} are numerically equal, where @var{n}
Xis a fixnum which is not a multiple of 10.  This will automatically be
Xused by @code{defmath} in place of the more general @code{math-equal}
Xwhenever possible.@refill
X@end defun
X
X@defun nearly-equal x y
XReturns true if @var{x} and @var{y}, as floating-point numbers, are
Xequal except possibly in the last decimal place.  For example,
X314.159 and 314.166 are considered nearly equal if the current
Xprecision is 6 (since they differ by 7 units), but not if the current
Xprecision is 7 (since they differ by 70 units).  Most functions which 
Xuse series expansions use @code{with-extra-prec} to evaluate the
Xseries with 2 extra digits of precision, then use @code{nearly-equal}
Xto decide when the series has converged; this guards against cumulative
Xerror in the series evaluation without doing extra work which would be
Xlost when the result is rounded back down to the current precision.
XIn @code{defmath}, this can be written @samp{(~= @var{x} @var{y})}.
X@end defun
X
X@defun nearly-zerop x y
XReturns true if @var{x} is nearly zero, compared to @var{y}.  This
Xchecks whether @var{x} plus @var{y} would by be @code{nearly-equal}
Xto @var{y} itself, to within the current precision, in other words,
Xif adding @var{x} to @var{y} would have a negligible effect on @var{y}
SHAR_EOF
echo "End of part 18"
echo "File calc.texinfo is continued in part 19"
echo "19" > s2_seq_.tmp
exit 0