Newsgroups: comp.sources.misc From: daveg@synaptics.com (David Gillespie) Subject: v24i102: gnucalc - GNU Emacs Calculator, v2.00, Part54/56 Message-ID: <1991Nov3.001134.20001@sparky.imd.sterling.com> X-Md4-Signature: 4abe2a5e4dc99be4212ce72aa5ac3ba0 Date: Sun, 3 Nov 1991 00:11:34 GMT Approved: kent@sparky.imd.sterling.com Submitted-by: daveg@synaptics.com (David Gillespie) Posting-number: Volume 24, Issue 102 Archive-name: gnucalc/part54 Environment: Emacs Supersedes: gmcalc: Volume 13, Issue 27-45 #!/bin/sh # do not concatenate these parts, unpack them in order with /bin/sh # file calc.texinfo continued # if test ! -r _shar_seq_.tmp; then echo 'Please unpack part 1 first!' exit 1 fi (read Scheck if test "$Scheck" != 54; then echo Please unpack part "$Scheck" next! exit 1 else exit 0 fi ) < _shar_seq_.tmp || exit 1 if test ! -f _shar_wnt_.tmp; then echo 'x - still skipping calc.texinfo' else echo 'x - continuing file calc.texinfo' sed 's/^X//' << 'SHAR_EOF' >> 'calc.texinfo' && Convert the HMS form @var{a} into a real number. If @var{ang} is specified, it is the angular mode in which to express the result, otherwise the current angular mode is used. If @var{a} is already a real number, it is returned as-is. @end defun X @defun to-radians a Convert the number or HMS form @var{a} to radians from the current angular mode. @end defun X @defun from-radians a Convert the number @var{a} from radians to the current angular mode. If @var{a} is a formula, this returns the formula @samp{deg(@var{a})}. @end defun X @defun to-radians-2 a Like @code{to-radians}, except that in Symbolic Mode a degrees to radians conversion yields a formula like @samp{@var{a}*pi/180}. @end defun X @defun from-radians-2 a Like @code{from-radians}, except that in Symbolic Mode a radians to degrees conversion yields a formula like @samp{@var{a}*180/pi}. @end defun X @defun random-digit Produce a random base-1000 digit in the range 0 to 999. @end defun X @defun random-digits n Produce a random @var{n}-digit integer; this will be an integer in the interval @samp{[0, 10^@var{n})}. @end defun X @defun random-float Produce a random float in the interval @samp{[0, 1)}. @end defun X @defun prime-test n iters Determine whether the integer @var{n} is prime. Return a list which has one of these forms: @samp{(nil @var{f})} means the number is non-prime because it was found to be divisible by @var{f}; @samp{(nil)} means it was found to be non-prime by table look-up (so no factors are known); @samp{(nil unknown)} means it is definitely non-prime but no factors are known because @var{n} was large enough that Fermat's probabilistic test had to be used; @samp{(t)} means the number is definitely prime; and @samp{(maybe @var{i} @var{p})} means that Fermat's test, after @var{i} iterations, is @var{p} percent sure that the number is prime. The @var{iters} parameter is the number of Fermat iterations to use, in the case that this is necessary. If @code{prime-test} returns ``maybe,'' you can call it again with the same @var{n} to get a greater certainty; @code{prime-test} remembers where it left off.@refill @end defun X @defun to-simple-fraction f If @var{f} is a floating-point number which can be represented exactly as a small rational number. return that number, else return @var{f}. For example, 0.75 would be converted to 3:4. This function is very fast. @end defun X @defun to-fraction f tol Find a rational approximation to floating-point number @var{f} to within a specified tolerance @var{tol}; this corresponds to the algebraic function @code{frac}, and can be rather slow. @end defun X @node Vector Lisp Functions, Symbolic Lisp Functions, Computational Lisp Functions, Internals @subsubsection Vector Functions X @noindent The functions described here perform various operations on vectors and matrices. X @defun math-concat x y Do a vector concatenation; this operation is written @samp{@var{x} | @var{y}} in a symbolic formula. @xref{Building Vectors}. @end defun X @defun vec-length v Return the length of vector @var{v}. If @var{v} is not a vector, the result is zero. If @var{v} is a matrix, this returns the number of rows in the matrix. @end defun X @defun mat-dimens m Determine the dimensions of vector or matrix @var{m}. If @var{m} is not a vector, the result is an empty list. If @var{m} is a plain vector but not a matrix, the result is a one-element list containing the length of the vector. If @var{m} is a matrix with @var{r} rows and @var{c} columns, the result is the list @samp{(@var{r} @var{c})}. Higher-order tensors produce lists of more than two dimensions. Note that the object @samp{[[1, 2, 3], [4, 5]]} is a vector of vectors not all the same size, and is treated by this and other Calc routines as a plain vector of two elements.@refill @end defun X @defun dimension-error Abort the current function with a message of ``Dimension error.'' The Calculator will leave the function being evaluated in symbolic form; this is really just a special case of @code{reject-arg}. @end defun X @defun build-vector args Return a Calc vector with the zero-or-more @var{args} as elements. For example, @samp{(build-vector 1 2 3)} returns the Calc vector @samp{[1, 2, 3]}, stored internally as the list @samp{(vec 1 2 3)}. @end defun X @defun make-vec obj dims Return a Calc vector or matrix all of whose elements are equal to @var{obj}. For example, @samp{(make-vec 27 3 4)} returns a 3x4 matrix filled with 27's. @end defun X @defun row-matrix v If @var{v} is a plain vector, convert it into a row matrix, i.e., a matrix whose single row is @var{v}. If @var{v} is already a matrix, leave it alone. @end defun X @defun col-matrix v If @var{v} is a plain vector, convert it into a column matrix, i.e., a matrix with each element of @var{v} as a separate row. If @var{v} is already a matrix, leave it alone. @end defun X @defun map-vec f v Map the Lisp function @var{f} over the Calc vector @var{v}. For example, @samp{(map-vec 'math-floor v)} returns a vector of the floored components of vector @var{v}. @end defun X @defun map-vec-2 f a b Map the Lisp function @var{f} over the two vectors @var{a} and @var{b}. If @var{a} and @var{b} are vectors of equal length, the result is a vector of the results of calling @samp{(@var{f} @var{ai} @var{bi})} for each pair of elements @var{ai} and @var{bi}. If either @var{a} or @var{b} is a scalar, it is matched with each value of the other vector. For example, @samp{(map-vec-2 'math-add v 1)} returns the vector @var{v} with each element increased by one. Note that using @samp{'+} would not work here, since @code{defmath} does not expand function names everywhere, just where they are in the function position of a Lisp expression.@refill @end defun X @defun reduce-vec f v Reduce the function @var{f} over the vector @var{v}. For example, if @var{v} is @samp{[10, 20, 30, 40]}, this calls @samp{(f (f (f 10 20) 30) 40)}. If @var{v} is a matrix, this reduces over the rows of @var{v}. @end defun X @defun reduce-cols f m Reduce the function @var{f} over the columns of matrix @var{m}. For example, if @var{m} is @samp{[[1, 2], [3, 4], [5, 6]]}, the result is a vector of the two elements @samp{(f (f 1 3) 5)} and @samp{(f (f 2 4) 6)}. @end defun X @defun mat-row m n Return the @var{n}th row of matrix @var{m}. This is equivalent to @samp{(elt m n)}. For a slower but safer version, use @code{mrow}. (@xref{Extracting Elements}.) @end defun X @defun mat-col m n Return the @var{n}th column of matrix @var{m}, in the form of a vector. The arguments are not checked for correctness. @end defun X @defun mat-less-row m n Return a copy of matrix @var{m} with its @var{n}th row deleted. The number @var{n} must be in range from 1 to the number of rows in @var{m}. @end defun X @defun mat-less-col m n Return a copy of matrix @var{m} with its @var{n}th column deleted. @end defun X @defun transpose m Return the transpose of matrix @var{m}. @end defun X @defun flatten-vector v Flatten nested vector @var{v} into a vector of scalars. For example, if @var{v} is @samp{[[1, 2, 3], [4, 5]]} the result is @samp{[1, 2, 3, 4, 5]}. @end defun X @defun copy-matrix m If @var{m} is a matrix, return a copy of @var{m}. This maps @code{copy-sequence} over the rows of @var{m}; in Lisp terms, each element of the result matrix will be @code{eq} to the corresponding element of @var{m}, but none of the @code{cons} cells that make up the structure of the matrix will be @code{eq}. If @var{m} is a plain vector, this is the same as @code{copy-sequence}.@refill @end defun X @defun swap-rows m r1 r2 Exchange rows @var{r1} and @var{r2} of matrix @var{m} in-place. In other words, unlike most of the other functions described here, this function changes @var{m} itself rather than building up a new result matrix. The return value is @var{m}, i.e., @samp{(eq (swap-rows m 1 2) m)} is true, with the side effect of exchanging the first two rows of @var{m}.@refill @end defun X @node Symbolic Lisp Functions, Formatting Lisp Functions, Vector Lisp Functions, Internals @subsubsection Symbolic Functions X @noindent The functions described here operate on symbolic formulas in the Calculator. X @defun calc-prepare-selection num Prepare a stack entry for selection operations. If @var{num} is omitted, the stack entry containing the cursor is used; otherwise, it is the number of the stack entry to use. This function stores useful information about the current stack entry into a set of variables. @code{calc-selection-cache-num} contains the number of the stack entry involved (equal to @var{num} if you specified it); @code{calc-selection-cache-entry} contains the stack entry as a list (such as @code{calc-top-list} would return with @code{entry} as the selection mode); and @code{calc-selection-cache-comp} contains a special ``tagged'' composition (@pxref{Formatting Lisp Functions}) which allows Calc to relate cursor positions in the buffer with their corresponding sub-formulas. X A slight complication arises in the selection mechanism because formulas may contain small integers. For example, in the vector @samp{[1, 2, 1]} the first and last elements are @code{eq} to each other; selections are recorded as the actual Lisp object that appears somewhere in the tree of the whole formula, but storing @code{1} would falsely select both @code{1}'s in the vector. So @code{calc-prepare-selection} also checks the stack entry and replaces any plain integers with ``complex number'' lists of the form @samp{(cplx @var{n} 0)}. This list will be displayed the same as a plain @var{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 @code{eq} to each other. Next time the stack entry is involved in a computation, @code{calc-normalize} will replace these lists with plain numbers again, again invisibly to the user. @end defun X @defun calc-find-selected-part Find the smallest sub-formula of the current formula that contains the cursor. This assumes @code{calc-prepare-selection} has been called already. If the cursor is not actually on any part of the formula, this returns @code{nil}. @end defun X @defun calc-change-current-selection selection Change the currently prepared stack element's selection to @var{selection}, which should be @code{eq} to some sub-formula of the stack element, or @code{nil} to unselect the formula. The stack element's appearance in the Calc buffer is adjusted to reflect the new selection. @end defun X @defun calc-find-nth-part expr n Return the @var{n}th sub-formula of @var{expr}. This function is used by the selection commands, and (unless @kbd{j b} has been used) treats sums and products as flat many-element formulas. Thus if @var{expr} is @samp{((a + b) - c) + d}, calling @code{calc-find-nth-part} with @var{n} equal to four will return @samp{d}. @end defun X @defun calc-find-parent-formula expr part Return the sub-formula of @var{expr} which immediately contains @var{part}. If @var{expr} is @samp{a*b + (c+1)*d} and @var{part} is @code{eq} to the @samp{c+1} term of @var{expr}, then this function will return @samp{(c+1)*d}. If @var{part} turns out not to be a sub-formula of @var{expr}, the function returns @code{nil}. If @var{part} is @code{eq} to @var{expr}, the function returns @code{t}. This function does not take associativity into account. @end defun X @defun calc-find-assoc-parent-formula expr part This is the same as @code{calc-find-parent-formula}, except that (unless @kbd{j b} has been used) it continues widening the selection to contain a complete level of the formula. Given @samp{a} from @samp{((a + b) - c) + d}, @code{calc-find-parent-formula} will return @samp{a + b} but @code{calc-find-assoc-parent-formula} will return the whole expression. @end defun X @defun calc-grow-assoc-formula expr part This expands sub-formula @var{part} of @var{expr} to encompass a complete level of the formula. If @var{part} and its immediate parent are not compatible associative operators, or if @kbd{j b} has been used, this simply returns @var{part}. @end defun X @defun calc-find-sub-formula expr part This finds the immediate sub-formula of @var{expr} which contains @var{part}. It returns an index @var{n} such that @samp{(calc-find-nth-part @var{expr} @var{n})} would return @var{part}. If @var{part} is not a sub-formula of @var{expr}, it returns @code{nil}. If @var{part} is @code{eq} to @var{expr}, it returns @code{t}. This function does not take associativity into account. @end defun X @defun calc-replace-sub-formula expr old new This function returns a copy of formula @var{expr}, with the sub-formula that is @code{eq} to @var{old} replaced by @var{new}. @end defun X @defun simplify expr Simplify the expression @var{expr} by applying various algebraic rules. This is what the @kbd{a s} (@code{calc-simplify}) command uses. This always returns a copy of the expression; the structure @var{expr} points to remains unchanged in memory. X More precisely, here is what @code{simplify} does: The expression is first normalized and evaluated by calling @code{normalize}. 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 @code{normalize}) and, if it has changed, the entire procedure is repeated (starting with @code{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. @end defun X @defun simplify-extended expr Simplify the expression @var{expr}, with additional rules enabled that help do a more thorough job, while not being entirely ``safe'' in all circumstances. (For example, this mode will simplify @samp{sqrt(x^2)} to @samp{x}, which is only valid when @var{x} is positive.) This is implemented by temporarily binding the variable @code{math-living-dangerously} to @code{t} (using a @code{let} form) and calling @code{simplify}. Dangerous simplification rules are written to check this variable before taking any action.@refill @end defun X @defun simplify-units expr Simplify the expression @var{expr}, treating variable names as units whenever possible. This works by binding the variable @code{math-simplifying-units} to @code{t} while calling @code{simplify}. @end defun X @defmac math-defsimplify funcs body Register a new simplification rule; this is normally called as a top-level form, like @code{defun} or @code{defmath}. If @var{funcs} is a symbol (like @code{+} or @code{calcFunc-sqrt}), this simplification rule is applied to the formulas which are calls to the specified function. Or, @var{funcs} can be a list of such symbols; the rule applies to all functions on the list. The @var{body} is written like the body of a function with a single argument called @code{expr}. The body will be executed with @code{expr} bound to a formula which is a call to one of the functions @var{funcs}. If the function body returns @code{nil}, or if it returns a result @code{equal} to the original @code{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 @var{expr} in the original formula.@refill X At each point in the formula, rules are tried in the order of the original calls to @code{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 @code{simplify} loop. X Note that, since @code{defmath} is not being used here, @var{body} must be written in true Lisp code without the conveniences that @code{defmath} provides. If you prefer, you can have @var{body} simply call another function (defined with @code{defmath}) which does the real work. X 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: X @smallexample (math-defsimplify calcFunc-arcsinh X (or (and (math-looks-negp (nth 1 expr)) X (math-neg (list 'calcFunc-arcsinh (math-neg (nth 1 expr))))) X (and (eq (car-safe (nth 1 expr)) 'calcFunc-sinh) X (or math-living-dangerously X (math-known-realp (nth 1 (nth 1 expr)))) X (nth 1 (nth 1 expr))))) @end smallexample X This is really a pair of rules written with one @code{math-defsimplify} for convenience; the first replaces @samp{arcsinh(-x)} with @samp{-arcsinh(x)}, and the second, which is safe only for real @samp{x}, replaces @samp{arcsinh(sinh(x))} with @samp{x}.@refill @end defmac X @defun common-constant-factor expr Check @var{expr} to see if it is a sum of terms all multiplied by the same rational value. If so, return this value. If not, return @code{nil}. For example, if called on @samp{6x + 9y + 12z}, it would return 3, since 3 is a common factor of all the terms. @end defun X @defun cancel-common-factor expr factor Assuming @var{expr} is a sum with @var{factor} as a common factor, divide each term of the sum by @var{factor}. This is done by destructively modifying parts of @var{expr}, on the assumption that it is being used by a simplification rule (where such things are allowed; see above). For example, consider this built-in rule for square roots: X @smallexample (math-defsimplify calcFunc-sqrt X (let ((fac (math-common-constant-factor (nth 1 expr)))) X (and fac X (math-mul (list 'calcFunc-sqrt fac) X (list 'calcFunc-sqrt X (math-cancel-common-factor X (nth 1 expr) fac)))))) @end smallexample @end defun X @defun frac-gcd a b Compute a ``rational GCD'' of @var{a} and @var{b}, which must both be rational numbers. This is the fraction composed of the GCD of the numerators of @var{a} and @var{b}, over the GCD of the denominators. It is used by @code{common-constant-factor}.@refill @end defun X @defun map-tree func expr many Try applying Lisp function @var{func} to various sub-expressions of @var{expr}. Initially, call @var{func} with @var{expr} itself as an argument. If this returns an expression which is not @code{equal} to @var{expr}, apply @var{func} again until eventually it does return @var{expr} with no changes. Then, if @var{expr} is a function call, recursively apply @var{func} to each of the arguments. This keeps going until no changes occur anywhere in the expression; this final expression is returned by @code{map-tree}. Note that, unlike simplification rules, @var{func} functions may @emph{not} make destructive changes to @var{expr}. If a third argument @var{many} is provided, it is an integer which says how many times @var{func} may be applied; the default, as described above, is infinitely many times.@refill @end defun X @defun compile-rewrites rules Compile the rewrite rule set specified by @var{rules}, which should be a formula that is either a vector or a variable name. If the latter, the compiled rules are saved so that later @code{compile-rules} calls for that same variable can return immediately. If there are problems with the rules, this function calls @code{error} with a suitable message. @end defun X @defun apply-rewrites expr crules heads Apply the compiled rewrite rule set @var{crules} to the expression @var{expr}. This will make only one rewrite and only checks at the top level of the expression. The result @code{nil} if no rules matched, or if the only rules that matched did not actually change the expression. The @var{heads} argument is optional; if is given, it should be a list of all function names that (may) appear in @var{expr}. The rewrite compiler tags each rule with the rarest-looking function name in the rule; if you specify @var{heads}, @code{apply-rewrites} can use this information to narrow its search down to just a few rules in the rule set. @end defun X @defun rewrite-heads expr Compute a @var{heads} list for @var{expr} suitable for use with @code{apply-rewrites}, as discussed above. @end defun X @defun rewrite expr rules many This is an all-in-one rewrite function. It compiles the rule set specified by @var{rules}, then uses @code{map-tree} to apply the rules throughout @var{expr} up to @var{many} (default infinity) times. @end defun X @defun match-patterns pat vec not-flag Given a Calc vector @var{vec} and an uncompiled pattern set or pattern set variable @var{pat}, this function returns a new vector of all elements of @var{vec} which do (or don't, if @var{not-flag} is non-@code{nil}) match any of the patterns in @var{pat}. @end defun X @defun deriv expr var value symb Compute the derivative of @var{expr} with respect to variable @var{var} (which may actually be any sub-expression). If @var{value} is specified, the derivative is evaluated at the value of @var{var}; otherwise, the derivative is left in terms of @var{var}. If the expression contains functions for which no derivative formula is known, new derivative functions are invented by adding primes to the names; @pxref{Calculus}. However, if @var{symb} is non-@code{nil}, the presence of undifferentiable functions in @var{expr} instead cancels the whole differentiation, and @code{deriv} returns @code{nil} instead. X Derivatives of a one-argument function can be defined by adding a @code{math-derivative-@var{n}} property to the property list of the symbol for the function's derivative, which will be the function name followed by an apostrophe. Here @var{n} is the number of arguments to the function. 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 @code{ln} is defined by X @smallexample (put 'calcFunc-ln\' 'math-derivative-1 X (function (lambda (u) (math-div 1 u)))) @end smallexample X The two-argument @code{log} function has two derivatives, @smallexample (put 'calcFunc-log\' 'math-derivative-2 ; d(log(x,b)) / dx X ... ) (put 'calcFunc-log\'2 'math-derivative-2 ; d(log(x,b)) / db X ... ) @end smallexample @end defun X @defun tderiv expr var value symb Compute the total derivative of @var{expr}. This is the same as @code{deriv}, except that variables other than @var{var} are not assumed to be constant with respect to @var{var}. @end defun X @defun integ expr var low high Compute the integral of @var{expr} with respect to @var{var}. @xref{Calculus}, for further details. @end defun X @defmac math-defintegral funcs body Define a rule for integrating a function or functions of one argument; this macro is very similar in format to @code{math-defsimplify}. The main difference is that here @var{body} is the body of a function with a single argument @code{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 @code{math-integ-var}. If evaluation of the integral requires doing further integrals, the body should call @samp{(math-integral @var{x})} to find the integral of @var{x} with respect to @code{math-integ-var}; this function returns @code{nil} if the integral could not be done. Some examples: X @smallexample (math-defintegral calcFunc-conj X (let ((int (math-integral u))) X (and int X (list 'calcFunc-conj int)))) X (math-defintegral calcFunc-cos X (and (equal u math-integ-var) X (math-from-radians-2 (list 'calcFunc-sin u)))) @end smallexample X In the @code{cos} example, we define only the integral of @samp{cos(x) dx}, relying on the general integration-by-substitution facility to handle cosines of more complicated arguments. An integration rule should return @code{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-@code{nil} result.@refill @end defmac X @defmac math-defintegral-2 funcs body Define a rule for integrating a function or functions of two arguments. This is exactly analogous to @code{math-defintegral}, except that @var{body} is written as the body of a function with two arguments, @var{u} and @var{v}.@refill @end defmac X @defun solve-for lhs rhs var full Attempt to solve the equation @samp{@var{lhs} = @var{rhs}} by isolating the variable @var{var} on the lefthand side; return the resulting righthand side, or @code{nil} if the equation cannot be solved. The variable @var{var} must appear at least once in @var{lhs} or @var{rhs}; if it appears more than once, Calc can solve the equation in only a few cases (such as when the quadratic formula can be applied). Note that the return value is a formula which does not contain @var{var}; this is different from the user-level @code{solve} and @code{finv} functions, which return a rearranged equation or a functional inverse, respectively. If @var{full} is non-@code{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:@refill X @smallexample (put 'calcFunc-ln 'math-inverse X (function (lambda (x) (list 'calcFunc-exp x)))) @end smallexample X This function can call @samp{(math-solve-get-sign @var{x})} to create a new arbitrary sign variable, returning @var{x} times that sign, and @samp{(math-solve-get-int @var{x})} to create a new arbitrary integer variable multiplied by @var{x}. These functions simply return @var{x} if the caller requested a non-``full'' solution. @end defun X @defun solve-eqn expr var full This version of @code{solve-for} takes an expression which will typically be an equation or inequality. (If it is not, it will be interpreted as the equation @samp{@var{expr} = 0}.) It returns an equation or inequality, or @code{nil} if no solution could be found. @end defun X @defun expr-contains expr var Returns the number of occurrences of @var{var} as a subexpression of @var{expr}, or @code{nil} if there are no occurrences. Thus, this function can be used as a Lisp predicate or as an actual counting function.@refill X When used as a predicate, this function seems at first to be identical to @code{calc-find-sub-formula}. The key difference is that @code{expr-contains} uses @code{equal} to test for matches, whereas @code{calc-find-sub-formula} uses @code{eq}. In the formula @samp{f(a, a)}, the two @samp{a}'s will be @code{equal} but not @code{eq} to each other. @end defun X @defun expr-depends expr var Returns true if @var{expr} refers to any variable the occurs in @var{var}. In other words, it checks if @var{expr} and @var{var} have any variables in common. @end defun X @defun expr-contains-vars expr Return true if @var{expr} contains any variables, or @code{nil} if @var{expr} contains only constants and functions with constant arguments. @end defun X @defun expr-subst expr old new Returns a copy of @var{expr}, with all occurrences of @var{old} replaced by @var{new}. This treats the derivative forms specially with respect to the dummy variable, so that the effect is always to return @var{expr} evaluated at @var{old} = @var{new}.@refill @end defun X @defun expr-weight expr Returns the ``weight'' of @var{expr}, basically a count of the total number of objects and function calls that appear in @var{expr}. For ``primitive'' objects, this will be one. @end defun X @defun expr-height expr Returns the ``height'' of @var{expr}, which is the deepest level to which function calls are nested. (Note that @samp{@var{a} + @var{b}} counts as a function call.) For primitive objects, this returns zero.@refill @end defun X @defun polynomial-p expr var Check if @var{expr} is a polynomial in variable (or sub-expression) @var{var}. If so, return the degree of the polynomial, that is, the highest power of @var{var} that appears in @var{expr}. For example, for @samp{(x^2 + 3)^3 + 4} this would return 6. This function returns @code{nil} unless @var{expr}, when expanded out by @kbd{a x} (@code{calc-expand}), would consist of a sum of terms in which @var{var} appears only raised to nonnegative integer powers. Note that if @var{var} does not occur in @var{expr}, then @var{expr} is considered a polynomial of degree 0.@refill @end defun X @defun is-polynomial expr var degree loose Check if @var{expr} is a polynomial in variable or sub-expression @var{var}, and, if so, return a list representation of the polynomial where the elements of the list are coefficients of successive powers of @var{var}: @samp{@var{a} + @var{b} x + @var{c} x^3} would produce the list @samp{(@var{a} @var{b} 0 @var{c})}, and @samp{(x + 1)^2} would produce the list @samp{(1 2 1)}. The highest element of the list will be non-zero, with the special exception that if @var{expr} is the constant zero, the returned value will be @samp{(0)}. Return @code{nil} if @var{expr} is not a polynomial in @var{var}. If @var{degree} is specified, this will not consider polynomials of degree higher than that value. This is a good precaution because otherwise an input of @samp{(x+1)^1000} will cause a huge coefficient list to be built. If @var{loose} is non-@code{nil}, then a looser definition of a polynomial is used in which coefficients are no longer required not to depend on @var{var}, but are only required not to take the form of polynomials themselves. For example, @samp{sin(x) x^2 + cos(x)} is a loose polynomial with coefficients @samp{((calcFunc-cos x) 0 (calcFunc-sin x))}. The result will never be @code{nil} in loose mode, since any expression can be interpreted as a ``constant'' loose polynomial.@refill @end defun X @defun polynomial-base expr pred Check if @var{expr} is a polynomial in any variable that occurs in it; if so, return that variable. (If @var{expr} is a multivariate polynomial, choose one variable arbitrarily.) If @var{pred} is specified, it should be a Lisp function which is called as @samp{(@var{pred} @var{subexpr})}, and which should return true if @code{mpb-top-expr} (a global name for the original @var{expr}) is a suitable polynomial in @var{subexpr}. The default predicate uses @samp{(polynomial-p mpb-top-expr @var{subexpr})}; you can use @var{pred} to specify additional conditions. Or, you could have @var{pred} build up a list of every suitable @var{subexpr} that is found.@refill @end defun X @defun poly-simplify poly Simplify polynomial coefficient list @var{poly} by (destructively) clipping off trailing zeros. @end defun X @defun poly-mix a ac b bc Mix two polynomial lists @var{a} and @var{b} (in the form returned by @code{is-polynomial}) in a linear combination with coefficient expressions @var{ac} and @var{bc}. The result is a (not necessarily simplified) polynomial list representing @samp{@var{ac} @var{a} + @var{bc} @var{b}}.@refill @end defun X @defun poly-mul a b Multiply two polynomial coefficient lists @var{a} and @var{b}. The result will be in simplified form if the inputs were simplified. @end defun X @defun build-polynomial-expr poly var Construct a Calc formula which represents the polynomial coefficient list @var{poly} applied to variable @var{var}. The @kbd{a c} (@code{calc-collect}) command uses @code{is-polynomial} to turn an expression into a coefficient list, then @code{build-polynomial-expr} to turn the list back into an expression in regular form.@refill @end defun X @defun check-unit-name var Check if @var{var} is a variable which can be interpreted as a unit name. If so, return the units table entry for that unit. This will be a list whose first element is the unit name (not counting prefix characters) as a symbol and whose second element is the Calc expression which defines the unit. (Refer to the Calc sources for details on the remaining elements of this list.) If @var{var} is not a variable or is not a unit name, return @code{nil}. @end defun X @defun units-in-expr-p expr sub-exprs Return true if @var{expr} contains any variables which can be interpreted as units. If @var{sub-exprs} is @code{t}, the entire expression is searched. If @var{sub-exprs} is @code{nil}, this checks whether @var{expr} is directly a units expression.@refill @end defun X @defun single-units-in-expr-p expr Check whether @var{expr} contains exactly one units variable. If so, return the units table entry for the variable. If @var{expr} does not contain any units, return @code{nil}. If @var{expr} contains two or more units, return the symbol @samp{'wrong}. @end defun X @defun to-standard-units expr which Convert units expression @var{expr} to base units. If @var{which} is @code{nil}, use Calc's native base units. Otherwise, @var{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.@refill @end defun X @defun remove-units expr Return a copy of @var{expr} with all units variables replaced by ones. This expression is generally normalized before use. @end defun X @defun extract-units expr Return a copy of @var{expr} with everything but units variables replaced by ones. @end defun X @node Formatting Lisp Functions, Lisp Variables, Symbolic Lisp Functions, Internals @subsubsection I/O and Formatting Functions X @noindent The functions described here are responsible for parsing and formatting Calc numbers and formulas. X @defun calc-eval str sep arg1 arg2 @dots{} This is the simplest interface to the Calculator from another Lisp program. @xref{Calling Calc from Your Programs}. @end defun X @defun read-number str If string @var{str} contains a valid Calc number, either integer, fraction, float, or HMS form, this function parses and returns that number. Otherwise, it returns @code{nil}. @end defun X @defun read-expr str Read an algebraic expression from string @var{str}. If @var{str} does not have the form of a valid expression, return a list of the form @samp{(error @var{pos} @var{msg})} where @var{pos} is an integer index into @var{str} of the general location of the error, and @var{msg} is a string describing the problem.@refill @end defun X @defun read-exprs str Read a list of expressions separated by commas, and return it as a Lisp list. If an error occurs in any expressions, an error list as shown above is returned instead. @end defun X @defun calc-do-alg-entry initial prompt no-norm Read an algebraic formula or formulas using the minibuffer. All conventions of regular algebraic entry are observed. The return value is a list of Calc formulas; there will be more than one if the user entered a list of values separated by commas. The result is @code{nil} if the user presses Return with a blank line. If @var{initial} is given, it is a string which the minibuffer will initially contain. If @var{prompt} is given, it is the prompt string to use; the default is ``Algebraic:''. If @var{no-norm} is @code{t}, the formulas will be returned exactly as parsed; otherwise, they will be passed through @code{calc-normalize} first.@refill X To support the use of @kbd{$} characters in the algebraic entry, use @code{let} to bind @code{calc-dollar-values} to a list of the values to be substituted for @kbd{$}, @kbd{$$}, and so on, and bind @code{calc-dollar-used} to 0. Upon return, @code{calc-dollar-used} will have been changed to the highest number of consecutive @kbd{$}s that actually appeared in the input.@refill @end defun X @defun format-number a Convert the real or complex number or HMS form @var{a} to string form. @end defun X @defun format-flat-expr a prec Convert the arbitrary Calc number or formula @var{a} to string form, in the style used by the trail buffer. This is a simple format designed mostly to guarantee the string is of a form that can be re-parsed by @code{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 @var{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. @end defun X @defun format-nice-expr a width This is like @code{format-flat-expr} (with @var{prec} equal to 0), except that newlines will be inserted to keep lines down to the specified @var{width}, and vectors of vectors (not necessarily strict matrices) are written in a pseudo-matrix format. The @code{calc-edit} command uses this when only a stack entry is being edited. @end defun X @defun format-value a width Convert the Calc number or formula @var{a} to string form, using the format seen in the stack buffer. Beware the the string returned may not be re-readable by @code{read-expr}, for example, because of digit grouping. Multi-line objects like matrices produce strings that contain newline characters to separate the lines. The @var{w} parameter, if given, is the target window size for which to format the expressions. If @var{w} is omitted, the width of the Calculator window is used.@refill @end defun X @defun compose-expr a prec Format the Calc number or formula @var{a} according to the current language mode, returning a ``composition.'' To learn about the structure of compositions, see the comments in the Calc source code. You can specify the format of a given type of function call by putting a @code{math-compose-@var{lang}} property on the function's symbol, whose value is a Lisp function that takes @var{a} and @var{prec} as arguments and returns a composition. Here @var{lang} is a language mode name, one of @code{normal}, @code{big}, @code{c}, @code{pascal}, @code{fortran}, @code{tex}, @code{eqn}, @code{math}, or @code{maple}. In Big mode, Calc actually tries @code{math-compose-big} first, then tries @code{math-compose-normal}. If this property does not exist, or if the function returns @code{nil}, the function is written in the normal function-call notation for that language. @end defun X @defun composition-to-string c w Convert a composition structure returned by @code{compose-expr} into a string. Multi-line compositions convert to strings containing newline characters. The target window size is given by @var{w}. The @code{format-value} function basically calls @code{compose-expr} followed by @code{composition-to-string}. @end defun X @defun comp-width c Compute the width in characters of composition @var{c}. @end defun X @defun comp-height c Compute the height in lines of composition @var{c}. @end defun X @defun comp-ascent c Compute the portion of the height of composition @var{c} which is on or above the baseline. For a one-line composition, this will be one. @end defun X @defun comp-descent c Compute the portion of the height of composition @var{c} which is below the baseline. For a one-line composition, this will be zero. @end defun X @defun comp-first-char c If composition @var{c} is a simple horizontal composition, return the first (leftmost) character of the composition as an integer. Otherwise, return @code{nil}.@refill @end defun X @defun comp-last-char c If composition @var{c} is a simple horizontal composition, return the last (rightmost) character, otherwise return @code{nil}. @end defun X @node Lisp Variables, Hooks, Formatting Lisp Functions, Internals @subsubsection Lisp Variables X @noindent (This section is currently unfinished.) X @node Hooks, , Lisp Variables, Internals @subsubsection Hooks X @noindent 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 @code{run-hooks} to invoke the hooks shown below. Several other customization-related variables are also described here. X @defvar calc-load-hook This hook is called at the end of @file{calc.el}, after the file has been loaded, before any functions in it have been called, but after @code{calc-mode-map} and similar variables have been set up. @end defvar X @defvar calc-ext-load-hook This hook is called at the end of @file{calc-ext.el}. @end defvar X @defvar calc-start-hook This hook is called as the last step in a @kbd{M-x calc} command. At this point, the Calc buffer has been created and initialized if necessary, the Calc window and trail window have been created, and the ``Welcome to Calc'' message has been displayed. @end defvar X @defvar calc-mode-hook This hook is called when the Calc buffer is being created. Usually this will only happen once per Emacs session. The hook is called after Emacs has switched to the new buffer, the mode-settings file has been read if necessary, and all other buffer-local variables have been set up. After this hook returns, Calc will perform a @code{calc-refresh} operation, set up the mode line display, then evaluate any deferred @code{calc-define} properties that have not been evaluated yet. @end defvar X @defvar calc-trail-mode-hook This hook is called when the Calc Trail buffer is being created. It is called as the very last step of setting up the Trail buffer. Like @code{calc-mode-hook}, this will normally happen only once per Emacs session. @end defvar X @defvar calc-end-hook This hook is called by @code{calc-quit}, generally because the user presses @key{q} or @kbd{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 has been destroyed. @end defvar X @defvar calc-window-hook If this hook exists, it is called to create the Calc window. Upon return, this new Calc window should be the current window. (The Calc buffer will already be the current buffer when the hook is called.) If the hook is not defined, Calc will generally use @code{split-window}, @code{set-window-buffer}, and @code{select-window} to create the Calc window. @end defvar X @defvar calc-trail-window-hook If this hook exists, it is called to create the Calc Trail window. The variable @code{calc-trail-buffer} will contain the buffer which the window should use. Unlike @code{calc-window-hook}, this hook must @emph{not} switch into the new window. @end defvar X @defvar calc-edit-mode-hook This hook is called by @code{calc-edit} (and a few other similar commands) when the temporary editing buffer is being created. The buffer will have been selected and set up to be in @code{calc-edit-mode}, but will not yet have been filled with text. (In fact it may still have leftover text from a previous @code{calc-edit} command.) @end defvar X @defvar calc-mode-save-hook This hook is called by the @code{calc-save-modes} command, after Calc's own mode features have been inserted into the @file{.emacs} buffer and just before the ``End of mode settings'' message is inserted. @end defvar X @defvar calc-reset-hook This hook is called after @kbd{M-# 0} (@code{calc-reset}) has reset all modes. The Calc buffer will be the current buffer. @end defvar X @defvar calc-other-modes This variable contains a list of strings. The strings are concatenated at the end of the modes portion of the Calc mode line (after standard modes such as ``Deg'', ``Inv'' and ``Hyp''). Each string should be a short, single word followed by a space. The variable is @code{nil} by default. @end defvar X @defvar calc-mode-map This is the keymap that is used by Calc mode. The best time to adjust it is probably in a @code{calc-mode-hook}. If the Calc extensions package (@file{calc-ext.el}) has not yet been loaded, many of these keys will be bound to @code{calc-missing-key}, which is a command that loads the extensions package and ``retypes'' the key. If your @code{calc-mode-hook} rebinds one of these keys, it will probably be overridden when the extensions are loaded. @end defvar X @defvar calc-digit-map This is the keymap that is used during numeric entry. Numeric entry uses the minibuffer, but this map binds every non-numeric key to @code{calcDigit-nondigit} which generally calls @code{exit-minibuffer} and ``retypes'' the key. @end defvar X @defvar calc-alg-ent-map This is the keymap that is used during algebraic entry. This is mostly a copy of @code{minibuffer-local-map}. @end defvar X @defvar calc-store-var-map This is the keymap that is used during entry of variable names for commands like @code{calc-store} and @code{calc-recall}. This is mostly a copy of @code{minibuffer-local-completion-map}. @end defvar X @defvar calc-edit-mode-map This is the (sparse) keymap used by @code{calc-edit} and other temporary editing commands. It binds @key{RET}, @key{LFD}, and @kbd{C-c C-c} to @code{calc-edit-finish}. @end defvar X @defvar calc-mode-var-list This is a list of variables which are saved by @code{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 @code{equal}) and any non-default variables are written out. @end defvar X @defvar calc-local-var-list This is a list of variables which should be buffer-local to the Calc buffer. Each entry is a variable name (as a Lisp symbol). These variables also have their default values manipulated by the @code{calc} and @code{calc-quit} commands; @pxref{Multiple Calculators}. Since @code{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 @code{make-local-variable} itself. @end defvar X @node Installation, Reporting Bugs, Programming, Top @appendix Installation X @noindent Calc 2.00 comes as a set of GNU Emacs Lisp files, with names like @file{calc.el} and @file{calc-ext.el}, and also as a @file{calc.texinfo} file which can be used to generate both on-line and printed documentation.@refill X To install Calc, just follow these simple steps. If you want more information, each step is discussed at length in the sections below. X @enumerate @item Change (@samp{cd}) to the Calc ``home'' directory. This directory was created when you unbundled the Calc @file{.tar} or @file{.shar} file. X @item Type @samp{make} to install Calc privately for your own use, or type @samp{make install} to install Calc system-wide. This will compile all the Calc component files, modify your @file{.emacs} or the system-wide @file{lisp/default} file to install Calc as appropriate, and format the on-line Calc manual. X @noindent Both variants are shorthand for the following three steps: @itemize @bullet @item @pindex calc-compile @samp{make compile} to run the byte-compiler. X @item @samp{make private} or @samp{make public}, corresponding to @samp{make} and @samp{make install}, respectively. (If @samp{make public} fails because your system doesn't already have a @file{default} or @file{default.el} file, use Emacs or the Unix @code{touch} command to create a zero-sized one first.) X @item @samp{make info} to format the on-line Calc manual. This first tries to use the @file{makeinfo} program; if that program is not present, it uses the Emacs @code{texinfo-format-buffer} command instead. @end itemize @noindent The Unix @code{make} utility looks in the file @file{Makefile} in the current directory to see what Unix commands correspond to the various ``targets'' like @code{install} or @code{public}. If your system doesn't have @code{make}, you will have to examine the @file{Makefile} and type in the corresponding commands by hand. X @item If you ever move Calc to a new home directory, just give the @samp{make private} or @samp{make public} command again in the new directory. X @item Test your installation as described at the end of these instructions. X @item (Optional.) To print a hardcopy of the Calc manual (over 500 pages) or just the Calc Summary (about 20 pages), follow the instructions under ``Printed Documentation'' below. @end enumerate X @noindent Calc is now installed and ready to go! @example X @end example X @appendixsec Upgrading from Calc 1.07 X @noindent If you have Calc version 1.07 or earlier, you will find that Calc 2.00 is organized quite differently. For one, Calc 2.00 is now distributed already split into many parts; formerly this was done as part of the installation procedure. Also, some new functions must be autoloaded and the @kbd{M-#} key must be bound to @code{calc-dispatch} instead of to @code{calc}. X The easiest way to upgrade is to delete your old Calc files and then install Calc 2.00 from scratch using the above instructions. You should then go into your @file{.emacs} or @file{default} file and remove the old @code{autoload} and @code{global-set-key} commands for Calc, since @samp{make public}/@samp{make private} has added new, better ones. X @xref{New for Calc 2.00}, for more information about what has changed since version 1.07. X @ifinfo @example X @end example @end ifinfo @appendixsec The @samp{make public} Command X If you are not the regular Emacs administrator on your system, your account may not be allowed to execute the @samp{make public} command, since the system-wide @file{default} file may be write-protected. If this is the case, you will have to ask your Emacs installer to execute this command. (Just @code{cd} to the Calc home directory and type @samp{make public}.) X The @samp{make private} command adds exactly the same set of commands to your @file{.emacs} file as @samp{make public} adds to @file{default}. If your Emacs installer is concerned about typing this command out of the blue, you can ask her/him instead to copy the necessary text from your @file{.emacs} file. (They will be marked by a comment that says ``Commands added by @code{calc-private-autoloads} on (date and time).'') X @ifinfo @example X @end example @end ifinfo @appendixsec Compilation X @noindent Calc is written in a way that maximizes performance when its code has been byte-compiled; a side effect is that performance is seriously degraded if it @emph{isn't} compiled. Thus, it is essential to compile the Calculator before trying to use it. The function @samp{calc-compile} in the file @file{calc-maint.el} runs the Emacs byte-compiler on all the Calc source files. (Specifically, it runs @kbd{M-x byte-compile-file} on all files in the current directory with names of the form @file{calc*.el}, and also on the file @file{macedit.el}.) X If @code{calc-compile} finds that certain files have already been compiled and have not been changed since, then it will not bother to recompile those files. X The @code{calc-compile} command also pre-builds certain tables, such as the units table (@pxref{The Units Table}) and the built-in rewrite rules (@pxref{Rearranging with Selections}) which Calc would otherwise need to rebuild every time those features were used. X The @samp{make compile} shell command is simply a convenient way to start an Emacs and give it a @code{calc-compile} command. X @ifinfo @example X @end example @end ifinfo @appendixsec Auto-loading X @noindent To teach Emacs how to load in Calc when you type @kbd{M-#} for the first time, add these lines to your @file{.emacs} file (if you are installing Calc just for your own use), or the system's @file{lisp/default} file (if you are installing Calc publicly). The @samp{make private} and @samp{make public} commands, respectively, take care of this. (Note that @samp{make} runs @samp{make private}, and @samp{make install} runs @samp{make public}.) X @smallexample (autoload 'calc-dispatch "calc" "Calculator Options" t) (autoload 'full-calc "calc" "Full-screen Calculator" t) (autoload 'full-calc-keypad "calc" "Full-screen X Calculator" t) (autoload 'calc-eval "calc" "Use Calculator from Lisp") (autoload 'defmath "calc" nil t t) (autoload 'calc "calc" "Calculator Mode" t) (autoload 'quick-calc "calc" "Quick Calculator" t) (autoload 'calc-keypad "calc" "X windows Calculator" t) (autoload 'calc-embedded "calc" "Use Calc from any buffer" t) (autoload 'calc-embedded-activate "calc" "Activate =>'s in buffer" t) (autoload 'calc-grab-region "calc" "Grab region of Calc data" t) (autoload 'calc-grab-rectangle "calc" "Grab rectangle of data" t) @end smallexample X @vindex load-path Unless you have installed the Calc files in Emacs' main @file{lisp/} directory, you will also have to add a command that looks like the following to tell Emacs where to find them. In this example, we have put the files in directory @file{/usr/gnu/src/calc-2.00}. X @smallexample (setq load-path (append load-path (list "/usr/gnu/src/calc-2.00"))) @end smallexample X @noindent The @samp{make public} and @samp{make private} commands also do this (they use the then-current directory as the name to add to the path). If you move Calc to a new location, just repeat the @samp{make public} or @samp{make private} command to have this new location added to the @code{load-path}.@refill X The @code{autoload} command for @code{calc-dispatch} is what loads @file{calc.elc} when you type @kbd{M-#}. It is the only @code{autoload} that is absolutely necessary for Calc to work. The others are for commands and features that you may wish to use before typing @kbd{M-#} for the first time. In particular, @code{full-calc} and @code{full-calc-keypad} are autoloaded to support ``standalone'' operation (@pxref{Standalone Operation}), @code{calc-eval} and @code{defmath} are autoloaded to allow other Emacs Lisp programs to use Calc facilities (@pxref{Calling Calc from Your Programs}), and @code{calc-embedded-activate} is autoloaded because some Embedded Mode files may call it as soon as they are read into Emacs (@pxref{Assignments in Embedded Mode}). X @ifinfo @example X @end example @end ifinfo @appendixsec Finding Component Files X There is no need to write @code{autoload} commands that point to all the various Calc component files like @file{calc-misc.elc} and @file{calc-alg.elc}. The main file, @file{calc.elc}, contains all the necessary @code{autoload} commands for these files. X (Actually, to conserve space @file{calc.elc} only autoloads a few of the component files, plus @file{calc-ext.elc}, which in turn autoloads the rest of the components. This allows Calc to load a little faster in the beginning, but the net effect is the same.) X This autoloading mechanism assumes that all the component files can be found on the @code{load-path}. The @samp{make public} and @samp{make private} commands take care of this, but Calc has a few other strategies in case you have installed it in an unusual way. X If, when Calc is loaded, it is unable to find its components on the @code{load-path} it is given, it checks the file name in the original @code{autoload} command for @code{calc-dispatch}. If that name included directory information, Calc adds that directory to the @code{load-path}: X @example (autoload 'calc-dispatch "calc-2.00/calc" "Calculator" t) @end example X @noindent Suppose the directory @file{/usr/gnu/src/emacs/lisp} is on the path, and SHAR_EOF true || echo 'restore of calc.texinfo failed' fi echo 'End of part 54' echo 'File calc.texinfo is continued in part 55' echo 55 > _shar_seq_.tmp exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.