About this document:

By combining this powerful datatyping with the extensive libraries of Maple functions, you can solve problems from any field that requires:

Finally, whenever you use Maple there is one important caveat that you need to keep in mind. Maple is an excellent tool for performing or verifying tedious and error-prone computations, but it is not a substitute for mathematical knowledge and intuition. Like most programs it will try to do what you ask of it, but you must judge the mathematical relevance of both your question and Maple's answer.

> *commands-typed-here*

*
response-printed-here*

The only typographic licence taken with these dialogs is reduction of non-critical output like white space. Maple inserts blank lines liberally to make the results easier to read; it also inserts solid lines between completed statements that you enter.

Example:

> *statement-one*;

*
response-to-statement-one*

-----------------------------------------------

> *statement-two*;

*
response-to-statement-two*

-----------------------------------------------

>

Most of these extra lines were removed to reduce size and improve overall readability of this document.

**
Checkpoint.** Look for notes like this located at various places in this
document. They are designed to let you know that you are at a good place to
stop and apply what you've learned about Maple, and what to do when you are
ready to learn more.

athena% **add maple**

(This is for all workstation types except VAXstations; for that type, you can
only use Maple V, available in the maple.old locker rather than the maple
locker). The **add** command attaches the maple locker to the directory
/mit/maple and appropriately modifies your environment -- in particular, it
adjusts both your program search path (PATH) and your manual-page search path
(MANPATH) variables to let you run **maple** and access the Maple man
pages.

To run **maple**, just type the following command:

athena% **maple**

If you are running an X-windows session, then a few moments after you enter the
command **maple**, a new window will appear with Maple running in it. (Note
that Maple automatically "backgrounds" itself -- you do not need to use the
command form **maple &** the way you might do for other windowed
applications.)

GIF_FILE

If you are accessing Maple on a plain-text format (e.g., over dialup), you will just see its startup message and a prompt:

|\^/| MAPLE V Release 2 (Massachusetts Institute of Technology)

._|\| |/|_. Copyright (c) 1981-1993 by the University of Waterloo.

\ MAPLE / All rights reserved. Maple and Maple V are registered

<____ ____> trademarks of Waterloo Maple Software.

| Type ? for help.

>

There are two ways to invoke help on Maple. The simpler and recommended way is to preface a topic with a question mark. To get help on the help system itself, type either of these commands:

> **?**

> **?help**

To get an index of topics, just type:

> **?index**

To get a quick overview of maple, try:

> **?intro**

The second way of getting help is to use the **help** function call. Your
query must conform to Maple's statement syntax, which will be explained later
in this document. As an example, to get the help on **help** you would use
either of these commands:

> **help();**

> **help(`help`);**

The backquotes and the semicolons are necessary, though in all other respects this method of getting help is the same as described previously.

These manuals are still in production, but the MIT Coop intends to stock them once they are available.

If you have access to documentation for previous releases of Maple, you may
notice references to the **MRM**. This stands for the **Maple Reference
Manual**. Starting with Maple V, that document has been split into the
separate language and library reference manuals listed above.

You can also browse the current collection of Answers to Commonly Asked
Questions about Maple by typing **olc_answers** at your athena% prompt.
Maple answers are under the category Other.

A Maple user's group exists which corresponds by electronic mail. This group can be reached by sending mail to maple_group@daisy.waterloo.edu.

If you have not used electronic mail before on Athena, you may want to read the
document **Electronic Mail on Athena**. This document is available online
in the Athena On-Line Help System (OLH). It is also available in hardcopy form
at MIT Graphic Arts.

There also exists a Usenet newsgroup devoted to symbolic algebra and various mathematical software packages. The newsgroup name is sci.math.symbolic.

If you have not read netnews before, you may want to read the document
**Netnews on Athena**. Like the mail document, this document is available
both online on OLH and in hardcopy form from MIT Graphic Arts.

>

For Maple to understand what you type, your commands must conform to Maple's expectations for statements. In particular, your statement must be terminated by a semicolon (;) or a colon (:) for Maple to realize that you have completed it. The semicolon tells Maple to print out the result of evaluating the statement, while the colon tells it not to print the result. The terminator does not need to be typed on the same line as the rest of the statement, so if you forget it on one line you can type it on the next line. For example:

> **4+5:**

is a statement to add 4 and 5 but not to print the result. An equivalent statement is:

> **4+5**

> **:**

In this case, after the first line Maple will assume that you have not finished
your statement. On seeing the colon on the next line, Maple will realize the
statement is finished and evaluate **4+5**.

You can put more than one statement on a line, just as you can break a statement across multiple lines. The requirement is that statements be terminated, not that they fit on a line.

There are two Maple statements that do not have to be terminated in this way:

> **4+5;**

> **quit**

9

> **4+5; quit**

9

> **4+5; quit;**

9

The first example produces a syntax error; the second example actually works, but prints out the error message noted:

> **4+5: ?help**

syntax error:

4+5:?help

^

>

> **4+**

> **?help**

*
[a help window appears]*

Error, invalid types in sum

>

As shown above, when Maple detects a syntax error it echoes the statement and
shows you how far it was along in reading it when it detected the error. It
does this by placing a caret (^) below the point in question. The syntax error
is generally somewhere in the statement prior to this point. The best way to
recover from a syntax error is to type a terminator (:, ;) and **Return** to
ensure that Maple will know that you are trying to enter in a new statement.
Then type in a corrected version of the statement that gave you the syntax
error.

Maple has a number of pre-defined global variables. When you choose names for
your own variables, you should avoid the predefined ones. They are there to
help you control how Maple works. This is discussed further in the section
**Some Predefined Symbols**.

> **4+5;#This is an example of a comment**

gives the output:

9

Since a comment is not a statement, it does not need to be terminated. It only causes the remaining input on the line to be ignored.

It is possible to control how much information is echoed in Maple. The *echo
level* can be set with the **interface** function. An echo level of four
causes comments and statements to be echoed. For more information on how to
control various user-interface settings, type:

> **?interface**

Arithmetic expressions are evaluated according to typical precedence rules, so:

> **4+2*3;**

10

because **2*3** is evaluated before the addition. Other useful operators
are:

One useful aspect of Maple is that it distinguishes rational values from floating-point (pseudo-real) values. Compare these statements:

> **2/3;**

2/3

> **2.0/3.0;**

.6666666667

This gives you the flexibility to choose between approximate or exact answers to many mathematical questions.

> **x := 2 + 5;**

x := 7

> **x;**

7

The programming variable x now is a label for the result of 2+5.

The other kind of Maple variable is a *mathematical variable* or an
*unassigned variable*. These exist in the sense of algebraic unknowns, as
in the case of:

> **z := 2+y;**

z := 2 + y

Here, y is a mathematical variable, and z is a programming variable because an expression has been assigned to it. If we now assign a value to y, y becomes a programming variable, and is no longer an algebraic unknown:

> **y := 5;**

y := 5

> **z;**

7

An equation is different from an assignment statement. Consider the difference between:

> **a := 2;**

a := 2;

> **b = 2;**

b = 2

In the first case we are assigning the value 2 to the variable a. In the
second case, we are making the assertion that b is in fact already equal to 2.
We can evaluate the boolean assertion using the **evalb** function:

> **# First, see what the value of b is:**

> **b;**

b

> **# So b is a mathematical variable. Try the evaluation:**

> **evalb(b=2);**

false

> **# Now assign the value 2 to b:**

> **b := 2;**

b := 2

> **b;**

2

> **# So b is now a programming variable. Evaluate the assertion
again:**

> **evalb(b=2);**

true

> **# Now assign the assertion to a (which replaces the old contents of
a):**

> **a := b = 2;**

a := 2 = 2

> **evalb(a);**

true

The last part of the example shows that you can assign an *expression* to
a variable. Maple statements are built of zero or more expressions of various
types connected in various ways. Thus **b=2**, and **abs(4)** are both
expressions, while **evalb(b=2)** is a composite expression built from
**evalb(...)** and **b=2**. Finally, **evalb(b=2) and (c = 3);** is a
statement, because it is built from (boolean) expressions and is terminated.

> **z1 := z2 + z3;**

z1 := z2 + z3;

> **a1 := a2 * a3;**

a1 := a2 * a3;

> **" + "";**

a2 a3 + z2 + z3

Backquotes (left-quotes) are used to construct strings, as in:

> **a := `This is a string`;**

a := This is a string

> **a;**

This is a string

In the previous section, a mathematical variable was also described as an unassigned variable. Unassigned variables have their own name as their value. This is the default condition for a variable until you assign it a value. To turn an assigned variable (i.e., a programming variable) back into an unassigned variable (i.e., a mathematical variable), you must assign it its own name. As an example:

> **# r hasn't been used, so its an unassigned variable:**

> **r;**

r

> **# Now make r an assigned variable:**

> **r := 2;**

r := 2

> **r;**

2

> **# Now try to give r its own name:**

> **r := r;**

r := 2

> **# That didn't work, because the r on the right side of the
assignment**

> **# statement was evaluated prior to the assignment. Assign the
name**

> **# of the variable by delaying evaluation:**

> **r := 'r';**

r := r

> **r;**

r

> **# r is now a mathematical variable once more.**

This shows the function of the apostrophe (right-quote). It delays evaluation of an expression.

Maple generally performs what is called "full evaluation". You have seen an example of this already. Here it is again:

> **z := 2+y;**

z := 2 + y

> **y := 5;**

y := 5

> **z;**

7

Once "y" had been assigned a value, you didn't have to do anything to tell Maple that "z" could be completely evaluated to a number instead of an algebraic expression. Every time Maple evaluates a statement, it checks to see if it knows any other expressions that could be re-evaluated in light of the new information. An exception to automatic full evaluation is in procedures, which is discussed later.

> **a := -2;**

a := -2

> **abs(a);**

2

> **a;**

-2

The result of taking the absolute value of "**a**" is returned as the result
of the function **abs(...)**. The variable "**a**" itself is not
modified as a side effect. If you wanted to change the value of the variable,
you would use:

> **a := abs(a);**

a := 2

Functions are a special case of procedures. Later in this document you will learn how to construct your own functions and procedures.

*
Integers* are expressed as a string of one or more digits with an optional
sign, like "-2" or "3870". *Rational numbers* are a signed ratio of
unsigned integers, like "2/3" or "-8/30", and will be simplified by Maple:

> **-8/30;**

-4/15

*
Floating point numbers* contain an explicit decimal point, and any integer
or rational expression that contains such a decimal point will be evaluated as
floating point:

> **2/3;**

2/3

> **2.0/3.0;**

.6666666667

Maple has a global variable named "Digits" that you use to control the accuracy of floating-point operations. The initial setting for Digits is 10 but you can change it by assigning it some other value:

> **Digits:=5;**

Digits := 5

> **2.0/3.0;**

.66667

> **Digits:=10;**

Digits := 10

> **"";**

.66667

> **2.0/3.0;**

.6666666667

Notice that the value of Digits does not control the display of floating point values, it controls their calculation. If you calculate something with one value for Digits, then change Digits to a new value, then only future floating-point operations will reflect the change.

You can perform conversions between various Maple datatypes. One way is to
force evaluation of expressions in the type you want. For example to convert a
rational expression to floating point, you could use the **evalf**
function:

> **evalf(2/3);**

.6666666667

> **evalf(2/3, 5);**

.66667

As you can see, **evalf** also provides a way to temporarily control the
accuracy of floating-point calculations. See **help('eval')** for
information on other Maple evaluation functions.

The second, more general, way to convert between types is to use the
**convert** function. See **help('convert')** for more information.

> **with(linalg):**

Warning: new definition for norm

Warning: new definition for trace

When Maple loads a package, it checks to see whether any of the new function
names will replace an existing function. If so, it gives you a warning. For
instance, since **linalg** has a function to compute the trace of a matrix
that is called "**trace**", which is the same name as the debugging command
"**trace**", a warning was generated. The new function is available for
use, but the previous function of the same name is no longer accessible.

There is a way to avoid this problem if you want access to both functions. The
technique will allow you to use a single function of a package without loading
the entire package into memory. You use the "long form" to specify the
function, ** libname[funcname](...)** where

A Maple "*library*" is a collection of packages. The standard Maple
library consists of some internally-defined functions, but most of them reside
externally on the file system. When you use the **readlib** command, Maple
reads in the definition for the specified function in much the same way that
**with** works for packages. **readlib** is particularly useful in
situations where you have redefined a standard library function.

For example, when the **linalg** package was loaded in, the standard
**trace** function became unavailable. To get it back, use:

> **readlib('trace');**

proc(fname) ... end

For example, the following command saves everything you created during the
session in a file named "*filename*.m":

> **save ` filename.m`;**

When you specify a filename with the extension ".m", Maple saves your work in "Maple internal format". This is the most useful format for Maple when you restore your work later on. You restore the information with the command:

> **read ` filename.m`;**

To save only specific items, or to save and restore information in a
human-readable format, read the sections in the **First Leaves** document
entitled "**Saving the state of your Maple session**" and "**Recording
results in files in human-readable format**".

Once you have saved your work, you can terminate your Maple session with any of
the commands **quit**, **done**, or **stop**.

**
Checkpoint.** You have now been given a general overview of the basic
features and syntax of Maple. Experiment with what you have learned. When you
want more information on what Maple can do, continue to read this document.

There are two reasons why only a limited number of automatic simplifications are performed:

The **simplify** command provides typical expression simplifications. By
using **simplify(expr, variety)** you can control what simplifications are
performed:

> **(x^y)^z;**

y z

(x )

> **simplify((x^y)^z,power);**

(y z)

x

See **help('simplify')** for the various simplification options.

The **expand** command forces distribution of multiplication over addition.
For instance:

> **f := (x + y) * (x - y);**

f := (x + y) (x - y)

> **expand(f);**

2 2

x - y

Since **expand** turns **f** into x^2 + y * x - x * y - y^2, the
automatic simplifications turn the expression into x^2 - y^2.

For more information on simplification, see **help('simplify')**,
**help('expand')**, **help('factor')**, **help('normal')**, and the
**First Leaves** section on "**Simplification of expressions**".

*
*

*
*

*
*

*
*

The global variable "printlevel" is a particularly handy one to know. By
setting "printlevel := 0;" you turn off the automatic printing of your
commands; setting "printlevel := 1;" is the default behaviour. See
**help('printlevel')** for the effect of other settings.

> **# Be sure that the index variable is a mathematical variable.**

> **# If i had a value (say, 3), it would be meaningless to say**

> **# something like "sum 3 squared for 3 from 1 to n" when you meant
to**

> **# say "sum i squared for i from 1 to n":**

> **i;**

i

> **# This is an example of a sum over an indefinite (non-negative)**

> **# index range:**

> **x; # Just to be sure, we want to see if x is a mathematical
variable.**

x

> **sum(x^i, i);**

i

x

-----

x - 1

> **# These are examples of definite sums:**

> **sum(i, i = -2 .. 5);**

12

> **sum(x**i, i = 0 .. 3);**

2 3

1 + x + x + x

> **# Take the first-order derivative of an expression w.r.t. x:**

> **diff(3*x^2, x);**

6 x

> **# Take higher-order partial derivatives by specifying a sequence**

> **# of variables. Derivatives are taken in the same order as the **

> **# variable sequence:**

> **diff(y * x^2 + y, x, y);**

2 x

Definite and indefinite integration are performed using the **int** command,
in the same way as described for the **sum** command:

> **# An example of indefinite integration:**

> **int( cos(x), x );**

sin(x)

> **# An example of definite integration:**

> **int( x^2, x=0..2 );**

8/3

> **# An example where Maple can't find the solution:**

> **int(x^(-2), x=-1..1);**

1

/

| 1

| ---- dx

| 2

/ x

-1

When Maple is unable to find the solution to a problem, it returns a "prettyprinted" version of the original command expression. Sometimes this will be because Maple doesn't know how to solve the problem, but more often it will be because either no solution exists or the original command/query was not posed properly.

> **# Compute some terms of the Taylor series for cos(z) at z=0:**

> **taylor(cos(z),z=0);**

2 4 6

1 - 1/2 z + 1/24 z + O(z )

> **# The default number of terms in the expansion is controlled by
the**

> **# global variable Order, which is initially set to 6:**

> **Order := 9;**

Order := 9

> **taylor(cos(z),z=0);**

2 4 6 8 9

1 - 1/2 z + 1/24 z - 1/720 z + 1/40320 z + O(z )

> **# You can also specify the expansion order to taylor(..):**

> **taylor(cos(z),z=0,4);**

2 4

1 - 1/2 z + O(z )

There is also a **series** function for a more general method of series
expansion. See **help('series')**, **help('taylor')**, and
**help('asympt')** for more information on series-expansion facilities.

> **limit(cos(x+Pi/2)/x,x=0);**

-1

> **limit(sin(1/y^2),y=0);**

-1 .. 1

> **limit(a*cos(x+Pi)/x,x=0);**

undefined

> **# Solve a single equation with one unknown and one solution:**

> **solve(exp(x) = 1);**

0

> **# Solve a single equation with a constant, an unknown, and two
solutions:**

> **solve(x^2 = a, x);**

1/2 1/2

a , - a

> **# An expression like "x+y" is implicitely assumed to be equal to
0.**

> **# Solve a system of equations simultaneously:**

> **solve( {x+y, x*y=b}, {x,y} );**

1/2 1/2 1/2 1/2

{y = - (- b) , x = (- b) }, {y = (- b) , x = - (- b) }

The function for solving differential equations is **dsolve**. For full
details on using it, see **help('dsolve')**. Here is a simple example:

> **deq := diff(y(x),x) + y = 0;**

/ d \

deq := |---- y(x)| + y = 0

\ dx /

> **dsolve(deq, y(x));**

y(x) = exp(- x) _C1

As the various solve functions need to specify solution constants, they generate names like "_C1", "_C2", etc.

> # x and y are mathematical variables:

> **x,y;**

x, y

> **solset := solve({x+y, x*y=b}, {x,y});**

solset :=

1/2 1/2 1/2 1/2

{y = - (- b) , x = (- b) }, {y = (- b) , x = - (- b) }

> # Now assign the first solution to the independent variables:

> **assign(solset[1]); x,y;**

1/2 1/2

(- b) , - (- b)

When there is a choice of solutions to assign, and you haven't specified a particular choice by subscripting a particular solution in the set, assign will chose one solution to apply to the independent variables.

You can make temporary assignments to mathematical variables using the function
**subs**. This allows you to evaluate an expression for a given set of
values, without turning the mathematical variables into programming variables.
Given that Maple generally applies full evaluation, this is an important
feature. By giving **subs** a sequence of variable bindings and an
expression, you can "test" the expression with those values:

> **# z is a programming variable:**

> **z;**

z

> **f := cos(z);**

f := cos(z)

> **# Now, to see what f(2) is:**

> **subs(z=Pi, f);**

cos(Pi)

> **# Force evaluation to simplify the result:**

> **eval(subs(z=Pi, f));**

-1

> **# Now check to see the value of z:**

> **z;**

z

Here is an example to show the difference between **print** and
**lprint**:

> **f := (a*b)/(c*d), c^d:**

> **print(f);**

a b d

---, c

c d

> lprint(f);

a*b/c/d c**d

You can also plot expressions in Maple. Two-dimensional plots are generated
using the **plot** command, which works both in tty- and X-sessions. To
generate 3-D plots you use the **plot3d** command, which only works in
X-sessions. To utilize the plotting features to the fullest, you may need to
understand the basics of writing Maple procedures, but simple plots can be
generated without this knowledge. The section "**Plotting Functions**" in
the **First Leaves** document discusses 3-dimensional plotting of
procedures; you can see **help('plot')** and **help('plot3d')** for more
details.

**
Checkpoint.** You have now been given a general overview of some of the
fundamental techniques of using Maple. Experiment with what you have learned.
When you want more information on what Maple can do, continue to read this
document.

**
Combinatorial Functions (combinat).** This package contains functions to
calculate or manipulate various combinatorial values and objects. This ranges
from calculation of binomial or fibonacci numbers to generation of subsets and
power sets.

**
Differential Forms (difforms).** The differential forms package is used to
extend the basic differentiation and differential-equation-solving capabilities
of Maple. Read the help sections on the differential operators "**d**" and
"**D**" as well as the help on **difforms** for more information.

**
Three-Dimensional Euclidean Geometry (geom3d).** This package allows you to
define and manipulate three-dimensional objects such as points, lines and line
segments, planes, spheres, and tetrahedra. You can use the various functions
to determine properties like volume, distance, collinearity, and area.

**
Two-Dimensional Euclidean Geometry (geometry).** This package is the
two-dimensional equivalent of the **geom3d** package. It allows you to
define and manipulate two-dimensional objects such as points, lines, circles,
and triangles. There are functions in the package to determine properties like
distance, circumferance, diameter, and similarity.

**
Grobner Bases (grobner).** This package gives you the ability to perform
various grobner basis calculations for a given list of polynomial functions,
with respect to a given list of variables.

**
Permutation and Finitely-Presented Groups (group).** This package implements
and manipulates permutation groups and finite-presentation groups. Among other
things, you can find the centralizer and normalizer for a group, test for group
membership, and calculate the order of a group.

**
Lie symmetries (liesymm).** The Lie Symmetries package is an implementation
of the Harrison-Estabrook procedure. This is another package for dealing with
differential equations.

**
Linear Algebra (linalg).** The linear algebra package implements the
numerous operations that you can perform on vectors and matrices, including
determining eigenvalues and eigenvectors, column and row operations, basis
finding, Gaussian elimination, and conversion to various normal/canonical
forms. (There is a discussion of this package in the "**Linear algebra in
Maple; the with function; packages**" section of the **First Leaves**
document).

**
Boolean logic (logic).** The boolean logic package provides additional
operations over boolean expressions, conversion to canonical forms, and
expression simplification.

**
Newman-Penrose Formalism (np).** The Newman-Penrose formalism package is
another package for dealing with differential operators.

**
Number Theory (numtheory).** The number theory package provides you with a
wide assortment of algebraic operations and tests. In particular, you can
generate mersenne primes, calculate modular roots, test primality, and perform
integer factorizations.

**
Orthogonal Polynomials (orthopoly).** This package allows you to generate
various kinds of orthogonal polynomials, including Gegenbauer, Hermite,
Laguerre, Legendre, Jacobi, and Chebyshev types.

**
Graphics Package (plots).** The plots package implements a variety of
plotting aids in addition to the commands **plot** and **plot3d**
discussed in this document. For instance, **sphereplot** lets you plot a
3-dimensional surface in spherical coordinates.

**
Formal Power Series (powseries).** The formal power series package provides
additional combinatorial facilities in Maple. Included are the ability to add,
multiply, evaluate, and invert power series. This provides a very powerful
combinatorial modelling capability when used in conjunction with standard
library functions like **op** and **coeff**.

**
Projective Geometry (projgeom).** The projective geometry package provides
additional geometric capabilities. You can find line meetings and
intersections, tangents to conics in the complex plane, and test for or
generate collinear points.

**
Linear Optimization (simplex).** The simplex package consists of
implementations of routines for linear optimization. In addition to being able
to find minimal or maximal solutions, you can also test for solution
feasibility and generate the dual of a problem.

**
Statistics (stats).** The statistics package provides the standard
collection of statistical calculations and tests, including linear and multiple
regression, t and F tests, and random number generators for various
distributions.

**
Student Calculus (student).** Typically, Maple packages are designed to
(where possible) solve problems for you. You give the input or problem
description, and Maple gives the output or solution. The student calculus
package, on the other hand, is a collection of tools to solve problems in a
step-by-step fashion. It is designed to be an instructional aid for a
first-year calculus course.

**
Total Orders on Names (totorder).** The total ordering package helps you
test for order between members of an ordered set. You give it the names of the
members of a set, and some ordering relations between them, and it then lets
you test for order between two arbitrarily-chosen members. For instance, if
you tell it that "a<b" and "b<c" via the **assume** command, you could
use the **if** function to test whether "a<c" with .

**
Checkpoint.** You have now been given a general overview of the various
packages that come with Maple and what they can do. Experiment with ones that
provide mathematical facilities that you are familar with. When you want more
information on what Maple can do, continue to read this document.

To look at the i-th part of an expression, you use **op(i, expression)**,
where *i* evaluates to a non-negative integer.

Example:

> **e1 := op1 + op2 + op3:**

> **e2 := op1 * op2 * sin(op3):**

> **op(2, e1);**

op2

> **op(3, e2);**

sin(op3)

As you can see, the operands of the expression are returned, not the operators
that connect them. This is because Maple categorizes expressions into
"*types*". For instance, "a+b+c" is of type "+" and has three operands;
"a+b*c" is also of type "+" and has only two operands, one of which is of type
"*" and itself has two operands. The **whattype** function tells you the
type of an expression; **type** is a boolean test that allows you to check
for a particular type of expression. For example:

> **whattype(e1);**

+

> **whattype(e2);**

*

> **type(e1+e2, `+`);**

true

> **type(expand(e1*e2),`+`);**

true

To find out the number of operands in an expression, you use
**nops(expr)**.

For example:

> **expand(e1*e2);**

2 2

op1 op2 sin(op3) + op1 op2 sin(op3) + op1 op2 sin(op3) op3

> **nops(");**

3

*
Sets* and *lists* are also Maple types. A set is just a sequence of
items between "{" and "}" symbols; a list is a sequence of items between "["
and "]" symbols. Their Maple type names are "set" and "list".

To access particular items of sequences, sets, and lists all you have to do is subscript them:

> **w0 := a1, a2, a3:**

> **w0[1];**

a1

> **w1 := {a1, a2, a3};**

w1 := {a3, a2, a1}

> **w1[2];**

a2

> **w2 := [a1,a2,a3];**

w2 := [a1, a2, a3]

> **w2[1..2];**

a1, a2

The last example uses a "range". A range is valid Maple type and is used to describe a range of values. Unlike sequences, sets, and lists, you can not subscript a range.

There are a number of operations that work on sequences, sets, and lists. See
the Maple **help** sections on their type names for more information.

> **tab := table([key=100, name=joeuser, address=mit]);**

tab := table([

key = 100

name = joeuser

address = mit

])

> **tab[name];**

joeuser

> **tab[phone] := `x0-0000`;**

tab[phone] := x0-0000

> **tab;**

tab

> **op(tab);**

table([

phone = x0-0000

key = 100

name = joeuser

address = mit

])

The example shows that tables are one of Maple's exceptions to the use of full
evaluation. Tables, arrays, and procedures use what is referred to as "last
name evaluation". In essence, variables access these objects by reference, not
by value. To directly access the value (to copy it, for instance), you need to
use the **op** function described earlier.

An *array* is much like a table, except that you specify an integer range
of subscripts. For example:

> **arr := array(1..2, 1..2);**

arr := array(1 .. 2, 1 .. 2, [])

> **arr[1,1] := 1: arr[2,2] := 2:**

> **print(arr);**

[ 1 arr[1, 2] ]

[ ]

[ arr[2, 1] 2 ]

**
Checkpoint.** You have now been given a general overview of some of the more
advanced non-programming features of Maple. Experiment with what you have
learned. When you want more information on what Maple can do, continue to read
this document.

Each of these structures is explained here. There are some other statements
that affect flow of control that have either already been introduced
(**done**/**quit**/**stop**), or will be dealt with in the sections
**Procedures** and **Error Handling**.

for *variable* from *start* by *change* to *finish* while
*condition* do

*statement-sequence*

od;

and:

for *variable* in *expression* while *condition* do

*statement-sequence*

od;

The *statement-sequence* is repeated for each distinct value of
"*variable*" while "*condition*" is true. The "**for ...**",
"**from ...**", "**by ...**", "**to ...**", and "**while ...**"
clauses are all optional. If "**from start**" or "

In the first case, "*variable*" is initially assigned the "*start*"
value (so "*variable*" can be either a mathematical or programming
variable prior to use in the loop). With each successive loop if
"*variable*" is less than or equal to "*finish*" then
"*variable*" is incremented by "*change*"; if the "**while**"
condition is also true then the statement sequence is repeated. If either the
"**to**" or "**while**" conditions are false, the loop terminates.

In the second case, "*variable*" is successively assigned the component
parts of the *expression*. This form of the **for** statement is just
a more convenient way of expressing something like:

for *variable* to nops(*expression*) while *condition* do

* statements that use* op(*variable*, *expression*)

od;

Example:

> **printlevel := 0:**

> **listsum := 0;**

> **for i in [1,2,3,4,5] while i < 5 do**

> **listsum := listsum + i;**

> **od;**

> **listsum;**

10

> **printlevel := 1:**

if *condition* then

*statement-sequence*

elif *condition* then

*statement-sequence*

...

elif *condition* then

*statement-sequence*

else

*statement-sequence*

fi;

The **elif** and **else** portions are optional; there may be more than
one **elif** clause in a row. The (boolean) *condition* in the
**if** section is evaluated; the corresponding *statement-sequence* is
evaluated if the *condition* is true. If the *condition* is false,
control passes to the next **elif** or **else** clause. If no
*condition* is true and there is no **else** clause, no action is
taken.

Example:

> **printlevel := 0:**

> **for x by 3 to 20 do**

> **if isprime(x) then**

> **print(x, `is prime`);**

> **elif type(x, odd) then**

> **print(x, `is odd non-prime`);**

> **else**

> **print(x, `is even non-prime`);**

> **fi;**

> **od;**

1, is odd non-prime

4, is even non-prime

7, is prime

10, is even non-prime

13, is prime

16, is even non-prime

19, is prime

> **printlevel := 1:**

break;

The **break** statement is used in **for** and **while** loops to
terminate iteration of the loop altogether. Flow of control resumes with the
statement following the body of the loop.

Example:

> **printlevel := 0:**

> **listsum := 0;**

> **for i in [1,2,3,4,5] do**

**if i >= 5 then break fi;**

> **listsum := listsum + i;**

> **od;**

> **listsum;**

10

> **printlevel := 1:**

next;

The **next** statement is used in **for** and **while** loops to
terminate the current iteration of the loop. Flow of control resumes with
evaluation of the loop condition.

Example:

> **printlevel := 0:**

> **listsum := 0;**

> **for i in [1,2,3,4,5] do**

> **if type(i, odd) then**

> **next;**

> **fi;**

> **listsum := listsum + i;**

> **od;**

> **listsum;**

6

> **printlevel := 1:**

proc (*name-sequence*)

local *name-sequence*;

options *name-sequence*;

*statement-sequence*;

end;

The **proc ( name-sequence)** is the procedure header, and the

Maple documentation variously refers to certain routines as being "functions"
or "procedures". Syntactically, they are all the same kind of object, and are
all implemented using **proc**. The only difference between functions and
procedures is in side-effects. Functions use the values passed as parameters,
but otherwise leave those arguments alone. Procedures may treat some of those
arguments as variable names, and modify the value that the variable name refers
to. This is the same distinction as you find in other programming languages
that allow both "pass by value" and "pass by reference" parameters.

Notice that there is no specification for the name of the procedure. Since
procedures are objects that can be assigned to variables, the name of the
variable you assign it to is used as the name of procedure. The value of the
procedure is the value of the last expression evaluated (though see the section
on the **RETURN** statement, later in this document).

Example:

> **# Out of curiosity, see if "x" and "y" are mathematical
variables:**

> **x, y;**

x, y

> **f := proc(x)**

> **x^2 + 1;**

> **y := x;**

> **end;**

f := proc(x) x^2+1 end

> **f(2);**

5

> **x, y;**

x, 2

In this example, the global variable "x" is not affected by the formal parameter "x", which is local to function "f". The global variable "y" was affected, since it is not a parameter and was not declared as a local variable.

Example:

> **# Set value of global "a":**

> **a := 0;**

a := 0

> **g := proc(x)**

> **local a, b;**

> **a := b^2 + x;**

> **print(a);**

> **b := 2;**

> **print(`a:`, a, ` eval a:`, eval(a), ` a:`, a);**

> **end:**

> **g(2);**

2

b + 2

2 2

a:, b + 2, eval a:, 6, a:, b + 2

> **# So full evaluation doesn't happen to local variable "a", even**

> **# if evaluation is called. You'd have to assign the result of**

> **# "eval(a)" to "a" to update its value.**

> **a;**

0

> **# Just to check, the global variable "a" is not affected by**

> **# the local variable "a" in function "g".**

*
Options* are used to control run-time behaviour of a procedure. The options
defined for Maple V are **builtin**, **remember**, **system**,
**operator**, and **trace**. **remember** is the one of greatest use
to most users. When you use **option remember**, the values that correspond
to particular parameter lists are stored for future use. This way they can be
retrieved instead of recalculated, a feature particularly useful for recursive
function implementations.

You can force **remember** for particular argument values, whether or not
**option remember** has been specified. You simply perform an assignment to
the function with the appropriate parameter value. For example:

> **h(2) := 3;**

h(2) := 3

> **h(2);**

3

This is why it is necessary to use **proc** to define functions. It is
tempting to try syntactic definitions like **m(x) := x^2**, but what you are
really doing is stating something like "the value of function m at the string
`x` has the value `x`^2", assuming "x" was a mathematical variable when you
entered in the assignment statement. When you try to plot this
pseudo-function, you will find that some forms of plotting (like parameterized
3-D plotting) do not work.

RETURN(*value*);

The procedure terminates processing and returns the value specified. If an
explicit **RETURN(...)** does not terminate the procedure, then the value of
the procedure is result of the last expression evaluated before the procedure
terminated normally.

ERROR(*error-message-string*);

The "ERROR" must be in capital letters. When you use **ERROR** in
procedures to indicate that something has gone wrong, you will see a message
printed of the form:

Error, (in *functname*) *error-message-string*

As is the case with Maple-detected errors, the computation is then interrupted and aborted.

> **x1 := proc(tau, theta)**

> **(a + b*sin(tau))*cos(theta);**

> **end:**

> **y1 := proc(tau, theta)**

> **(a + b*sin(tau))*sin(theta);**

> **end:**

> **z1 := proc(tau, theta)**

> **b*cos(tau);**

> **end:**

> **torus1 := [x1,y1,z1]:**

> **x2 := proc(tau, theta)**

> **a + x1(tau, theta);**

> **end:**

> **y2 := proc(tau, theta)**

> **z1(tau, theta);**

> **end:**

> **z2 := proc(tau, theta)**

> **y1(tau, theta);**

> **end:**

> **torus2 := [x2, y2, z2]:**

> **plotranges := 0..2*Pi, 0..2*Pi:**

> **optionseq := scaling=CONSTRAINED, axes=NONE, numpoints=1600:**

> **plotboth := 'plot3d({torus1, torus2}, plotranges, optionseq)':**

> **a := 10: b := 3:**

> **# Now just use "plotboth" to plot the two surfaces**

> **plotboth;**

Maple will spend a few minutes calculating all the points for plot, then display the result in a separate window. If you find that the window does not display the graph when it opens, just try moving the window or iconizing and opening it again.

To print the graph on a postscript printer, just click on the **print**
button on the plotting window. It will open a pop-up dialog that gives you the
default file name (plotoutfile) that it will write a postscript-format file to.
Move the mouse pointer into this little window and change the filename if you
so desire. Then click on the **postscript** button; after a few moments,
Maple will have finished writing a description of your plot to the file.

To print this file to a postscript printer, from the athena% prompt just use the command:

athena% **lpr -P printername filename**

where *printername* is the name of a postscript printer near you.

> **mypackage[successor] := proc(n) n+1 end:**

A *library* is a collection of Maple objects (typically packages) stored
on disk. Though the implementation can vary across platforms, on Athena a
Maple library is a directory that contains files of source and files in "Maple
internal format", otherwise known as ".m" files.

You need to tell Maple where your libraries will be. This is done with the global variable "_liblist". This variable contains a list of libraries (i.e., directory names) that you want to use in addition to the standard Maple library. Be sure you create the directories first from the athena% prompt before trying to use them in Maple. If you didn't create them before starting Maple, then enter an xterm and use a command like:

athena% **mkdir ~/mylibrary**

athena% **mkdir ~/mylibrary/src**

to create the directories for your library and source off of your home directory.

Example:

> **mylibrary := `/mit/joeuser/mylibrary/`:**

> **_liblist := [ mylibrary ]:**

Now to place a package in a library, you need to save it as a ".m" file in one of the libraries (directories) in "_liblist". You should also place the source for package in the "src" subdirectory of the library. We are going to introduce the string concatenation operator to build the path names for the new library:

Example:

> **save mypackage, `` . mylibrary . `mypackage.m`;**

> **save mypackage, `` . mylibrary . `src/mypackage`;**

> **# Now, lets see if we can load the package in:**

> **with(mypackage);**

[successor]

The concatenation operator "**.**" takes expressions, evaluates them to
strings if possible, then concatenates them together. The only operand that is
not evaluated is the leftmost one. This is why the null string `` was used at
the beginning of each pathname: we wanted "**mylibrary**" to be evaluated.

mint *filename*

Be sure that the file is a source file, not a .m file that is in Maple's own internal format.

To help you debug programs while they are running, you use the Maple command
**trace** and the global variable "printlevel". By setting "printlevel" to
a high value, the values of statements nested in procedures and control
structures is displayed, just as you see at the top level for statements you
enter interactively. For example:

> **testproc := proc(x) if x > 2 then s := x-1; testproc(s) else x fi;
end;**

testproc := proc(x) if 2 < x then s := x-1; testproc(s) else x fi end

> **printlevel := 17:**

> **testproc(4);**

> **testproc(4);**

--> enter testproc, args = 4

s := 3

--> enter testproc, args = 3

s := 2

--> enter testproc, args = 2

<-- exit testproc = 2

2

<-- exit testproc = 2

2

<-- exit testproc = 2

2

> **printlevel := 1:**

The **trace** command is used to selectively trace calls and exits of a
particular procedure. You use **trace( procname)** to turn tracing on
for the procedure

> **trace(testproc);**

testproc

> **testproc(4);**

--> enter testproc, args = 4

--> enter testproc, args = 3

--> enter testproc, args = 2

2

<-- exit testproc = 2

2

<-- exit testproc = 2

2

<-- exit testproc = 2

2

> **untrace(testproc);**

testproc

> **testproc(4);**

2

To learn more about debugging in Maple using **trace** and "printlevel", see
**help('trace')**, **help('printlevel')**, and the section of the
**First Leaves** document called "**Creating and debugging Maple
programs**". To learn more about Mint you can read the man page (once you've
added the maple locker) by typing the following command from the athena%
prompt:

athena% **man mint**

**
Checkpoint.** You have now been given a general overview of what Maple can
do. Experiment with what you have learned. When you want more specific
information on Maple, read the documentation produced by the vendor, including
**First Leaves** and the Maple reference manual(s).