.EQ
delim @@
.EN
.so eqnfix
.na
.fi
.Lc Data\ Types\ in\ MACSYMA 2
.pp
This chapter describes the data types used by
.Ma .
The first table below summarizes the basic data types that are familiar
to most mathematicians who have used computers in their work. They are
similar to those data types in conventional programming languages, although
they are in some ways extended or generalized.
.nf
.TS
center box;
c s s s
l | l | l | l.
\fBTable 2.1: Basic Data Type Summary\fP
_
\fBData type \fP \fBShort Name\fP \fBComments\fP \fBSection\fP
_
number num Any numeric type 2-1 through 2-5
integer int Arbitrary length 2-1
rational ratnum Including integers 2-2
floating-point number flonum 2-3
big-float number bfloat 2-4
complex number complex 2-5
Boolean bool literally "true" or "false" 2-6
symbol symbol symbolic literal name 2-7
constant constant identifier 2-8
string string messages, etc. 2-9
.TE
.pp
Not all of the data types are as simple as those above.
.Ma
provides notations for three purposes:
(a) a representation language for mathematical data;
(b) a command language to manipulate that data;
and (c) a programming language for constructing additional notations
or commands. These are summarized in the table below.
.TS
center box;
c s s s
l | l | l | l.
\fBTable 2.2: Complex Data Type Summary\fP
_
\fBData type \fP \fBShort Name\fP \fBComments\fP \fBSection\fP
_
function name fun a symbol interpreted as a function
filename file Just a string, usually
"cre"-form cre Canonical Rational Expression
"general"-form gen Includes anything else
Poisson form pois See section ??
program prog
list list A type of general form data
matrix mat list of lists
any any Any of the above
.TE
.pp
.fi
Some
(I) [an intermediate-level note follows] Because
.Ma
crosses the line between symbolic and programming notations,
variables and indeterminates are easily mixed.
.Ma
may never need to think about this, most serious users must understand
that if one assigns to \fIx\fP the value 3, say, one must still be able
to refer to the symbol \fIx\fP independent of its current value (e.g. in order
to assign it a different value.) In general,
.Ma
will, when presented with a name like \fIx\fP, "evaluate" it, and use
its associated value, say 3. If the name \fIx\fP has no value associated with it, the name is sometimes said to be "quoted" automatically, and its associated value
is the (symbol) \fIx\fP itself.
If it is necessary to refer to the symbol \fIx\fP
itself even though it has an associated value,
the notation \fI'x\fP is used (that's an apostrophe or "single quote"
to the left of the symbol.)
The confusion is more apparent when one variable's value is
(a name of) another variable.
.pp
.".Ma
."will in some instances quote a name in a command automatically e.g.
."file-names are usually not evaluated. In the manual
."command descriptions, the items which \fB are evaluated\fP are indicated by
."the presence of the apostrophe (e.g. 'x_type). Thus the description
."of the command, referring to x_type, is talking about the result
."of evaluating 'x_type. This notation means that
."you generally \fBshould not\fP type the apostrophe unless
."you wish to avoid evaluation. This substantially simplifies
."the command descriptions.
.sh 2 "Numbers" 2
.pp
There are several sub-categories of numbers in
.Ma .
Principal representations are integers, rational numbers, floating point numbers, and
"bigfloats" plus minor variations.
Integers are an essentially accurate model of the mathematical
construct "ring of integers". The only limit to the size of a particular
integer (or the total sizes of all the integers)
is the size of the computer memory you are using.
.Ma
differs from most conventional languages in this. Most others
have integers represented by "integers modulo @2 sup n@" or so. The external
(printed) representation of
an integer is
a string of decimal digits.
.pp
Rational numbers are written as the quotient of two integers:
numerator/denominator.
.Ma
uniformly insists on reducing these numbers to a unique form,
regardless of the form in which you type them in. The representation
used removes common factors from the numerator and denominator, and
the denominator is positive. If the numerator is a multiple of
the denominator, the rational number is simplified to an integer.
.pp
Floating point numbers are an approximation to the real numbers,
and are supported in
.Ma
because they are supported directly in the computer hardware.
They are represented internally in the double-precision*
.(f
* It would be convenient to standardize on the IEEE arithmetic specification,
but we do not require it.
.)f
format of the
host system. They are written essentially as in FORTRAN, i.e.
strings of digits containing a period and optionally followed by an integer
exponent beginning with the letter e. Their default output format can be
altered by the user to provide more or less precision via the function
\fIfloatformat\fP.
.pp
The input format for bigfloats is similar to that of
floating point numbers in "e" format, except the letter b is used to denote
the beginning of the exponent. The b is compulsory to distinguish bigfloats
from the floating point numbers.
A bigfloat is also an approximation to a real number but it carries
along with it a parameter which is the number of digits carried.
This is determined by the value of the
.Ma
variable \fIfpprec\fP at the time the number was created.
Non-zero floating point numbers on the VAX-11 must have absolute value
between about 1.e-38 and
1.7e38 and are limited to approximately 16 digits precision. This is the
hardware limitation of the computer. Bigfloats may have any number of digits.
The default precision is 16 but the user can change this by setting the
variable
.Lv fpprec 16
to an integer representing the desired precision.
.Eb
.ce 5
-17253733574534 6.023e23 -1.6e-19
37.567834987250832568b-98 3.14159 227
-3354665557331/66724255465544 -.7b0
.Ee
.sh 2 "Boolean Values"
.pp
There are only two Boolean values, namely
.I true
and
.I false.
In many programming systems these Boolean values are treated differently
from other values or names, but in
.Ma
they are treated much the same as other simple names.
They do, however, have special semantics properties
since \fI true and false \fP evaluates to \fIfalse\fP, etc.
.sh 2 Names
.pp
Names are used to designate variables, functions, and arrays. A name consists
of a string of letters (which may include % and _ ) and digits. It may also include
other characters but these must be preceded with a \\ when typed in. Names can
be of any length and must begin with a letter (unless the leading character is a
\\ ). Upper case letters may be typed, but they are normally converted into the
corresponding lower case letters.
.Eb
.ce
%pi epsilon x10y30isastrangename \\\*special standard_deviation
.Ee
.sh 2 Strings
.pp
A string of characters of any length may be constructed by enclosing the string
in quotation marks ("). To include a quotation mark, semicolon, or dollar sign in
the string you should type a \\ to its left. Quoted strings
are useful as messages (such as those giving instructions for entering data) or
as descriptive titles for printed data.
.pp
Sometimes you can get the same results by using symbols,
(since \fCWhello\fP and \f(CW"hello"\fP print the same), it is safer to
use strings, because some symbols will have special properties and reserved
usages.
If you must include quotes in a string,
they may be themselves quoted with \\.
.Ex
"Input amount in \\$" "Riemann's \\"Zeta\\" Function"
.sh 2 "Atomic Variables"
.pp
Names can be used as synonyms for locations in computer memory
which store information. Assigning a value to a name is equivalent
to storing information in that location. Because of the nature of
.Ma ,
these "locations" can store almost any kind of data, regardless of
the apparent size or complexity.
Names which are assigned values are sometimes referred to as
variables, as opposed to mathematical indeterminates. If a variable
is "subscripted," the same name, say @x@, could be used for a sequence
or array of values by the notation \fIx[i]\fP for @x sub i@, etc.
If it is important to exclude subscripted variables, we will
designate the non-subscripted variety as "atomic variables".
.Lv myoptions []
is a
.Ma
variable---an "infolist"
which is a list (see the section later in this chapter on lists) of all the
.Ma
options you set during a session.
.pp
Subsequently when we describe a command, the names we use will reflect
the data types in this table. e.g. x_name will be of type name.
.sh 2 "General Form"
.pp
Mathematical expressions are constructed by using infix, prefix, postfix
and functional-position operators. What this means is,
.Ma
attempts to include the usual types of notation in a linearized form.
The usage and priorities of operators, from highest to lowest are:
." .Example group turn on "\"; narrow 8; tabs 4, 24, 32, 40, 48, 56;
.TS
box;
l l c.
\fBOperator Name Symbol Usage\fP
_
factorials ! !! postfix
_
exponentiation ** or ^ infix
_
non-commutative ^^ infix
exponentiation
_
non-commutative . infix
multiplication
_
division, multiplication * / infix
_
negation - prefix
_
additionn, subtraction +- infix
.TE
.pp
The way this works is that @a*b+c@ is parsed as @( a * b) + c@ because
* has higher priority than *. Also, "^" is right-associative, meaning
that @a ^ b ^ c@ is @ a sup {b sup c} @ rather than @ ( a sup b ) sup c @,
which is equal to @ a sup b*c @. Other operators of equal precedence
associate to the left.
.Ex
@ sin (a*b*x^y/z!)"^"2 @ means @ ( sin((a*b)*(x^y))/(z!)) "^"2 @
.pp
If you refer to
an operator out of the context of an expression,
you must enclose it in quotation marks.
.pp
In the case of particularly unwieldy exponents,
\fIexpt\fP
is used to display exponentiation.
! is the factorial which is the product of all the integers from 1 up to its
argument. Thus 5! = 1*2*3*4*5 = 120. The value of the option
.Lv factlim -1
gives the highest factorial which is automatically expanded. If
it is -1 then all integers are expanded.
!! stands for double factorial which is defined as the product of all the
consecutive odd (or even) integers from 1 (or 2) to the odd (or even) argument.
Thus 8!! is 2*4*6*8 = 384.
Period is used for a non-commutative product operation. You can elaborate
on the semantics of
this operation by various simplifier facilities described later.
In typing this, you must precede and follow it by
a space when it would look like a floating point number.
Non-commutative exponentiation is provided : @m "^^" 2 @ means @m ~.~m@.
Parentheses can be used to
change the order of evaluation. Also functional application has the highest priority.
The operands may be any
.Ma
expressions whose values are the correct types
of data. Recall that every statement in
.Ma
yields a value even if the value
is only a trivial one.
.Ma
has no restriction on the mixing of modes of operands. Integers, rationals, floating point numbers, and
bigfloats may be freely intermixed in an expression; when conversions are necessary, the priority of conversion
is toward the end of the list just mentioned.
If floating point numbers or bigfloats of differing precision are combined in a
operation, they will be converted to floating point or bigfloat numbers of the current precision by
padding with zeroes or by dropping off low order digits and rounding.
Floating point underflow will return 0.0.
." .sec (Functions and Arrays,functions!arrays)
.sh 2 "Functions and Arrays"
.pp
Sometimes it is useful to associate names with sequences or arrays
of values, or to associate names with some rule for the computation
of values. For the first of these, arrays are generally used,
and for the second, it is possible to write programs, or
"functions". Again, the mathematically formal notion of function
is inappropriate; the relevant concepts are outlined in appendix ?
for the programming novice.
.sh 3 Functions
.pp
The novel idea, even for most programming language buffs, concerning
functions in
.Ma
is that these objects can themselves be manipulated as data in
.Ma
itself. This will perhaps become clear in this section.
.pp
A function defined by using the command ":=", and associates a name
with a function "body" or "lambda-expression". The lambda-expression
provides a fixed format for determining the association of actual
parameters or arguments to the function with the names used to specify
the computation in the body. Since this paragraph is unlikely to
make sense to you unless you already knew what it meant, we will try
again via the following example:
.Eb
.nf
(c1) ":="(f,lambda[x,y],2*x+y+z);
.EQ L (d1)
f ( x , y) := 2^x^+^ y ^+^ z
.EN
(c2) f(3,4);
EQ L (d2)
z ^+^ 10
.EN
.Ee
.pp
Note the alternative syntax displayed on line d1, in which the
function definition
is written as a name followed by the formal parameters (here, @x@ and @y@)
to the function
separated by commas and enclosed in parentheses, and the body of
the function is an arbitrary
.Ma
expression involving those parameters and perhaps other objects.
The use of the function on line c2 illustrates the actual parameters
(here, 3 and 4) which are associated by position with @x@ and @y@ respectively,
then substituted into the function "body" and evaluated.
The arguments may be any expressions whatsoever, not just numbers.
Now that you understand @lambda@ forms, you could, if you wish, read the
section on them in this chapter.
.pp
There are many more elaborate techniques for function definition
which are deferred to the next chapter. What we wish to identify here
is the notion that a name can be a name of a function.
.sh 3 Arrays
.pp
Arrays enable one to refer to a collection of elements by using a
single name. An element of an array is referred to by a subscripted
variable which is a name followed by a list of subscripts enclosed in
square brackets. Arrays in
.Ma
are of two types,*
.(f
*For efficient
translation, the user can also inform MACSYMA of arrays all of whose
elements are of a single type, e.g. FIXNUM, FLOAT, or whose elements
are all known before being referenced, called a COMPLETE array.
.)f
declared or undeclared. Declared arrays are similar to FORTRAN
arrays. The user declares the number of dimensions and indicates the
maximum value of each subscript. The system then allocates space for
the entire array. To declare an array the user types:
.skip 1
.inline function(ARRAY,|name, dim1, dim2, ..., dimk|)
.scon
This sets up a k-dimensional array.
The subscripts for the i2th* dimension are the integers running from
0 to 2dimi*. If the user assigns to a subscripted variable without declaring
the corresponding array, an undeclared array is set up.
Undeclared arrays, otherwise known as hashed arrays (because hash coding is done
on the subscripts), are more general than declared arrays. The user does not
declare their maximum size, and they grow dynamically by hashing as more
elements are assigned values. The subscripts of undeclared arrays need not even
be numbers. However, unless an array is rather sparse, it is probably more
efficient to declare it when possible than to leave it undeclared. The ARRAY
function can be used to transform an undeclared array into a declared array.
Array elements can be assigned values explicitly with the : operator or
implicitly by means of an associated function, and the values assigned may be
any MACSYMA expression. To understand implicit assignment we must understand
what MACSYMA does when asked to evaluate a subscripted variable. MACSYMA first
evaluates the subscripts left to right. Then it does an array access to see if
the requested array element already has a value. If it does, the value is
returned. If it does not, MACSYMA checks to see whether the array has an
associated function (see below). If not, the subscripted variable (with the
subscripts evaluated) is returned. (This is standard MACSYMA practice - if
there is no value for a variable, the variable itself is returned when an
evaluation is done.) If there is an associated function, the parameters of the
function are bound to the given subscripts, and the function body is evaluated.
The value of the function call is stored in the appropriate array element and
returned. Note that once an element is computed by the associated function it
is stored so that next time it is needed it will not be recomputed. A
consequence of this is that unless the user uses the $fun, $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.