This is algae.info, produced by makeinfo version 4.3 from algae.texinfo.

INFO-DIR-SECTION Programming Languages
START-INFO-DIR-ENTRY
* algae: (algae).		Another Matrix Programming Language
END-INFO-DIR-ENTRY


File: algae.info,  Node: Top,  Next: About Algae,  Prev: (dir),  Up: (dir)

   For algae 4.3.6; February 22, 2004.

   Typing "q" exits, "?" lists all INFO commands, "h" gives an INFO
tutorial, "m" selects menu items, etc.  Items are selected by any unique
case-insensitive abbreviation of their name.  For example, type "m" and
then "prim" to select the `Primer' item in the menu below.

* Menu:

* About Algae::			History and acknowledgments.
* Primer::			An introduction to Algae.
* Examples::			Some example programs in Algae.
* Language::			Variables, operators, and expressions.
* Data::        		Scalars, vectors, matrices, ...
* Standard Functions::  	Reference guide for the standard functions.
* Running Algae::	        Starting and running the Algae interpreter.
* Projects::			The Algae wish list.
* Bugs::			Bugs, and how to report them.
* Concept Index::		An item for each concept.
* Function Index::		An item for each standard function.

Copyright (C) 1994-2004  K. Scott Hunziker.
Copyright (C) 1990-1994  The Boeing Company.

   Algae is free software.  You may redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.

   Algae is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

   You should have received a copy of the GNU General Public License
along with Algae; see the file `LICENSE'.  If not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   The copyright to major portions of Algae belongs to The Boeing
Company.  The following permission notice and warranty disclaimer
pertain to those portions of the code:

     Permission to use, copy, modify, and distribute this software and
     its documentation for any purpose is hereby granted, provided that
     the above copyright notice appear in all copies, that both the
     copyright notice and this permission notice and warranty
     disclaimer appear in supporting documentation, and that the names
     of Boeing or any of its entities not be used in advertising or
     publicity pertaining to distribution of the software without
     specific, written, prior permission.

     BOEING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND
     NONINFRINGEMENT.  IN NO EVENT SHALL BOEING BE LIABLE FOR ANY
     SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER
     IN AN ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION,
     ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
     THIS SOFTWARE.

   Caution: Use of this product as a substitute for a healthy physical,
emotional, and spiritual life is not recommended and could be harmful.


File: algae.info,  Node: About Algae,  Next: Primer,  Prev: Top,  Up: Top

About Algae
***********

   Algae is an interpreted language for numerical analysis.  Algae was
developed because we needed a fast and versatile tool, capable of
handling large problems.  Algae has been applied to interesting dynamics
problems in aerospace and related fields for more than a decade.

   This document describes both Algae, the programming language, and
`algae', the interpreter.  Neither one of them is complete.  Even so,
they offer some unique capabilities that we hope you'll find useful.

   Algae was designed and implemented by Scott Hunziker and Mike
Brennan.

   Algae grew up in the "Structures Outback" of the Boeing Aerospace
Company (now the Boeing Defense & Space Group).  Way back in 1989, Bill
Russell convinced Bob Vos, the head of Boeing's ISM project, that ISM
needed an interactive language.  With Dave Beste's help, Bill put
together a crude system (it looked a lot like MATLAB) with a recursive
descent parser.  They called it ISMLAB.  After Bill got a real job,
Scott Hunziker took over and made major changes.  ISMLAB, along with the
entire ISM project, was cancelled ignominiously in 1991.

   Scott Hunziker and Mike Brennan began work on a successor to ISMLAB
called AMPL (A Matrix Programming Language) with internal Boeing
funding.  (The author remembers well the first day of their
collaboration, when he inadvertently showed Mike that AMPL could
multiply two matrices and get the wrong answer.)  As AMPL took shape,
the internal funding dried up, leaving Scott to maintain it in his spare
time.  Boeing generously released AMPL to the public in 1994.  The name
was changed to Alki in 1995 because, by then, an unrelated package
called AMPL was being distributed through netlib.  That name also had a
conflict, and it was finally changed to Algae in early 1997.

   Thanks to Don Morris for contributing the plotting code (not to
mention countless bug reports), and Ian Searle for advice, constructive
criticism, and pizza.


File: algae.info,  Node: Primer,  Next: Examples,  Prev: About Algae,  Up: Top

Primer
******

   What follows is a quick introduction to Algae.  It shows many simple
examples, but leaves out the detailed descriptions.  *Note Language::,
for more details about the Algae language.

   The first thing that you'll need to know is how to get Algae
started.  If your system is properly set up, it's a simple matter of
typing the command `algae'.  This brings Algae up in interactive mode;
a prompt is displayed and it waits for you to start typing statements.
Later we'll discuss other options, such as giving Algae a file of
statements to execute in "batch" mode.

   This manual is available on-line through the `info' function; type
`info()' to view it.  You can go to a specific topic by naming it as an
argument.  For example, `info("operators")' takes you directly to the
description of Algae's operators.

   An Algae "statement" describes the operations to be performed.  For
example, the statement

     1+sin(2)

tells Algae to add 1 to the sine of 2.  Statements may be terminated
with a newline, a semicolon, or a question mark; the results are printed
unless a semicolon is used.

   The statement

     printf ("hello, world\n");

prints a hopeful little "hello, world" message to the terminal.  This
is exactly like the C language, right down to the `\n' escape sequence
to indicate a newline.  If you know C, you'll probably notice many
other similarities between its syntax and that of Algae.

   Like most computer languages, Algae has "variables" to which values
can be assigned.  In Algae, these variables need not be declared before
being used, and may be created or destroyed during a session.  If you
type the statement `x=1', the variable `x' will be created if it
doesn't already exist.  If `x' already had a value, then assignment to
`x' destroys its previous contents.

   The values taken on by variables are known as "entities", which have
various "classes" such as `scalar', `vector', `matrix', `table', etc.
A builtin function called `class' returns the class of its argument, so
if you make the assignment `x=1' then the statement `class(x)' returns
`"scalar"'.

   Notice that a scalar is not the same thing as a one-element vector
or as a one-by-one matrix.  The builtin functions `scalar', `vector',
and `matrix' may be used to convert from one to another.  For example,
`matrix(7)' returns a matrix with one row and one column, its single
element having the value 7.  Algae will often make these conversions
between classes automatically.  In the code

     x = [ 3, 2, 1 ];
     y = sort (x);

the `sort' function first converts its matrix argument `x' into a
vector and then returns another vector with the same elements but
sorted in increasing order.  (An expression enclosed in brackets defines
a matrix, as we'll discuss later.)

   Besides its class, an entity may have other attributes which are
stored as its "members".  For example, the number of rows in a matrix is
stored in a member called "nr".  Members are referenced with the "dot"
operator, so if `M' is a matrix, then `M.nr' returns its row size.
Most entities have one or more predefined members (such as `nr' in
matrices) that you cannot directly modify.  You can create new members
simply by assignment.

   A function called `show' prints information about an entity and its
members.  Another function, `members', returns a vector containing the
names of all the members of its argument.

   When a non-existent variable or member is referenced, the special
value `NULL' is returned.  For example, the line

     a = 1; a.nr

(which consists of two statements) prints "NULL", since scalars do not
start life with a member `nr'.

   The NULL constant may be used on the right-hand side of assignments,
effectively deleting the previous value of an entity.  Actually, the
entity still exists, but it has the value NULL.  You can perform a
number of other operations on NULL, such as in

     if (x != NULL) { x.class? }

   All array entities (and that includes scalars) have a member called
`type', which may have one of these values: "integer", "real",
"complex", or "character".  The constant `1' is an integer, but `1.0'
has real type.  Algae has no complex constant like Fortran does--you
have to use an expression such as `sqrt(-1)'.  Users often make the
assignment `i=sqrt(-1)' when they first start up Algae and then use
expressions like `1+2*i' for their complex numbers.

   The "character" type refers to a string of characters.  It is
specified using double-quotes as we did for `"hello world"' above.  A
character scalar like `"1"' is different than an integer scalar like
`1', and an expression like `1+"1"' is not allowed.

   A "vector" is a one-dimensional array of values.  For example,
`x=1,2,3' specifies a vector with three elements.  The elements in a
vector are numbered starting at one, and the total number of elements
is given by its `ne' member.  All of the elements have the same type.

   Actually, the comma character is Algae's "append" operator.  You can
put several expressions together in a vector, as in

     v = 1, sin(2), 3+4;

   A "subvector" expression may be used to specify a particular element
or elements.  You do that simply by following the vector with a
"specifier" enclosed in brackets.  For example, `v[3]' gives a scalar
having the value of the third element of `v'.  If the specifier is a
scalar, then the result is a scalar; otherwise, the result is a vector.

   A more complicated example is

     aset = 3, 9, 15;
     x = v[aset][2];

Here, `x' gets the value of the ninth element of `v'.  You can also
assign to a subvector, so `v[1]=0' sets the first element of `v' to
zero.

   Vectors have a member `eid' (it stands for element id) that contains
labels for its elements.  You don't need labels (`eid' may be NULL),
but they can be pretty useful.  For one thing, they can help you to
avoid errors by not allowing you to perform certain operations unless
the labels match.  If you try to add two vectors and they both have
labels, then the labels must be identical.

   You can also use labels instead of element numbers in a subvector
expression.  You do this by using character strings as the specifier.
For example, the code

     weight =        172,    216,     188;
     weight.eid =  "Tom", "Dick", "Harry";

sets up the vector `weight' with character string labels.  Then
`weight["Dick"]' gives Dick's weight of 216.

   Vectors can be generated by using the colon operator.  The expression
`1:5:2' gives a vector whose first element is `1', last element is no
more than `5', and has a difference of `2' between each successive
element.  In other words, `1:5:2' is the same as `1,3,5'.  If you leave
off the second colon and the third operand, then Algae infers a `1' for
the third operand.  Thus, if `n=100', then `1:n' is the vector
containing all the integers from `1' through `100'.

   A "matrix" is a two-dimensional array of values.  The expression
`[1,2;3,4;5,6]' specifies a matrix with three rows and two
columns--rows are given as vectors and are separated by semicolons.

   Submatrix expressions work just like subvector expressions, but with
a semicolon to separate the row specifier from the column specifier.
The expression `M[3;2,3]' gives a vector containing the elements of `M'
in its third row and second and third columns.  If both specifiers are
scalars, then the result is a scalar.  If only one specifier is a
scalar, then the result is a vector.  Otherwise, the result is a
matrix.  The members `nr' and `nc' give the number of rows and columns
of a matrix.

   Matrices have both row and column labels.  They're stored in the
members `rid' and `cid', respectively.  As with vectors, character
strings used as specifiers in submatrix expressions refer to the labels.

   A "table" is an entity that simply holds a collection of other
entities.  For example, the statements

     x = 1; y = "foo", "bar";
     t = { x; y };

result in a table `t' that contains the scalar `x' and the vector `y'.
Instead, we could write

     t = { x = 1; y = "foo", "bar" };

and get the same table.  In the latter case, though, `x' and `y' exist
only inside the table.

   You can put any class of entity into a table, even another table.
The members are referenced with the "dot" operator, just like the other
entities.  The line `a={u=1;v=2}; a.u+a.v' prints the value 3.  You can
add two tables (the members of the right-hand table are inserted into
the left-hand table) and subtract two tables (the members of the
left-hand table having the same name as a member of the right-hand table
are removed).

   Algae normally executes statements in the order that it receives
them, but the control-flow statements `if', `for', `while', and `try'
can change that.  The code

     if (x > 0) { y = 1/x; }

is an example of an `if' statement.  The parentheses are required
around the test expression.  If that expression is "true", then the
statements following it are executed.  The `if' statement may also have
an `elseif' part, an `else' part, or both, so

     if (x > 0)
     {
         printf ("positive");
     elseif (x < 0)
         printf ("negative");
     else
         printf ("zero");
     }

prints the sign of `x'.  (But you should use the `sign' function,
instead.)

   As long as only scalars are involved, Algae's relational, equality,
and logical operators probably won't surprise you.  An expression is
`1' if it's true and `0' if it's false.  The relational operators are
`>', `>=', `<', `<='.  The equality operators are `==' and `!='.  The
logical operators are `&', `|', and `!'.  Two additional logical
operators, `&&' and `||', are special; they are described later.

   Where these operators might surprise you is when vectors and matrices
are involved.  Like most Algae operators, they work on an
element-by-element basis.  For example, if `A' and `B' are both
matrices, then the expression `A==B' has several features:

   * `A' and `B' must have the same size.

   * Their labels must match.

   * The expression returns a matrix with the same size as `A' and `B',
     every element of which is either `1' or `0' depending on whether
     the corresponding elements of `A' and `B' are equal.

You can see, then, that `A==B' doesn't give you a simple true or false
answer but rather a matrix of answers.

   The `if' statement, however, does need a simple true or false in
order to decide whether to execute its statements or not.  It does this
by recognizing certain entities as false--all others are true.  The
"false" entities are as follows:

   * NULL.

   * Numeric entities in which every element is zero.

   * Character entities in which every element is `""'.

   * Vectors and matrices with no elements.

   * Tables with no members.

   What gets new users into trouble is a statement like

     if (A == B) { done = 1; }

If `A' and `B' are matrices, then `A==B' returns a matrix of ones and
zeros.  The `if' statement interprets that as "true" if even one of its
elements is nonzero.  In words, the above statement starts out "If any
element of `A' is equal to the corresponding element of `B', then ..."
The difficulty is that the element-by-element "equality" operation is
not the same as a test of the equality of two arrays.  If the latter
test is what you really want, then you should use the `equal' function
instead.

   On the other hand, the statement

     if (A != B) { done = 0; }

does work in both senses.  The expression `A!=B' returns a matrix that
has nonzero elements where the corresponding elements of `A' and `B'
are unequal.  Thus this expression also serves as a test of the
inequality of the two arrays.

   The `&&' ("and") and `||' ("or") operators are special in two ways:
they don't perform element-by-element like the other operators in this
section, and they "short-circuit" by skipping evaluation of the second
operand if the result is already established by the first operand.

   Each operand of `&&' and `||' is evaluated for "truth" in the same
way that the `if' test does.  For `&&', if the first operand evaluates
to "false" then the second operand is not evaluated and the result of
the operation is 0.  For `||', if the first operand evaluates to "true"
then the second operand is not evaluated and the result of the
operation is 1.

   For example, in the expression

     x != NULL && x.type == "integer"

`x' is first checked to see if it's NULL.  If it is, then the first
operand of `&&' is 0 and that's also the result of the entire
expression.  In that case, the member reference `x.type' is never
evaluated.  This is convenient, since that would otherwise be an error.

   An `if' statement such as

     if (x < tol) { x = tol; }

could be written instead as

     x < tol && (x = tol);

   The parentheses are required in the second version, since the
precedence of `=' is lower than that of `&&'.  Although they accomplish
the same thing, the first version is recommended; it is easier to read
and executes a bit faster.

   Algae has two control-flow statements that perform looping: `while'
and `for'.  The `while' statement executes a set of statements over and
over, as long as a given condition is true.  For example, the code

     a=0; b=1;
     while (b < 10000)
     {
       c = b;
       b = a+b;
       a = c;
     }
     c?

computes and prints the largest Fibonacci number less than 10000.  The
interpreter checks to make sure that `b<10000', executes the statements
in the `while' block, and then repeats.  The first time that the
expression `b<10000' evaluates false, the loop terminates.

   The `for' statement also causes looping, but in a different way.
Assuming that `v' is a numeric vector, the code

     for (i in 1:v.ne) { v[i] = 1 / v[i]; }

inverts each of its members.  Inside the parentheses, the keyword `in'
separates an identifier on the left and a vector expression on the
right.  In this example, the vector expression is `1:v.ne' which
contains the integers from 1 to the length of `v'.  The `for' loop sets
`i' equal to the first element, 1, and then executes the statement
`v[i]=1.0/v[i];'.  Then `i' is set equal to the second element, and the
statement is executed again.  This cycle repeats until all of the
elements of `1:v.ne' are used.

   The previous example also illustrates an important topic concerning
both `while' loops and `for' loops.  Essentially the same results would
be obtained with the statement `v=1/v'.  This obviously takes less
typing and is easier to read.  The really important difference, though,
is that it is far more efficient.  With the `for' loop, all of the
operations (assignment, division, etc.) are performed by the
interpreter.  Although Algae is fast, it can't possibly compete with
doing the same job in C, as `v=1/v' is.  On my computer, it's about 60
times faster.

   Sometimes it's convenient to interrupt the execution of `while' and
`for' loops.  The `continue' statement causes another iteration of the
loop to begin immediately.  If we wanted to invert the nonzero elements
of a vector, we could write

     for (i in 1:v.ne)
     {
       if (v[i] == 0) { continue; }
       v[i] = 1 / v[i];
     }

   The `break' statement goes even further, exiting the loop
altogether.  For example, we could have written our Fibonacci routine as

     a=0; b=1;
     while (1)
     {
       c = b;
       if ((b = a+b) > 10000) { break; }
       a = c;
     }
     c?

The `continue' and `break' statements affect execution of only the
innermost enclosing loop.

   It's important to note that `continue' and `break' are statements,
not expressions.  The code

     x < 0 && break;

is not valid, since the operands of `&&' must be expressions.

   The `try' statement is the remaining control-flow statement.  It is
used to modify Algae's response to something called an "exception".
When an exception occurs, we say that it has been "raised".  Many error
conditions (dividing by zero, running out of memory, etc.) cause an
exception to be raised.  You may also raise an exception directly by
calling the `exception' function.

   When an exception is raised, Algae's default action is to stop
execution.  If it's running interactively, it returns to the command
line prompt; otherwise it exits completely.  This action can be modified
by using the `try' statement.  If an exception is raised within the
`try' block, execution continues at the point immediately following
that block.  For example, the statement

     try { i += 1; }

increments `i' by one if possible.  If an error occurs (say `i' was
NULL), then Algae just moves on to execute the next line.  Although
it's probably not a good idea, we could use this instead of `break' in
the previous Fibonacci example:

     a=0; b=1;
     try
     {
       while (1)
       {
         c = b;
         if ((b = a+b) > 10000) { exception (); }
         a = c;
       }
     }
     c?

There's a real difference between these approaches, though.  In the
version using the `break' statement, the result is printed only when
the correct value is reached.  In the `try' version, the result is
printed regardless of why the exception was raised--if Algae received
an interrupt signal while in the middle of the loop, it would jump out
of the `try' block and then print an incorrect value.

   The `try' statement has an optional `catch' clause, which is
something like the `else' clause of an `if' statement.  Any statements
that follow `catch' are executed only if an exception is raised while
in the preceding part of the `try' block.  Also, exceptions that occur
within the `catch' block are not handled specially.  For example,

     try
     {
       v = 1/v;
     catch
       message ("I can't do that, Dave.");
       exception ();
     }

   would print a message if it had trouble performing the inverse and
then stop execution.  If no exception occurs prior to the `catch'
clause, then execution continues following the end of the `try'
statement.

   The language syntax does not allow a `break' or `continue' statement
to be positioned such that it would cause execution to jump out of the
`try' block.

   Like other computer languages, Algae has "functions".  Some functions
(like `sin' and `printf') are "builtin", meaning that they are part of
the Algae executable file.  Others, called "user functions", are those
written in the Algae language.  A function is called by giving its name
followed by a parenthesized list of "arguments".  The arguments are
separated by semicolons, and their values are passed to the function.
Since only the values are passed, the function cannot modify the
variables that you pass it.

   For example, let's assume that you're calling the function `shady'.

     x = 1;
     y = shady (x);

The value returned by `shady' is assigned to `y'.  You can't tell by
looking at it what class of entity (scalar, matrix, etc.)  `shady'
returns.  In fact, that might even change from one call to the next.
Rest assured, though, the value of `x' is still 1, no matter what
happened in `shady'.

   Algae functions are entities--just like scalars and matrices.  That
means that you can perform operations on them as you do with other
entities.  For example, the statement

     my_sin = sin

creates a new function called `my_sin' that works just like the
original `sin' function.  Of course,

     sin = NULL;

gets rid of the `sin' function completely--probably not a very good
idea in most cases.

   Functions may be defined during an interactive session or simply
included from files.  As an example, consider writing a function called
"findit" that will look through the elements of a vector for a given
value, returning the locations where it found it.  The following
function should do the job:

     findit = function (s; v)
     {
       local (w; i);
       w = vector ();
       for (i in 1:v.ne)
       {
         if (v[i] == s) { w = w, i; }
       }
       return w;
     }

(The builtin function `find' does this job much more efficiently.)  The
`local' statement declares its arguments as having local scope.  For
example, the assignment to `w' would have no effect outside this
function.  Without the `local' declaration, the assignment would change
the value of `w' globally.

   The `return' statement causes execution of the function to terminate
and passes it's expression as the function's return value.  Recursive
calls to a function are no problem.  For example, we could write a
function to compute factorials as

     fact = function (n)
     {
       if (n < 2) { return 1.0; else return n * fact (n-1); }
     }

   This function has one slight problem.  (Several, really, if you
consider that it does no error checking.)  If we later decide to change
its name by typing `factorial=fact', it still calls function `fact'
internally.  Now if we're really mean-spirited we can change `fact' as
in `fact=sin'; now `factorial' gives wrong answers.  The way to handle
this is to call the function `self' when you make a recursive function
call, as in

     fact = function (n)
     {
       if (n < 2) { return 1.0; else return n * self (n-1); }
     }

   The `self' keyword refers to the current function.  Besides
recursive function calls, it's also useful for keeping data local to a
function.  For example, consider a function that returns the "shape" of
its argument:

     shape = function (x)
     {
       return self.(class(x)) (x);
     };
     
     shape.scalar = function (x) { return NULL; };
     shape.vector = function (x) { return x.ne; };
     shape.matrix = function (x) { return x.nr, x.nc; };

   This `shape' function determines the class of its argument and then
calls the appropriate member function.  (The standard `shape' function
additionally provides some error checking.)


File: algae.info,  Node: Examples,  Next: Language,  Prev: Primer,  Up: Top

Example Programs
****************

   Following are several examples designed to show off Algae's
capabilities as well as to give you a feel for how it is used.  The
`examples' directory in the source distribution of Algae contains some
additional code for perusal.

* Menu:

* Temperatures::        Fahrenheit to Celsius conversions
* Reading Numbers::     Reading and summing numbers
* Powers::              Integer powers


File: algae.info,  Node: Temperatures,  Next: Reading Numbers,  Prev: Examples,  Up: Examples

Temperature Conversion
======================

   This Algae program prints a table of Fahrenheit temperatures and
their Celsius equivalents:

     # Print temperature conversions
     fahr = sort (0:300:20, 32, 212);
     celsius = (5/9)*(fahr-32);
     [fahr;celsius]'?

Its output looks like this:

     [         0.000       -17.78 ]
     [         20.00       -6.667 ]
     [         32.00        0.000 ]
     [         40.00        4.444 ]
     [         60.00        15.56 ]
     [         80.00        26.67 ]
     [         100.0        37.78 ]
     [         120.0        48.89 ]
     [         140.0        60.00 ]
     [         160.0        71.11 ]
     [         180.0        82.22 ]
     [         200.0        93.33 ]
     [         212.0        100.0 ]
     [         220.0        104.4 ]
     [         240.0        115.6 ]
     [         260.0        126.7 ]
     [         280.0        137.8 ]
     [         300.0        148.9 ]

   This program does quite a bit in only four lines.  The entire first
line is a "comment" (because it starts with `#') and is ignored by
Algae.

   In the second line we define the Fahrenheit temperatures for our
table.  The expression `0:300:20' gives a vector that goes from 0 to
300 in steps of 20.  We add two more elements, 32 and 212, to that
vector by using the comma operator.  Then we use the `sort' function to
sort it in increasing order.  Finally, our vector of Fahrenheit
temperatures is assigned to the variable `fahr'.  Nothing is printed by
this statement, since it ends with a semicolon.

   The third line computes the Celsius equivalents using the familiar
conversion formula.  First 32 is subtracted from each element of
`fahr'.  Then each element is multiplied by 5/9.  The result is
assigned to the variable `celsius'.  Here, again, nothing is printed.

   Even though all of the terms so far have been integers, `celsius' is
a real-valued vector.  Unlike some programming languages, integer
division in Algae does not result in truncation--the expression `5/9'
returns a real value that is approximately 0.556.

   The last line prints the temperatures out as a matrix, with the
Fahrenheit temperatures in the first column and their Celsius
equivalents in the second column.  We do that by using brackets to form
a matrix with `fahr' in the first row and `celsius' in the second row
and then transposing the matrix with the `'' operator.  The question
mark on the end is not necessary, since the matrix would also be
printed without it, but it does call attention to the line as one that
prints.


File: algae.info,  Node: Reading Numbers,  Next: Powers,  Prev: Temperatures,  Up: Examples

Reading and Summing Numbers
===========================

   This Algae program reads a bunch of numbers, adds them up, and
prints the result:

     # Read and sum some numbers
     sum = 0;
     $read = 1;
     while ($read) { sum += readnum(); }
     sum?

   The program reads numbers one at a time and adds them to `sum', so
in the first line `sum' is initialized to zero.  The `readnum' function
is used to read the numbers.  This function is one of the few standard
functions that has a side effect:  it assigns to the variable `$read'
the number of values that it read.  It will be less than the number you
asked for if `readnum' runs out of data.

   The `while' loop executes its statements repeatedly until its
condition tests true.  We set `$read' to 1 (true) first, so we know
that the `while' loop will execute at least once.  After that, the
`while' loop continues until `$read' is eventually set to 0 by the
`readnum' function.  When the `while' loop is done, the last line
prints `sum'.

   Usually, we give the `readnum' function two arguments: a "shape"
vector and a file name.  The "shape" vector describes the number of
values to read and in what form (vector, matrix, etc.) they should be
returned.  The values are read from the named file.  Since the program
above gives neither argument, `readnum' simply reads one value from the
standard input device.

   The `+=' operator adds the value on the right to the variable on the
left; the expression `sum+=readnum()' does the same thing as
`sum=sum+readnum()'.  Every time the `while' loop repeats, `sum' is
increased by the value returned by `readnum'.  When `readnum' runs out
of data, it returns 0 (so `sum' isn't changed) and sets `$read' to 0
(so the `while' loop quits looping).

   Unless you redirect standard input, this program will quietly read
what you type until you signal an end-of-file (`C-d' on UNIX systems and
`C-z' on VMS).


File: algae.info,  Node: Powers,  Prev: Reading Numbers,  Up: Examples

Integer Powers
==============

   This program illustrates the use of a function.  In it, we define the
function `power' that computes integer powers of its argument.  We also
show some Algae code that calls `power'.

     # power:  raise `x' to the `n'-th power
     power = function (x; n)
     {
       local (y);
       y = x;
       while (n > 1)
       {
         y = y * x;
         n -= 1;
       }
       return y;
     };
     
     power (2; 8)?
     power ([ 1, 2; 2, 3 ]; 4)?

   The first line of this program is an ordinary assignment statement,
which assigns the function on its right side to the variable `power'.
The function's arguments are defined in the parentheses that follow the
`function' keyword.  In this case, there are two arguments:  `x' and
`n'.

   In Algae, all function arguments are called "by value".  When a
function is called, it gets copies of what the calling program gave as
arguments and can modify them without changing the values retained by
the calling program.  In the `power' function we decrement `n' each
time through the `while' loop, but this has no effect on the calling
program.

   The `local' statement defines its argument, the variable `y', as
having local scope.  This means that `power' has its own temporary
variable called `y' that is defined only within that function.  This
`y' is first given the value of `x' and then, inside the `while' loop,
repeatedly multiplied by `x' until `n' is no longer greater than 1.

   The value that `power' computes is returned to its caller by the
`return' statement.  Any expression may follow `return', and any number
of `return' statements may appear in a function.  If the function has
no return statement, it returns NULL to its caller.

   The first time we call `power', it returns (and the calling program
prints) the value 256.  In this case `power' is really not very useful,
since we could have obtained the same result with the expression `2^8'
using Algae's exponentiation operator.

   The `power' function does have a use, though, as the second call to
it shows.  Algae's exponentiation operator performs in an
element-by-element sense, so `[1,2;2,3]^4' returns

     [           1         16 ]
     [          16         81 ]

In contrast, `power' performs in a matrix sense.  In the program above,
it returns

     [          89        144 ]
     [         144        233 ]

   The algorithm used in the `power' function above can be improved
upon by using successive squaring:

     power = function (x; n)
     {
       if (n == 1)
       {
         return x;
       elseif (n%2)
         return x * self (x; n-1);
       else
         x = self (x; n/2);
         return x * x;
       }
     };

   This `power' function might be useful, but it's certainly not ready
for prime-time.  Notice that it gives wrong answers if `n' is 0 or a
negative integer.  What happens for the expression `power(4;1/2)', in
which `n' is not an integer?  To make `power' more robust you'd
probably want to add some `if' statements to check for illegal
arguments.


File: algae.info,  Node: Language,  Next: Data,  Prev: Examples,  Up: Top

The Algae Language
******************

   In Algae, variables and operators combine to form expressions and
statements.  The rules for this are mostly conventional; for example,
the statement `a=b+c' means that the sum of `b' and `c' is assigned to
the variable `a'.  In Algae, however, the concept of addition (as well
as many other operations) is expanded to include operations between a
variety of data classes.

* Menu:

* Entities::
* Variables::
* Operators::
* Expressions::
* Statements::
* Functions::


File: algae.info,  Node: Entities,  Next: Variables,  Prev: Language,  Up: Language

Entities
========

   The basic unit of data in Algae is the "entity".  Every entity has
an attribute called its "class" which describes it as a "scalar",
"vector", "matrix", etc.  The built-in function `class' returns the
class of its argument as a character string.  Thus

     x = 1.2E3; class(x)?

prints "scalar" and

     class (cos)?

prints "function".  Naturally, the statement

     class (class (log))?

prints "scalar", since `class' returns a scalar character string.

   Entities also contain "members", in which various additional
attributes of the entity are stored.  For example, matrix entities have
members such as `type', `density', and `symmetry'.  These members are
themselves entities, so it is not unusual to have several levels of
membership (a member of a member of a member).  *Note Data::, for a
description of the various classes.

   The "dot" operator is used to refer to members.  The statements

     x = 1; x.type?

print "integer", the value of the `type' member in `x'.  The line

     foo = 1492; foo.bar?

prints "NULL", since scalars don't contain a `bar' member when they're
created.  You could give it one, of course:

     foo.bar = "Columbus"


File: algae.info,  Node: Variables,  Next: Operators,  Prev: Entities,  Up: Language

Variables
=========

   A "variable" is a symbol that refers to a named entity; the entity
is known as the symbol's "value".  A variable comes into being when a
value is assigned to it; there are no explicit declarations.

* Menu:

* Variable Names::
* Evaluation::
* Scope::
* Predefined Variables::


File: algae.info,  Node: Variable Names,  Next: Evaluation,  Prev: Variables,  Up: Variables

Variable Names
--------------

   Variables have names consisting of letters, digits, dollar signs
(`$') and underscores (`_').  A variable name cannot begin with a
digit.  Variable names are case sensitive, so the variables `foo' and
`Foo' are distinct.

   We generally use names that begin with `$' to refer to global
variables that are set at startup or that have some kind of side effect.
For example, the variable `$beep' acts like any other variable, but
also control's Algae's sound effects.  The `who' function does not
report variables that begin with `$' unless you give it the argument
`"$"'.

   One variable name is special--the variable `$$' refers to the global
symbol table.  For example,

     a = "x";
     $$.(a)

prints the value of the global variable `x'.  You can use `$$' like any
other variable, except that you cannot reassign its value.

   The only limitation on the length of a variable name is that it must
have at least one character.  Short names are convenient for interactive
work, but longer, descriptive names have advantages in functions and
scripts.


File: algae.info,  Node: Evaluation,  Next: Scope,  Prev: Variable Names,  Up: Variables

Evaluation of Variables
-----------------------

   When a variable name is encountered in an expression, it is
evaluated by replacing the variable name with the corresponding named
entity.  If it is an argument to a function, then a copy is made
(conceptually, if not in fact) and passed to the function.  Thus, in a
function call like `func(a)' (*note Functions::), the function `func'
only gets a copy of `a' and can't modify the `a' belonging to its
caller.

   There is one exceptional case, involving the "dot" operator, in which
an identifier is not evaluated as a variable name.  An identifier on the
right side of a member expression is taken literally as the name of the
member.  For example, the statement

     v.type

prints the value of `v''s member called `type'.  You could well have a
variable named `type', but it would not affect the member expression
above.

   Alternatively, the statement

     v.(type)

   has an expression to the right of the "dot" operator, not a simple
identifier, and so prints the value of the member of `v' named by the
variable `type'.


File: algae.info,  Node: Scope,  Next: Predefined Variables,  Prev: Evaluation,  Up: Variables

Scope of Variables
------------------

   Variables referenced from within functions are global in scope unless
they are arguments to the function or are declared local with the
`local' statement.  For example, the function

     init = function ()
     {
       i = sqrt (-1);
       e = exp (1);
       pi = acos (-1);
     };

could be used to initialize some commonly used variables.  Once you
executed `init()', the variables `i', `e', and `pi' would be globally
defined.

   At the same time, you could have another function

     egg_hunt = function (v)
     {
       local (i);
       for (i in 1:v.ne)
       {
         if (v[i] == 0) { return i; }
       }
     }

in which `i' has local scope.  Here, you can't modify or even get the
value of the global variable `i'.

   The form of the `local' statement is similar to a function call, and
multiple variables may be specified by separating them by semicolons.

   The `local' statement is unusual, in that it is a directive to the
parser rather than something that is coded.  This means that it takes
effect when the parser sees it, not when it's executed.  In the code

     f = function ()
     {
       a = 1;
       if (0) { local (a); }
       a = 2;
     }

the global variable `a' gets set to 1.  Even though the code in the
`if' block is not executed, after seeing it the parser considers `a' to
be a local variable.  Normally, one simply puts `local' statements at
the beginning of a function.

   The `veil' statement allows you to make a temporary change to a
global variable which will remain active from that point until the end
of the current dynamic scope, typically until the function ends.  For
example, the function

     prt = function (x)
     {
       veil (pi);
       pi = "apple";
       bake ();
     };

changes the value of the global variable `pi' while it's executing, but
`pi' reverts to its previous value when `prt' finishes.  If the
function `bake' referred to `pi', it would use or modify the temporary
value.

   By dynamic scope, we refer to the current execution unit.  Within a
function, that lasts as long as the function is executing.  Otherwise,
the dynamic scope is the current file, except that for the `eval' and
`exec' functions it is the argument string itself.  Also, if executing
in interactive mode and not in a function, then the dynamic scope
extends only to the end of the last statement on a line.

   Unlike the `local' statement, the effect of the `veil' statement
takes place at the time it is executed.  Once a variable is veiled (and
before you set it to something else), it has the same value as the
associated global variable.


File: algae.info,  Node: Predefined Variables,  Prev: Scope,  Up: Variables

Predefined Variables
--------------------

   Several variables are already defined for you when Algae starts up.
Some of these are used to control Algae, and some provide you
information.  The predefined variables are:

`$beep'
     If this variable is "true" (that is, `test($beep)' returns 1),
     then error messages include a BEL character.  This causes most
     terminals to beep.  On startup, `$beep' is 0.

`$digits'
     This variable specifies the number of significant digits that
     Algae prints for real and complex numbers.  On startup, `$digits'
     is 4.

`$pid'
     On startup, `$pid' contains the "process id" of the Algae process.

`$program'
     On startup, `$program' gives the name of the current Algae
     program.  This will normally be `"algae"'.  It would be different
     if, for example, you had changed the name of the Algae executable.

`$prompt'
     This variable controls Algae's interactive prompt.  It is expected
     to be a character vector with two elements--on startup it is

          (  "> ", "  " )

     The first element is Algae's first-level prompt.  When Algae is
     waiting for another line of input before it executes what it has
     already seen, it presents its second-level prompt.  The second
     element of `$prompt' defines this second-level prompt.  If Algae
     can't make sense of `$prompt''s value, it does without a prompt.

`$read'
     The `$read' variable is set as a side-effect of the `readnum'
     function.  It reports the number of values read in the last call to
     `readnum'.

`$term_width'
     This variable tells Algae the width of your terminal in
     characters.  Algae will attempt to adjust its display to fit
     within this width.  On startup, Algae will attempt to sense this
     on its own.  If `term_width' is set to 0, Algae will not wrap
     lines.

`help'
     This is simply a character scalar that provides a few basic
     instructions for using Algae.

   You may wish to set some of these variables (like `$beep' or
`$prompt') every time you use Algae.  This is conveniently done by
putting the assignments in the `.algae' file in your home directory.


File: algae.info,  Node: Operators,  Next: Expressions,  Prev: Variables,  Up: Language

Operators
=========

   Algae has unary, binary, and ternary operators to perform a variety
of operations.  The standard arithmetic operators (`+', `-', `*', `/',
etc.) are available and have the usual precedence.  The caret `^' is
for exponentiation: 8^2 equals 64.  The single quote character `''
denotes the conjugate transpose.

   With a few exceptions, all operators work in the "element by element"
sense.  For example, if `A' and `B' are matrices with the same size,
then `A/B' returns a matrix, each element of which is the quotient of
the corresponding elements of `A' and `B'.  The `*' operator works in
an "inner product" sense, so `A*B' is a matrix multiplication.  The `@'
operator is Algae's "element by element" multiplication operator.

   When an operator has array operands of different types, one will be
automatically converted so that they have a common type, if possible.
An `integer' may be converted to `real' or `complex', and a `real' may
be converted to `complex'.  No conversion to or from `character' type
is possible.

   Unlike some other languages, the result of an operation in Algae may
have a type that is different than its operands.  For example, the
result of `1/2' has `real' type, even though its operands have type
`integer'.  Another example is `(-1)^0.5', which returns a complex
number.

   With the exception of `*', if a binary operator has both a `vector'
and a `matrix' as its operands the `vector' is converted to a `matrix'
before the operation is performed.  Upon conversion, a vector becomes a
matrix with one row.  For example, in the statement

     ( 1, 2 ) + [ 3, 4 ]

   the left-hand operand of `+' is the vector `(1,2)'.  This is
converted to a `matrix' before being added to `[3,4]'.

   The following table summarizes the precedence and associativity of
Algae's operators.  Those shown on the same line have equal precedence,
and the rows are in order of decreasing precedence.

*operators*
     *associativity*

`()'  `[]'  `.'
     left to right

`''
     right to left

`^'
     right to left

`!'  `+'  `-'
     (unary) left to right

`*'  `/'  `%'  `@'
     left to right

`+'  `-'
     (binary) left to right

`<'  `>'  `<='  `>='  `=='  `!='
     left to right

`&'
     left to right

`|'
     left to right

`&&'
     left to right

`||'
     left to right

`:'
     left to right

`,'
     left to right

`='  `+='  `-='  `*='  `/='  `@='  `%='
     right to left

* Menu:

* Call::		`()'
* Element::		`[]'
* Member::		`.'
* Transpose::		`''
* Power::		`^'
* Not::			`!'
* Negation::		`+' and `-' (unary)
* Multiplication::	`*', `/', `%', and `@'
* Addition::		`+' and `-' (binary)
* Relation::		`<', `>', `<=', `>=', `==', and `!='
* And::			`&'
* Or::			`|'
* Short And::		`&&'
* Short Or::		`||'
* Generate::		`:'
* Append::		`,'
* Assign::		`=', `+=', `-=', `*=', `/=', `@=', and `%='


File: algae.info,  Node: Call,  Next: Element,  Prev: Operators,  Up: Operators

Function Calls
--------------

   Functions are called in the usual way:  the function reference is
followed by a list of arguments.  For example,

     w = union (u; v);

calls the function `union', passing it the values of `u' and `v' for
arguments.  The value returned by the function's `return' statement (or
NULL if it doesn't have one) is the value of the function call.

   The arguments may be any expressions, and are separated by
semicolons.  The called function gets only the values of the
expressions you give it as arguments, so it can't modify the variables
that you give it.

   From its definition, the function knows how many arguments to expect.
Passing too many arguments is an error.  If you pass fewer arguments
than the function definition calls for, NULL's are passed in place of
the missing ones.

   Besides their use in function calls, parentheses are used for several
other purposes, including grouping expressions, `if', `for', and
`while' conditions, function definitions, etc.

