Go to the first, previous, next, last section, table of contents.
MACSYMA provides a DO loop for iteration, as well as more primitive constructs such as GO.
(Alternatively, the STEP may be given after the termination condition or limit.) The 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, MACSYMA 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, as every statement in MACSYMA returns a value. 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.
(C1) FOR A:-3 THRU 26 STEP 7 DO LDISPLAY(A)$ (E1) A = -3 (E2) A = 4 (E3) A = 11 (E4) A = 18 (E5) A = 25
The function LDISPLAY generates intermediate labels; DISPLAY does not.
(C6) S:0$ (C7) FOR I:1 WHILE I<=10 DO S:S+I; (D7) DONE (C8) S; (D8) 55
Note that the condition in C7 is equivalent to UNLESS I > 10 and also THRU 10
(C9) SERIES:1$ (C10) TERM:EXP(SIN(X))$ (C11) FOR P:1 UNLESS P>7 DO (TERM:DIFF(TERM,X)/P, SERIES:SERIES+SUBST(X=0,TERM)*X^P)$ (C12) SERIES; 7 6 5 4 2 (D12) X X X X X -- - -- - -- - -- + -- + X + 1 96 240 15 8 2 which gives 8 terms of the Taylor series for e^sin(x). (C13) POLY:0$ (C14) FOR I:1 THRU 5 DO FOR J:I STEP -1 THRU 1 DO POLY:POLY+I*X^J$ (C15) POLY; 5 4 3 2 (D15) 5 X + 9 X + 12 X + 14 X + 15 X (C16) GUESS:-3.0$ (C17) FOR I:1 THRU 10 DO (GUESS:SUBST(GUESS,X,.5*(X+10/X)), IF ABS(GUESS^2-10)<.00005 THEN RETURN(GUESS)); (D17) - 3.1622807
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". Additional Forms of the DO Statement 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.
(C1) 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.
(C1) X:1000 (C2) THRU 10 WHILE X#0.0 DO X:.5*(X+5.0/X)$ (C3) X; (D3) 2.236068
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.
(C1) NEWTON(F,GUESS):= BLOCK([NUMER,Y], LOCAL(DF), NUMER:TRUE, DEFINE(DF(X),DIFF(F(X),X)), DO (Y:DF(GUESS), IF Y=0.0 THEN ERROR("Derivative at:",GUESS," is zero."), GUESS:GUESS-F(GUESS)/Y, IF ABS(F(GUESS))<5.0E-6 THEN RETURN(GUESS)))$ (C2) SQR(X):=X^2-5.0$ (C3) NEWTON(SQR,1000); (D3) 2.236068
(Note that RETURN, when executed, causes the current value of GUESS 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 MACSYMA. The syntax is:
FOR variable IN list [end-tests] DO body
The members of the list are any expressions which will successively be assigned to the variable on each iteration of the body. The optional 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.)
(C1) FOR F IN [LOG, RHO, ATAN] DO LDISP(F(1))$ (E1) 0 (E2) RHO(1) %PI (E3) --- 4 (C4) EV(E3,NUMER); (D4) 0.78539816
. 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 GO.
IF condition THEN expression1 ELSE expression2.
The result of an IF statement is expression1 if condition is true and expression2 if it is false. expression1 and expression2 are any MACSYMA expressions (including nested IF statements), and condition is an expression which evaluates to TRUE or FALSE and is composed of relational and logical operators which are as follows:
Operator name Symbol Type greater than > relational infix equal to = , EQUAL " " not equal to # " " less than < " " greater than >= or equal to " " less than <= or equal to " " and AND logical infix or OR " " not NOT logical prefix
(C1) MAP(F,X+A*Y+B*Z); (D1) F(B Z) + F(A Y) + F(X) (C2) MAP(LAMBDA([U],PARTFRAC(U,X)),X+1/(X^3+4*X^2+5*X+2)); 1 1 1 (D2) ----- - ----- + -------- + X X + 2 X + 1 2 (X + 1) (C3) MAP(RATSIMP, X/(X^2+X)+(Y^2+Y)/Y); 1 (D3) Y + ----- + 1 X + 1 (C4) MAP("=",[A,B],[-0.5,3]); (D4) [A = - 0.5, B = 3]
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 MAPERROR is TRUE then an error message will be given in the above two instances.
(C1) EXP:(A^2+2*A+1)*Y + X^2$ (C2) SCANMAP(FACTOR,EXP); 2 2 (D2) (A + 1) Y + X
Note the way in which SCANMAP applies the given function FACTOR to the constituent subexpressions of exp; if another form of exp is presented to SCANMAP then the result may be different. Thus, D2 is not recovered when SCANMAP is applied to the expanded form of exp:
(C3) SCANMAP(FACTOR,EXPAND(EXP)); 2 2 (D3) A Y + 2 A Y + Y + X
Here is another example of the way in which SCANMAP recursively applies a given function to all subexpressions, including exponents:
(C4) EXPR : U*V^(A*X+B) + C$ (C5) SCANMAP('F, EXPR); F(F(F(A) F(X)) + F(B)) (D5) F(F(F(U) F(F(V) )) + F(C))
SCANMAP(function,expression,BOTTOMUP) applies function to exp in a "bottom-up" manner. E.g., for undefined F,
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.
Go to the first, previous, next, last section, table of contents.