.EQ
delim @@
.EN
.so eqnfix
.na
.fi
.Lc Data Types in MACSYMA 2
.pp
This chapter describes the data types used by
ma .
OUtline:
Constants
Numbers
integers
rational
float
bigfloat
complex
constant symbols
boolean
pi, e, ...
strings
file names
indeterminates
variables
functions
expressions
general mathematical representation
operators, operands, parsing
CRE form
Poisson form
matrices
lists
, $fun,
or $fun functions (sec. $ref) to kill an array element or the
entire array, the associated function will never be called a second time on the
same arguments. Thus the user should be aware that even if he redefines the
associated function, those values which already exist will stay around. Of
course individual array elements can be changed by assignment at any time.
These associated functions are defined with the := operator. Their definition
looks exactly the same as ordinary function definitions, except that the
parameters in the left side of the definition are enclosed in brackets instead
of parentheses.
In order to use a subscripted variable as a single entity without it
being an array and without ever assigning a value to it, it should be
prefixed by an apostrophe to avoid it being confused with a non-subscripted
variable of the same name. For example SUBST(0,W,W+'W[0]).
The MACSYMA variable $var is a list of all the arrays that have been allocated,
both declared and undeclared.
$fun $see may be used to display the definition of an array
associated function.
$fun $see may be used to find out whether an array is
declared or undeclared, how large it is, how many subscripts it has, and which elements
have values in the case of an undeclared array.
.Eb
(C1) A[N]:=N*A[N-1]$
(C2) A[0]:1$
(C3) A[5];
(D3) 120
(C4) A[N]:=N$
(C5) A[6];
(D5) 6
(Note that the definition in C4 is being used because
A[6] has no value up to this time.)
(C6) A[4];
(D6) 24
(Since A[4] was assigned a value as a result of A[5]
being computed, the new definition is not used.)
.Ee
If one is going to define a recursive function which is to be called several
times then if may be more efficient to use an array with an associated function
for initialization. The reason is that once an element is computed it is stored
and thus need not be computed again whereas with a non-subscripted function, each recursive call
may cause a repeat of a past computation.
.sh 2 "Lambda Notation *"
.pp
Note that this section has an asterisk: avoid on first reading.
.pp
Lambda*
.(f
* Blame it on the logician A. Church, and John McCarthy who
picked this up for programming languages.
.)f
notation provides a convention for establishing
correspondence between the formal and actual
parameters of a function, and the function "body" to be evaluated.
Lambda notation is useful in
ma
primarily in construction and use of "anonymous" un-named functions
for use in limited circumstances. It can also be used by the purist
to define functions by creating lambda-expressions, and giving them
names!
.Eb
(c1) f:lambda([x,y,z],r(x^2)+s(y^2)+v(z^2));
.EQ (d1)
size -2 { lambda ( [ x , y, z ] , v ( z sup 2 )~+~ s ( y sup 2 ) ~+~ r (x sup 2 )) }
.EN
(c2) f(1,2,a);
.EQ (d2)
FIX THIS UP
.EN
.Ee
ma also permits operators to be used in a functional notation; however, in order
not to get a syntax error they must be surrounded by "s.
.Eb
(C3) "+"(1,2,A);
(D3) A + 3
.Ee
MOVE THIS TO NEXT CHAPTER
.subsec ("Subscripted Functions (Arrays of Functions)",subscripted!functions,1)
It is possible for the value of an array element to be a lambda expression.
Thus if the assignment F[1]:LAMBDA([X],X^2+1) were performed, then F[1] could be
used in the ordinary prefix functional sense with its arguments following in
parentheses, e.g. F[1](3) would yield the value 10. There is an alternative
syntax available for assigning a lambda expression to an array which introduces
the notion of a "subscripted function". In the above case one could also type
F[1](X):=X^2+1 and this would be entirely equivalent. Other elements of the
array could be assigned different lambda expressions (or any MACSYMA
expressions). If there is an algorithm for computing the different functions to
be stored in an array on the basis of the subscripts alone, then one may use an
associated function. For example, F[K]:=LAMBDA([X],X^K+1). Again an alternative
syntax of F[K](X):=X^K+1 may be used. The left side of the definition consists
of the function name followed by the subscripts, enclosed in brackets, followed
by the arguments, enclosed in parentheses. The subscripts (which are not
evaluated at definition time) must be either all numeric or all symbolic. Note
that subscripted functions are treated exactly like arrays so all of the
information in sec. $ref applies. In particular when a subscripted function is
referenced, the element is immediately retrieved and applied to its arguments if
it exists; otherwise it is computed (this time only) and then applied.
Consequently, two evaluations of the definition are performed. Thus consider
the definition F[K](E):=COEFF(E,X,K) and the call F[2](3*X^2-1). Although the
user may have thought that this would return the coefficient of X^2 in 3*X^2-1,
i.e. 3, it will return 0. The reason is that F[2] is first computed by
evaluating the definition yielding 0, since E has not been bound at this time.
Note that F[K](E):= SUBST(K,'J,'(COEFF(E,X,J))) would return the desired result as would F(K,E):=COEFF(E,X,K). Thus the user
should be clear about the distinction between subscripted functions (a type of
array) and ordinary functions. Also a subscripted function should not be
redefined without $fun'ing or $fun'ing it first; otherwise the
elements which have already been stored will be used.
The $var list $see also includes subscripted functions.
The function $fun $see may also be used on subscripted
functions.
.example
(C1) T[N](X):=RATSIMP(2*X*T[N-1](X)-T[N-2](X))$
.scon
1This generates the Chebyshev polynomials.*
.scon
(C2) T[0](X):=1$
(C3) T[1](X):=X$
(C4) T[4](Y);
.begin group
4 2
(D4) 8 Y - 8 Y + 1
.end
(C5) G[N](X):=SUM(EV(X),I,N,N+2)$
(C6) H(N,X):=SUM(EV(X),I,N,N+2)$
.BEGIN GROUP
(C7) G[2](I^2);
2
(D7) 3 I
(C8) H(2,I^2);
(D8) 29
.end
.end
.scon
The following illustrates a definition for the Legendre polynomials.
.example
(C9) P[N](X):=RATSIMP(1/(2^N*N!)*DIFF((X^2-1)^N,X,N))$
(C10) Q(N,X):=RATSIMP(1/(2^N*N!)*DIFF((X^2-1)^N,X,N))$
.BEGIN GROUP
(C11) P[2];
2
3 X - 1
(D11) LAMBDA([X], --------)
2
(C12) P[2](Y+1);
2
3 (Y + 1) - 1
(D12) --------------
2
.END
.BEGIN GROUP
(C13) Q(2,Y+1);
2
3 Y + 6 Y + 2
(D13) --------------
2
.END
(C14) P[2](5);
(D14) 37
.begin group
(C15) Q(2,5);
5
attempt to differentiate wrt a number
.end
.end
.subsec (Additional Information About Functions,functions!continued,1)
In order to pass a function as an argument to another function you need only
give its name in the argument list of the call. It may then be used in the
called function by following the name of the corresponding formal parameter
with a parenthesized list of arguments. Subscripted functions $see are passed by
giving the name followed by the subscripts in brackets. Arrays can be passed by
giving the name of the array in the argument list and they can be referenced by
subscripting the corresponding formal parameter.
When passing names of functions or arrays one must take care that there is no
atomic variable with the same name which is bound because then that value rather
than the name will be passed. In this case the name should be preceded by a '
$see to prevent it from being evaluated.
In order to assign to a formal parameter of a function so that the
corresponding actual parameter gets changed (and remains changed) when the
function is exited, then the :: operator rather than the : operator should be
used.
.example group
(C7) F[I,J](X,Y):=X^I + Y^J;
I J
(D7) F (X, Y) := X + Y
I, J
(C8) G(FUN,ARG1,ARG2):=PRINT(FUN," APPLIED TO ",ARG1," AND ",
ARG2," IS ",FUN(ARG1,ARG2))$
.begin group
(C9) G(F[2,1],SIN(%PI),2*A);
2
LAMBDA([X,Y],Y+X ) APPLIED TO 0 AND 2 A IS 2 A
(D9) 2 A
.end
.end
.sh 2 Lists
.pp
Lists are representations for ordered sets of elements.
These elements may be any
ma
expressions. The external representation is
as a sequence of items separated by commas and enclosed in square
brackets. An empty list is [].
Many commands which must return a collection of answers use
lists as the basis for the return value.
.pp
If the value of a variable is a list, its
elements may be accessed for value, or changed, by using
subscript notation. For example,
.Eb
(c1) l:[a,b,c,d];
.EQ (d1)
size -2 { [a , b, c, d]}
.EN
(c2) l[3]:q$
(c3) l;
.EQ (d3)
size -2 { [ a , b, q , d ]}
.EN
.Ee
.pp
For certain commands,lists are used as a representation for mathematical
vectors (row or column matrices).
Lists are sometimes used as arguments to
ma
commands (e.g.\fImatrix, solve,\fP etc.).
Operations on lists
such
as deleting elements, selecting an element, testing for membership in
a list, and so on,
are give in section ??. Because lists provide a model for ordered
n-tuples, and lists of lists (etc.) are acceptable structures, they
are very general. The Lisp programming language underlying
ma
uses this notion very heavily.
.sh 2 Matrices
.pp
A matrix is a set of elements in a rectangular indexed arrangement. The
index sets are integers beginning at 1.
It is represented internally using a list of lists.
By convention, the top level of lists are "rows", and each
row is of the same length (the number of columns).
Matrices may be constructed by using the function
.Lf matrix "'row1_list, ['row2_list, ... ]"
.We
row1_list etc are lists of the same length.
.Re
a matrix
.No you should give the matrix a name by assignment, or use the linelabel.
.Ex
m:matrix([a,b],[c,d])
.pp
The functions
.I entermatrix
and
.I genmatrix
may also be used to construct a matrix. See section ?? on matrix functions.
.PP
THIS GOES TO NEXT CHAPTER
The operators + , - , * , and / may be used between two matrices and take effect
elementwise. (A matrix minus itself gives the zero matrix of the same size.)
They may also be used between a scalar* and a matrix and the scalar will be
operated on with each element of the matrix.
.(f *In
ma
a scalar is an expression consisting of numbers, constants, and atoms declared scalar.
.)f
.pp
Matrix multiplication is signified by using the dot operator (non-commutative
product). Raising a matrix to a power (multiplying it by itself) is
accomplished by use of the ^^ operator. That is, M.M is equivalent to M^^2.
The inverse of a matrix may be obtained by using a negative exponent, i.e.
M^^-1.
If the switch $var is TRUE then
.ip 1.
Lists will behave arithmetically: they can be added to one another, etc.
.ip 2.
In matrix operations they can be used as row or column vectors and will be
converted to such when necessary.
An element of a matrix may be referenced by subscripting the matrix as
with arrays but the same name should not be used to stand for both a
matrix and an array, or the array use will take precedence.
There are many functions for operating on matrices as well as many
options which can be set to give the user much flexibility and control
over matrix operations (these are described in sec.
$ref). If a matrix is too wide to be displayed all
at once, it is displayed column by column or as a list of lists.
.example
(C1) M:MATRIX([A,0],[B,1]);
.begin group
[ A 0 ]
(D1) [ ]
[ B 1 ]
.end
(C2) M[1,1]*%;
.begin group
[ 2 ]
(D2) [ A 0 ]
[ ]
[ A B A ]
.end
(C3) M*M;
.begin group
[ 2 ]
[ A 0 ]
(D3) [ ]
[ 2 ]
[ B 1 ]
.end
(C4) M.M;
.begin group
[ 2 ]
(D4) [ A 0 ]
[ ]
[ A B + B 1 ]
.end
(C5) D2-D4+1;
.begin group
[ 1 1 ]
(D5) [ ]
[ 1 - B A ]
.end
(C6) M^-1;
Division by 0
.begin group
(C7) M^^-1;
[ 1 ]
[ - 0 ]
[ A ]
(D7) [ ]
[ B ]
[ - - 1 ]
[ A ]
.end
(C8) [X,Y].M;
(D8) [ B Y + A X Y]
.end
.sec (Equations)
An equation is formed in MACSYMA simply by using an equal sign between any two
expressions. Equations may be added or subtracted, and they may be multiplied
or divided by any expression. They may be operated on just
as any MACSYMA expression can be and may serve as arguments to functions.
.example
(C1) X+1=Y^2$
(C2) X-1=2*Y+1$
(C3) D1+D2;
.begin group
2
(D3) 2 X = Y + 2 Y + 1
.end
(C4) D1/Y;
.begin group
X + 1
(D4) ----- = Y
Y
.end
(C5) 1/%;
.begin group
Y 1
(D5) ----- = -
X + 1 Y
.end
.end
.sec (IF Statement,if!statement,1)
The $fun statement is used for conditional execution. The syntax is
.begin turn on "_"
_IF 2condition* THEN 2expression1* ELSE 2expression2*.
.end
.scon
The result of an IF statement is 2expression1* if 2condition* is
true and 2expression2* if it is false. 2expression1* and
2expression2* are any MACSYMA expressions (including nested IF
statements), and 2condition1 is an expression (known as a
"predicate") which evaluates to
TRUE or FALSE and is composed of relational and logical operators
which are as follows:
.example group turn on "\"; narrow 8; tabs 4, 24, 32, 36, 48, 56;
\1Operator 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
.end
The relational operators all have equal priorities which are less than the
priorities of the arithmetic operators and greater than that of the logical
operators. The priority of NOT is greater than that of AND which is greater
than that of OR. The difference between "=" and EQUAL is discussed in sec. $ref.
If the ELSE clause is omitted, this will be the same as if
ELSE FALSE were specified. In order to have several expressions evaluated after the
THEN or ELSE clauses, the expressions may be enclosed in a compound statement $see but care should be taken to return the desired
value. The switch $var determines the action taken if a clause is not universally true or universally false $see.
.example
(C1) FIB[N]:= IF N=1 OR N=2 THEN 1
ELSE FIB[N-1]+FIB[N-2]$
(C2) FIB[1]+FIB[2];
(D2) 2
(C3) FIB[3];
(D3) 2
(C4) FIB[5];
(D4) 5
(C5) ETA(MU,NU):= IF MU=NU THEN MU
ELSE IF MU>NU THEN MU-NU
ELSE MU+NU$
(C6) ETA(5,6);
(D6) 11
(C7) ETA(ETA(7,7),ETA(1,2));
(D7) 4
(C8) IF NOT 5>=2 AND 6<=5 OR 4+1>3 THEN A ELSE B;
(D8) A
.end
.sec (Compound Statements,compound!statement,1)
In order to execute a sequence of statements in a context where a single
statement is permitted then the user may group these statements into a 2compound statement1 by separating them with commas and enclosing the whole group in
parentheses. The value of a compound statement is the value of the last
statement in the group.
Compound statements are also useful for grouping together a sequence of related calculations
when a computation cannot easily be expressed in a single MACSYMA statement.
.example group
(C1) IF X=Y THEN (X:X+1, Y:Y-1)
ELSE (S:0, FOR I:1 THRU X DO (S:S+F(I), Y:Y-G(Y)))$
.end
.sec (Program Blocks,program!blocks,1)
Blocks in MACSYMA are somewhat analogous to subroutines in FORTRAN or
procedures in ALGOL or PL/I. Blocks are like compound statements but
also enable the user to tag statements within the block and to assign
"dummy" variables to values which are local to the block. The syntax
is:
.inline function(BLOCK,|[v1, ... vk], statement1,..., statementj|)
.scon
where the 2vi* are atomic variables, possibly with initial assignments
(see below) which are local to the BLOCK and
the 2statements* are any MACSYMA expressions. If no variables are
to be made local then the list may be omitted.
A block uses these local variables to avoid conflict with variables
having the same names used outside of the block (i.e. global to the
block) and to free up storage used by local computation upon exit
from the block. In this case, upon entry to the block, the global values are
saved onto a stack and are inaccessible while the block is being
executed. The local variables then are unbound so that they evaluate
to themselves. They may be bound to arbitrary values within the block
but when the block is exited the saved values are restored to these
variables. The values created in the block for these local variables
are lost. Where a variable is used within a block and is not in the
list of local variables for that block it will be the same as the
variable used outside of the block.
In order to save and restore other local properties besides VALUE,
namely ARRAY (except for complete arrays - $see),
FUNCTION, DEPENDENCIES, ATVALUE, MATCHDECLARE, ATOMGRAD, CONSTANT, SCALAR and
NONSCALAR$$All of these properties except for FUNCTION are related
more closely to the use of the name as a variable rather than as a
function.* $see, the function $fun
should be used inside of the block with arguments being the names of
the variables $see.
The value of the block is the value of the last statement or the value
of the argument to the function $fun which may be used to exit
explicitly from the block. The function $fun may be used to
transfer control to the statement of the block that 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:X+1,...,GO(LOOP),...). The argument to GO must
be the name of a tag appearing within the BLOCK. One cannot use GO to
transfer to a tag in a BLOCK other than the one containing the GO.
Blocks typically appear on the right side of a function definition but can be used in
other places as well.
.example
.begin group
(C1) HESSIAN(F):=BLOCK([DFXX,DFXY,DFXZ,DFYY,DFYZ,DFZZ],
DFXX:DIFF(F,X,2),DFXY:DIFF(F,X,1,Y,1),
DFXZ:DIFF(F,X,1,Z,1),DFYY:DIFF(F,Y,2),
DFYZ:DIFF(F,Y,1,Z,1),DFZZ:DIFF(F,Z,2),
DETERMINANT(MATRIX([DFXX,DFXY,DFXZ],[DFXY,DFYY,DFYZ],
[DFXZ,DFYZ,DFZZ])))$
.end
(C2) HESSIAN(X^3-3*A*X*Y*Z+Y^3);
.begin group
3 2 3 2 3
(D2) - 54 A X Y Z - 54 A Y - 54 A X
.end
(C3) SUBST(1,Z,QUOTIENT(%,-54*A^2));
.begin group
3 3
(D3) X + A Y X + Y
.end
.end
The above example computes the Hessian of a cubic curve (the Folium of
Descartes) which turns out to be invariant under this transformation, i.e. the
result is of the same form.
The example below illustrates the saving and restoring of values described at the
beginning of this section.
.example
(C4) F(X):=BLOCK([Y], LOCAL(A), Y:4, A[Y]:X, DISPLAY(A[Y]))$
(C5) Y:2$
(C6) A[Y+2]:0$
(C7) F(9);
.begin group
A = 9
4
.end
(D7) DONE
(C8) A[Y+2];
(D8) 0
.once fill indent 0,0
1If LOCAL(A) had not been used, the value on line D8 would have been 9.
.end
.sec (The DO Statement,do!statements,1)
The $fun 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.
.subsec (Commonly Used Forms,common!forms,1)
There are three variants of this form that differ only in their terminating
conditions. They are:
.skip 1
.BEGIN GROUP NOFILL INDENT 0
1(a) 5$fun 2variable : 2initial-value 5STEP 2increment
5THRU 2limit 5DO 2body
(b) 5FOR 2variable : 2initial-value 5STEP 2increment
5WHILE 2condition 5DO 2body
(c) 5FOR 2variable : 2initial-value 5STEP 2increment
5UNLESS 2condition 5DO 2body1
.once fill indent 0,0
(Alternatively, the STEP may be given after the termination condition
or limit. )
.end
The 2initial-value*, 2increment*, 2limit*, and 2body* can be
any expressions. To iterate over several statements, the 2body* can
be made into a compound statement $see or a
$fun $see. The 2condition* (or predicate) is
as in the IF statement. If the 2increment* is 1 then "STEP 1" may
be omitted.
The execution of the DO statement proceeds by first assigning the
2initial-value* to the 2variable* (henceforth called the control-variable).
Then: (1) If the control-variable has exceeded the 2limit* of a THRU
specification, or if the 2condition* of the UNLESS is TRUE, or if the
2condition* of the WHILE is FALSE then the DO terminates. (2) The 2body* is
evaluated. (3) The 2increment* 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 2limit* if the 2increment* was non-negative, or when the
control-variable is less than the 2limit* if the 2increment* was negative.
The 2increment* and 2limit* may be non-numeric expressions as long as this
inequality can be determined. However, unless the 2increment* is syntactically
negative (e.g. is a negative number) at the time the DO statement is input,
ma 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 2limit*, 2increment*, and termination 2condition* 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 2body*, 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
$fun $see may be used inside the body to exit
the DO prematurely and give it any desired value. Note however that a
$fun within a DO that occurs in a $fun will exit only
the DO and not the BLOCK. Note also that the $fun function may
not be used to exit from a DO into a surrounding $fun.
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 (or resumes its
global value, if any) after the DO terminates.
.example
(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
.once fill indent 0,0
1The function LDISPLAY generates intermediate labels; DISPLAY does not.*
.SCON
(C6) S:0$
(C7) FOR I:1 WHILE I<=10 DO S:S+I;
(D7) DONE
(C8) S;
(D8) 55
.once fill indent 0,0
1Note that the condition in C7 is equivalent to UNLESS I > 10 and also THRU 10*
.SCON
(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;
.begin group
7 6 5 4 2
(D12) X X X X X
-- - --- - -- - -- + -- + X + 1
96 240 15 8 2
.end
.end
.bcon
1which gives 8 terms of the Taylor series for e^[sin(x)].*
.example
(C13) POLY:0$
.begin group
(C14) FOR I:1 THRU 5 DO
FOR J:I STEP -1 THRU 1 DO
POLY:POLY+I*X^J$
.end
(C15) POLY;
.begin group
5 4 3 2
(D15) 5 X + 9 X + 12 X + 14 X + 15 X
.end
(C16) GUESS:-3.0$
.begin group
(C17) FOR I:1 THRU 10 DO (GUESS:SUBST(GUESS,X,.5*(X+10/X)),
IF ABS(GUESS^2-10)<.00005 THEN RETURN(GUESS));
.end
(D17) - 3.1622807
.end
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".
.subsec (Additional Forms of the DO Statement,additional!do,1)
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
2expression*" instead of "STEP increment". This will cause the control-variable to be set
to the result of evaluating 2expression* each time through the loop.
.example group
(C1) FOR COUNT:2 NEXT 3*COUNT THRU 20
DO DISPLAY(COUNT)$
COUNT = 2
COUNT = 6
COUNT = 18
.end
As an alternative to $fun variable:value ...$fun... the syntax
.skip once nofill center
FOR variable FROM value ...DO...
.end continue
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.
.example group
(C1) X:1000
(C2) THRU 10 WHILE X#0.0 DO X:.5*(X+5.0/X)$
(C3) X;
(D3) 2.236068
.end
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 $fun $see should be used to
terminate execution of the DO.
.example
.begin group
(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)))$
.end
(C2) SQR(X):=X^2-5.0$
(C3) NEWTON(SQR,1000);
(D3) 2.236068
.end
(Note that RETURN, when executed, causes the current value of GUESS to be
returned as the value of the DO. The $fun 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 $fun is available in MACSYMA. The syntax is:
.example once center
5FOR 2variable 5IN 2list [end-tests] 5DO 2body
.end
1
The members of the 2list* $see are any expressions which will successively be
assigned to the variable on each iteration of the 2body*. The optional 2end-tests* can be
used to terminate execution of the DO; otherwise it will terminate when the 2list* is
exhausted or when a RETURN is executed in the 2body*. (In fact, 2list* may be any non-atomic expression, and successive parts are taken.)
.example
(C1) FOR F IN [LOG, RHO, ATAN] DO LDISP(F(1.0))$
(E1) 0
(E2) RHO(1)
%PI
(E3) ---
4
(C4) EV(E3,NUMER);
(D4) 0.78539816
.end
.sec (Syntax Extension,syntax!extension,1)
It is possible to add new operators to MACSYMA (infix, prefix, postfix, unary,
or matchfix with given precedences), to remove existing operators, or to redefine the
precedence of existing operators. Details may be found in Appendix II.