Go to the first, previous, next, last section, table of contents.
Maxima provides a
do loop for iteration, as well as more primitive
constructs such as
backtrace() prints the entire call stack.
backtrace (n) prints the n most recent
functions, including the currently active function.
backtrace can be called from a script, a function, or the interactive prompt
(not only in a debugging context).
backtrace()prints the entire call stack.
(%i1) h(x) := g(x/7)$ (%i2) g(x) := f(x-11)$ (%i3) f(x) := e(x^2)$ (%i4) e(x) := (backtrace(), 2*x + 13)$ (%i5) h(10); #0: e(x=4489/49) #1: f(x=-67/7) #2: g(x=10/7) #3: h(x=10) 9615 (%o5) ---- 49
backtrace (n)prints the n most recent functions, including the currently active function.
(%i1) h(x) := (backtrace(1), g(x/7))$ (%i2) g(x) := (backtrace(1), f(x-11))$ (%i3) f(x) := (backtrace(1), e(x^2))$ (%i4) e(x) := (backtrace(1), 2*x + 13)$ (%i5) h(10); #0: h(x=10) #0: g(x=10/7) #0: f(x=-67/7) #0: e(x=4489/49) 9615 (%o5) ---- 49
dostatement is used for performing iteration. Due to its great generality the
dostatement will be described in two parts. First the usual form will be given which is analogous to that used in several other programming languages (Fortran, Algol, PL/I, etc.); then the other features will be mentioned.
There are three variants of this form that differ only in their terminating conditions. They are:
for variable: initial_value step increment thru limit do body
for variable: initial_value step increment while condition do body
for variable: initial_value step increment unless condition do body
step may be given after the termination condition
initial_value, increment, limit, and body can be any
expressions. If the increment is 1 then "
step 1" may be omitted.
The execution of the
do statement proceeds by first assigning the
initial_value to the variable (henceforth called the
control-variable). Then: (1) If the control-variable has exceeded the
limit of a
thru specification, or if the condition of the
true, or if the condition of the
false then the
terminates. (2) The body is evaluated. (3) The increment is added to
the control-variable. The process from (1) to (3) is performed
repeatedly until the termination condition is satisfied. One may also
give several termination conditions in which case the
when any of them is satisfied.
In general the
thru test is satisfied when the control-variable is
greater than the limit if the increment was non-negative, or when the
control-variable is less than the limit if the increment was negative.
The increment and limit may be non-numeric expressions as long as this
inequality can be determined. However, unless the increment is
syntactically negative (e.g. is a negative number) at the time the
statement is input, Maxima assumes it will be positive when the
executed. If it is not positive, then the
do may not terminate
Note that the limit, increment, and termination condition are
evaluated each time through the loop. Thus if any of these involve
much computation, and yield a result that does not change during all
the executions of the body, then it is more efficient to set a
variable to their value prior to the
do and use this variable in the
The value normally returned by a
do statement is the atom
However, the function
return may be used inside the body to exit the
do prematurely and give
it any desired value.
Note however that a
return within a
occurs in a
block will exit only the
do and not the
block. Note also
go function may not be used to exit from a
do into a
The control-variable is always local to the
do and thus any
variable may be used without affecting the value of a variable with
the same name outside of the
do. The control-variable is unbound
(%i1) for a:-3 thru 26 step 7 do display(a)$ a = - 3 a = 4 a = 11 a = 18 a = 25
(%i1) s: 0$ (%i2) for i: 1 while i <= 10 do s: s+i; (%o2) done (%i3) s; (%o3) 55
Note that the condition
while i <= 10
is equivalent to
unless i > 10 and also
(%i1) series: 1$ (%i2) term: exp (sin (x))$ (%i3) for p: 1 unless p > 7 do (term: diff (term, x)/p, series: series + subst (x=0, term)*x^p)$ (%i4) series; 7 6 5 4 2 x x x x x (%o4) -- - -- - -- - -- + -- + x + 1 90 240 15 8 2
which gives 8 terms of the Taylor series for
(%i1) poly: 0$ (%i2) for i: 1 thru 5 do for j: i step -1 thru 1 do poly: poly + i*x^j$ (%i3) poly; 5 4 3 2 (%o3) 5 x + 9 x + 12 x + 14 x + 15 x (%i4) guess: -3.0$ (%i5) for i: 1 thru 10 do (guess: subst (guess, x, 0.5*(x + 10/x)), if abs (guess^2 - 10) < 0.00005 then return (guess)); (%o5) - 3.162280701754386
This example computes the negative square root of 10 using the
Newton- Raphson iteration a maximum of 10 times. Had the convergence
criterion not been met the value returned would have been
Instead of always adding a quantity to the control-variable one
may sometimes wish to change it in some other way for each iteration.
In this case one may use
next expression instead of
This will cause the control-variable to be set to the
result of evaluating expression each time through the loop.
(%i6) for count: 2 next 3*count thru 20 do display (count)$ count = 2 count = 6 count = 18
As an alternative to
for variable: value ...do... the syntax
for variable from value ...do... may be used. This permits the
from value to be placed after the step or next value or after the
termination condition. If
from value is omitted then 1 is used as
the initial value.
Sometimes one may be interested in performing an iteration where the control-variable is never actually used. It is thus permissible to give only the termination conditions omitting the initialization and updating information as in the following example to compute the square-root of 5 using a poor initial guess.
(%i1) x: 1000$ (%i2) thru 20 do x: 0.5*(x + 5.0/x)$ (%i3) x; (%o3) 2.23606797749979 (%i4) sqrt(5), numer; (%o4) 2.23606797749979
If it is desired one may even omit the termination conditions
entirely and just give
do body which will continue to evaluate the
body indefinitely. In this case the function
return should be used to
terminate execution of the
(%i1) newton (f, x):= ([y, df, dfx], df: diff (f ('x), 'x), do (y: ev(df), x: x - f(x)/y, if abs (f (x)) < 5e-6 then return (x)))$ (%i2) sqr (x) := x^2 - 5.0$ (%i3) newton (sqr, 1000); (%o3) 2.236068027062195
return, when executed, causes the current value of
x to be returned as the value of the
block is exited and
this value of the
do is returned as the value of the
block because the
do is the last statement in the block.)
One other form of the
do is available in Maxima. The syntax is:
for variable in list end_tests do body
The elements of list are any expressions which will
successively be assigned to the variable on each iteration of the
body. The optional termination tests end_tests can be used to terminate execution of
do; otherwise it will terminate when the list is exhausted or when
return is executed in the body. (In fact, list may be any
non-atomic expression, and successive parts are taken.)
(%i1) for f in [log, rho, atan] do ldisp(f(1))$ (%t1) 0 (%t2) rho(1) %pi (%t3) --- 4 (%i4) ev(%t3,numer); (%o4) 0.78539816
[expr_n](a list) if no error occurs. If an error occurs in the evaluation of any argument,
errcatchprevents the error from propagating and returns the empty list
without evaluating any more arguments.
is useful in
batch files where one suspects an error might occur which
would terminate the
batch if the error weren't caught.
error is set to a list describing the error.
The first element of
error is a format string,
which merges all the strings among the arguments expr_1, ..., expr_n,
and the remaining elements are the values of any non-string arguments.
errormsg() formats and prints
This is effectively reprinting the most recent error message.
errorholds the message, and
errormsgformats and prints it.
dofor a description of Maxima's iteration facilities.
blockto transfer control to the statement of the block which is tagged with the argument to
go. To tag a statement, precede it by an atomic argument as another statement in the
block. For example:
block ([x], x:1, loop, x+1, ..., go(loop), ...)
The argument to
go must be the name of a tag appearing in the same
block. One cannot use
go to transfer to tag in a
block other than the
one containing the
ifstatement is used for conditional execution. The syntax is:
if <condition> then <expr_1> else <expr_2>
The result of an
if statement is expr_1 if condition is
expr_2 otherwise. expr_1 and expr_2 are any
Maxima expressions (including nested
if statements), and condition is
an expression which evaluates to
false and is composed of
relational and logical operators which are as follows:
Operation Symbol Type less than < relational infix less than <= or equal to relational infix equality (syntactic) = relational infix negation of = # relational infix equality (value) equal relational function negation of equal notequal relational function greater than >= or equal to relational infix greater than > relational infix and and logical infix or or logical infix not not logical prefix
lambdaform of n arguments.
maperror - if
false will cause all of the mapping functions to
(1) stop when they finish going down the shortest expi if not all of
the expi are of the same length and (2) apply fn to [exp1, exp2,...]
if the expi are not all the same type of object. If
then an error message will be given in the above two instances.
One of the uses of this function is to
map a function (e.g.
onto each term of a very large expression where it ordinarily wouldn't
be possible to use the function on the entire expression due to an
exhaustion of list storage space in the course of the computation.
(%i1) map(f,x+a*y+b*z); (%o1) f(b z) + f(a y) + f(x) (%i2) map(lambda([u],partfrac(u,x)),x+1/(x^3+4*x^2+5*x+2)); 1 1 1 (%o2) ----- - ----- + -------- + x x + 2 x + 1 2 (x + 1) (%i3) map(ratsimp, x/(x^2+x)+(y^2+y)/y); 1 (%o3) y + ----- + 1 x + 1 (%i4) map("=",[a,b],[-0.5,3]); (%o4) [a = - 0.5, b = 3]
trueif and only if expr is treated by the mapping routines as an atom. "Mapatoms" are atoms, numbers (including rational numbers), and subscripted variables.
false, causes all of the mapping functions, for example
map (f, expr_1, expr_2, ...))
to (1) stop when they finish
going down the shortest expi if not all of the expi are of the same
length and (2) apply
[expr_1, expr_2, ...] if the
expr_i are not all
the same type of object.
true then an error message
is displayed in the above two instances.
maplist differs from
map (f, expr_1, ..., expr_n)
which returns an expression with the same main operator as expr_i has
(except for simplifications and the case where
map does an
true, an error message is displayed
whenever the predicate of an
if statement or an
is function fails to
evaluate to either
unknown is returned
instead in this case. The
prederror: false mode is not supported in
maybe is supported in translated code.
blockfor more information.
(%i1) exp:(a^2+2*a+1)*y + x^2$ (%i2) scanmap(factor,exp); 2 2 (%o2) (a + 1) y + x
Note the way in which
scanmap applies the given function
factor to the
constituent subexpressions of expr; if another form of expr is presented
scanmap then the result may be different. Thus,
%o2 is not
scanmap is applied to the expanded form of exp:
(%i3) scanmap(factor,expand(exp)); 2 2 (%o3) a y + 2 a y + y + x
Here is another example of the way in which
applies a given function to all subexpressions, including exponents:
(%i4) expr : u*v^(a*x+b) + c$ (%i5) scanmap('f, expr); f(f(f(a) f(x)) + f(b)) (%o5) f(f(f(u) f(f(v) )) + f(c))
scanmap (f, expr, bottomup) applies f to expr in a
bottom-up manner. E.g., for undefined
scanmap(f,a*x+b) -> f(a*x+b) -> f(f(a*x)+f(b)) -> f(f(f(a)*f(x))+f(b)) scanmap(f,a*x+b,bottomup) -> f(a)*f(x)+f(b) -> f(f(a)*f(x))+f(b) -> f(f(f(a)*f(x))+f(b))
In this case, you get the same answer both ways.
throwis used with
catchas a nonlocal return mechanism.
f is be the name of a function of n arguments or a lambda expression of n arguments. The arguments a_1, ..., a_n may be lists or nonlists. List arguments may have different lengths. Arguments other than lists are treated as lists of length 1 for the purpose of constructing the outer product.
The result of applying f to the outer product is organized as a nested list. The depth of nesting is equal to the number of list arguments (arguments other than lists do not contribute a nesting level). A list at nesting depth k has the same length as the k'th list argument.
outermap evaluates its arguments.
(%i1) f (x, y) := x - y$ (%i2) outermap (f, [2, 3, 5], [a, b, c, d]); (%o2) [[2 - a, 2 - b, 2 - c, 2 - d], [3 - a, 3 - b, 3 - c, 3 - d], [5 - a, 5 - b, 5 - c, 5 - d]] (%i3) outermap (lambda ([x, y], y/x), [55, 99], [Z, W]); Z W Z W (%o3) [[--, --], [--, --]] 55 55 99 99 (%i4) g: lambda ([x, y, z], x + y*z)$ (%i5) outermap (g, [a, b, c], %pi, [11, 17]); (%o5) [[a + 11 %pi, a + 17 %pi], [b + 11 %pi, b + 17 %pi], [c + 11 %pi, c + 17 %pi]] (%i6) flatten (%); (%o6) [a + 11 %pi, a + 17 %pi, b + 11 %pi, b + 17 %pi, c + 11 %pi, c + 17 %pi]
Go to the first, previous, next, last section, table of contents.