Maxima Special operator
do
The do
statement is used for performing iteration. Due to its
great generality the do
statement 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
(Alternatively, the step
may be given after the termination condition
or limit.)
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
unless
is true
, or if the condition of the while
is false
then the do
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 do
terminates 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 do
statement is input, Maxima assumes it will
be positive when the do
is executed. If it is not positive,
then the do
may not terminate properly.
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
do
form.
The value normally returned by a do
statement is the atom
done
. 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 do
that occurs in a block
will exit only the do
and not the
block
. Note also that the go
function may not be used
to exit from a do
into a surrounding block
.
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
after the do
terminates.
(%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 thru 10
.
(%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 e^sin(x)
.
(%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 done
.
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 step increment
.
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 do
.
(%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
(Note that return
, when executed, causes the current value of
x
to be returned as the value of the do
. 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 <span class="replaceable">variable</span> in <span class="replaceable">list</span> <span class="replaceable">end_tests</span> do <span class="replaceable">body</span>
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 the do
; otherwise it will
terminate when the list is exhausted or when a return
is
executed in the body. (In fact, list
may be any
non-atomic expression, and successive parts are taken.)