\input texinfo.tex    @c -*-texinfo-*-
@comment %**start of header (This is for running Texinfo on a region.)
@setfilename yorick.nfo
@settitle Yorick
@setchapternewpage odd
@comment %**end of header (This is for running Texinfo on a region.)

@comment -----------------------------------------------------------------

@ifinfo
This file documents Yorick, an interpreted language specialized for
numerical analysis.  Yorick can prepare input to or process output from
another physics simulation code.  New simulation codes can also be
constructed as a part of the Yorick interpreted environment.

Copyright @copyright{} 1994.  The Regents of the University of California.
			 All rights reserved.

Permission to use, copy, modify, and distribute this software for any
purpose without fee is hereby granted, provided that this entire
notice is included in all copies of any software which is or includes
a copy or modification of this software and in all copies of the
supporting documentation for such software.

This work was produced at the University of California, Lawrence
Livermore National Laboratory under contract no. W-7405-ENG-48 between
the U.S. Department of Energy and The Regents of the University of
California for the operation of UC LLNL.


			      DISCLAIMER

This software was prepared as an account of work sponsored by an
agency of the United States Government.  Neither the United States
Government nor the University of California nor any of their
employees, makes any warranty, express or implied, or assumes any
liability or responsibility for the accuracy, completeness, or
usefulness of any information, apparatus, product, or process
disclosed, or represents that its use would not infringe
privately-owned rights.  Reference herein to any specific commercial
products, process, or service by trade name, trademark, manufacturer,
or otherwise, does not necessarily constitute or imply its
endorsement, recommendation, or favoring by the United States
Government or the University of California.  The views and opinions of
authors expressed herein do not necessarily state or reflect those of
the United States Government or the University of California, and
shall not be used for advertising or product endorsement purposes.
@end ifinfo

@comment -----------------------------------------------------------------

@titlepage
@sp 10
@center @titlefont{Yorick: An Interpreted Language}
@sp 2
@center David H. Munro

@comment  The following two commands start the copyright page.
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1994.  The Regents of the University of California.
			 All rights reserved.

Permission to use, copy, modify, and distribute this software for any
purpose without fee is hereby granted, provided that this entire
notice is included in all copies of any software which is or includes
a copy or modification of this software and in all copies of the
supporting documentation for such software.

This work was produced at the University of California, Lawrence
Livermore National Laboratory under contract no. W-7405-ENG-48 between
the U.S. Department of Energy and The Regents of the University of
California for the operation of UC LLNL.


			      DISCLAIMER

This software was prepared as an account of work sponsored by an
agency of the United States Government.  Neither the United States
Government nor the University of California nor any of their
employees, makes any warranty, express or implied, or assumes any
liability or responsibility for the accuracy, completeness, or
usefulness of any information, apparatus, product, or process
disclosed, or represents that its use would not infringe
privately-owned rights.  Reference herein to any specific commercial
products, process, or service by trade name, trademark, manufacturer,
or otherwise, does not necessarily constitute or imply its
endorsement, recommendation, or favoring by the United States
Government or the University of California.  The views and opinions of
authors expressed herein do not necessarily state or reflect those of
the United States Government or the University of California, and
shall not be used for advertising or product endorsement purposes.
@end titlepage


@comment -----------------------------------------------------------------

@node Top, Basics, (dir), (dir)

@menu
* Basics::                      A tutorial-like introductory chapter.
* Arrays::                      Using array syntax.
* Embedding::                   Embedding compiled code in a custom Yorick.
* Concept Index::               

 --- The Detailed Node Listing ---

Basic Ideas

* Simple Statements::           
* Flow control::                Defining functions, conditionals, and loops.
* Environment::                 How to use Yorick's interpreted environment.

Simple Statements

* Define variable::             
* Call procedure::              
* Print expression::            

Flow Control Statements

* Define function::             
* Define procedure::            
* Conditionals::                Conditionally executing statements.
* Loops::                       Repeatedly executing statements. 
* Scoping::                     Local and external variables.

Conditional Execution

* if-else constructs::          
* logical operators::           

Loops

* while and do::                
* for::                         
* goto::                        How to break, continue, and goto from a loop body.

Variable scope

* extern::                      
* local::                       

The Interpreted Environment

* Starting::                    Starting, stopping, and interrupting Yorick.
* Include::                     How to read Yorick statements from a file.
* Help::                        Using the help command.
* Info::                        Getting information about a variable.
* Prompts::                     What Yorick prompts mean.
* Shell commands::              Issuing shell commands from within Yorick.
* Errors::                      What to do when Yorick detects an error.

Include files

* Sample include::              
* Comments::                    
* DOCUMENT::                    The help command recognizes special comments.
* Include path::                Directories Yorick searches for include files.
* Customizing::                 How to execute Yorick statements at startup.

Error Messages

* Runtime errors::              
* Simple debugging::            

Using Array Syntax

* Creating Arrays::             How to originate arrays.
* Interpolating::               Interpolation functions.
* Indexing::                    How to reference array elements.
* Sorting::                     How to sort an array.
* Transposing::                 How to change the order of array dimensions.
* Broadcasting::                Making arrays conformable.
* Dimension Lists::             

Indexing

* Scalar Index::                Scalar indices and array order.
* Index Range::                 Selecting a range of indices.
* Nil Index::                   Nil index refers to an entire dimension.
* Index List::                  Selecting an arbitrary list of indices.
* Pseudo-Index::                Creating a pseudo-index.
* Negative Index::              Numbering a dimension from its last element.
* Rubber-Index::                Using a rubber index.
* Matrix Multiply::             Marking an index for matrix multiplication.
* Statistical::                 Rank reducing (statistical) range functions.
* Finite Difference::           Rank preserving (finite difference) range functions.
@end menu

@comment -----------------------------------------------------------------

@node Basics, Arrays, Top, Top
@chapter Basic Ideas

Yorick is an interpreted programming language.  With Yorick you can
read input (usually lists of numbers) from virtually any text or
binary file, process it, and write the results back to another file.
You can also plot results on your screen.

Yorick expression and flow control syntax is similar to the C
programming language, but the Yorick language lacks declaration
statements.  Also, Yorick array index syntax more closely resembles
Fortran than C.


@menu
* Simple Statements::           
* Flow control::                Defining functions, conditionals, and loops.
* Environment::                 How to use Yorick's interpreted environment.
@end menu

@node Simple Statements, Flow control, Basics, Basics
@section Simple Statements

An interpreter immediately executes each line you type.  Most Yorick
input lines define a variable, invoke a procedure, or print the value
of an expression.

@menu
* Define variable::             
* Call procedure::              
* Print expression::            
@end menu

@node Define variable, Call procedure, Simple Statements, Simple Statements
@subsection Defining a variable

The following five Yorick statements define the five variables @kbd{c},
@kbd{m}, @kbd{E}, @kbd{theta}, and @kbd{file}:

@example
c= 3.00e10;  m= 9.11e-28
E= m*c^2
theta= span(0, 6*pi, 200)
file= create("damped.txt")
@end example

Variable names are case sensitive, so @kbd{E} is not the same variable
as @kbd{e}.  A variable name must begin with a letter of the alphabet
(either upper or lower case) or with an underscore (@kbd{_});
subsequent characters may additionally include digits.

A semicolon terminates a Yorick statement, so the first line contains
two statements.  To make Yorick statements easier to type, you don't
need to put a semicolon at the end of most lines.  However, if you are
composing a Yorick program in a text file (as opposed to typing
directly to Yorick itself, a semicolon at the end of every line
reduces the chances of a misinterpretation, and makes your program
easier to read.

Conversely, a new line need not represent the end of a statement.  If
the line is incomplete, the statement automatically continues on the
following line.  Hence, the second and third lines above could have
been typed as:

@example
E=
  m *
  c^2
theta= span(0, 6*pi,
            200)
@end example

In the second line, @kbd{*} and @kbd{^} represent multiplication and
raising to a power.  The other common arithmetic operators are
@kbd{+}, @kbd{-}, @kbd{/} (division), and @kbd{%} (remainder or
modulo).  The rules for forming arithmetic expressions with these
operators and parentheses are the same in Yorick as in Fortran or C
(but note that @kbd{^} does not mean raise to a power in C, and
Fortran uses the symbol @kbd{**} for that operation).@refill

The @kbd{span} function returns 200 equally spaced values beginning
with @kbd{0} and ending with @kbd{6*pi}.  The variable @kbd{pi} is
predefined as 3.14159...@refill

The @kbd{create} function returns an object representing the new file.
The variable @kbd{file} specifies where output functions should write
their data.  Besides numbers like @kbd{c}, @kbd{m}, and @kbd{E}, or
arrays of numbers like @kbd{theta}, or files like @kbd{file}, Yorick
variables may represent several other sorts of objects, taken up in
later chapters.@refill

The @kbd{=} operator is itself a binary operator, which has the side
effect of redefining its left operand.  It associates from right to
left, that is, the rightmost @kbd{=} operation is performed first (all
other binary operators except @kbd{^} associate from left to right).
Hence, several variables may be set to a single value with a single
statement:@refill

@example
psi= phi= theta= span(0, 6*pi, 200)
@end example

When you define a variable, Yorick forgets any previous value and data
type:

@example
phi= create("junk.txt")
@end example


@node Call procedure, Print expression, Define variable, Simple Statements
@subsection Invoking a procedure

A Yorick function which has side effects may sensibly be invoked as a
procedure, discarding the value returned by the function, if any:

@example
plg, sin(theta)*exp(-theta/6), theta
write, file, theta, sin(theta)*exp(-theta/6)
close, file
@end example

The @kbd{plg} function plots a graph on your screen --- in this case,
three cycles of a damped sine wave.  The graph is made by connecting
200 closely spaced points by straight lines.@refill

The @kbd{write} function writes a two column, 200 line table of values
of the same damped sine wave to the file @file{damped.txt}.  Then
@kbd{close} closes the file, making it unavailable for any further
@kbd{write} operations.@refill

A line which ends with a comma will be continued, to allow procedures
with long argument lists.  For example, the @kbd{write} statement could
have been written:@refill

@example
write, file, theta,
             sin(theta)*exp(-theta/6)
@end example

A procedure may be invoked with zero arguments; several graphics
functions are often used in this way:

@example
hcp
fma
@end example

The @kbd{hcp} function writes the current graphics window contents to
a ``hardcopy file'' for later retrieval or printing.  The @kbd{fma}
function stands for ``frame advance'' --- subsequent plotting commands
will draw on a fresh page.  Normally, plotting commands such as
@kbd{plg} draw on top of whatever has been drawn since the previous
@kbd{fma}.@refill


@node Print expression,  , Call procedure, Simple Statements
@subsection Printing an expression

An unadorned expression is also a legal Yorick statement; Yorick prints
its value.  In the preceding examples, only the characters you would
type have been shown; to exhibit the @kbd{print} function and its
output, I need to show you what your screen would look like --- not only
what you type, but what Yorick prints.  To begin with, Yorick prompts
you for input with a @kbd{>} followed by a space (@pxref{Prompts}).  In
the examples in this section, therefore, the lines which begin with
@kbd{>} are what you typed; the other line(s) are Yorick's
responses.@refill

@example
> E
8.199e-07
> print, E
8.199e-07
> m;c;m*c^2
9.11e-28
3.e+10
8.199e-07
> span(0,2,5)
[0,0.5,1,1.5,2]
> max(sin(theta)*exp(-theta/6))
0.780288
@end example

In the @kbd{span} example, notice that an array is printed as a comma
delimited list enclosed in square brackets.  This is also a legal
syntax for an array in a Yorick statement.  For numeric data, the
@kbd{print} function always displays its output in a format which
would be legal in a Yorick statement; you must use the @kbd{write}
function if you want ``prettier'' output.  Beware of typing an
expression or variable name which is a large array; it is easy to
generate lots of output (you can interrupt Yorick by typing control-c
if you do this accidentally, @pxref{Starting}).@refill

Most non-numeric objects print some useful descriptive information;
for example, before it was closed, the @kbd{file} variable above would
have printed:

@example
> file
write-only text stream at:
  LINE: 201  FILE: /home/icf/munro/damped.txt
@end example

As you may have noticed, printing a variable and invoking a procedure
with no arguments are syntactically indistinguishable.  Yorick decides
which operation is appropriate at run time.  Thus, if @kbd{file} had
been a function, the previous input line would have invoked the
@kbd{file} function; as it was not a function, Yorick printed the
@kbd{file} variable.  Only an explicit use of the @kbd{print} function
will print a function:

@example
> print, fma
builtin fma()
@end example


@node Flow control, Environment, Simple Statements, Basics
@section Flow Control Statements

Almost everything you type at Yorick during an interactive session
will be one of the simple Yorick statements described in the previous
section -- defining variables, invoking procedures, and printing
expressions.  However, in order to actually use Yorick you need to
write your own functions and procedures.  You can do this by typing
Yorick statements at the keyboard, but you should usually put function
definitions in a text file.  Suggestions for how to organize such
``include'' files will be the topic of the next section.  This section
introduces the Yorick statements which define functions, conditionals,
and loops.


@menu
* Define function::             
* Define procedure::            
* Conditionals::                Conditionally executing statements.
* Loops::                       Repeatedly executing statements. 
* Scoping::                     Local and external variables.
@end menu

@node Define function, Define procedure, Flow control, Flow control
@subsection Defining a function

Consider a damped sine wave.  It describes the time evolution of an
oscillator, such as a weight on a spring, which bobs up and down for a
while after you whack it.  The basic shape of the wave is determined
by the Q of the oscillator; a high Q means there is little friction,
and the weight will continue bobbing for many cycles, while a low Q
means a lot of friction and few cycles.  The amplitude of the
oscillation is therefore a function of two parameters -- the phase
(time in units of the natural period of the oscillator), and the Q:

@example
func damped_wave(phase, Q)
@{
  nu= 0.5/Q;
  omega= sqrt(1.-nu*nu);
  return sin(omega*phase)*exp(-nu*phase);
@}
@end example

Within a function body, I terminate every Yorick statement with a
semicolon (@pxref{Define variable}).

The variables @kbd{phase} and @kbd{Q} are called the parameters of the
function.  They and the variables @kbd{nu} and @kbd{omega} defined in
the first two lines of the function body are @emph{local} to the
function.  That is, calling @kbd{damped_wave} will not change the
values of any variables named @kbd{phase}, @kbd{Q}, @kbd{nu}, or
@kbd{omega} in the calling environment.@refill

In fact, the only effect of calling @kbd{damped_wave} is to return its
result, which is accomplished by the @kbd{return} statement in the
third line of the body.  That is, calling @kbd{damped_wave} has no side
effects.  You can use @kbd{damped_wave} in expressions like this:

@example
> damped_wave(1.5, 3)
0.775523
> damped_wave([.5,1,1.5,2,2.5], 3)
[0.435436,0.705823,0.775523,0.659625,0.41276]
> q5= damped_wave(theta,5)
> fma; plg, damped_wave(theta,3), theta
> plg, damped_wave(theta,1), theta
@end example

The last two lines graphically compare Q=3 oscillations to Q=1
oscillations.

Notice that the arguments to @kbd{damped_wave} may be arrays.  In this
case the result will be the array of results for each element of
input; hence @kbd{q5} will be an array of 200 numbers.  Nor is Yorick
confused by the fact that the @kbd{phase} argument (@kbd{theta}) is an
array, while the @kbd{Q} argument (@kbd{5}) is a scalar.  The precise
rules for ``conformability'' between two arrays will be described
later (@pxref{Broadcasting}); usually you get what you expected.@refill

In this case, as Yorick evaluates @kbd{damped_wave}, @kbd{nu} and
@kbd{omega} will both be scalars, since @kbd{Q} is a scalar.  On the
other hand, @kbd{omega*phase} and @kbd{nu*phase} become arrays, since
@kbd{phase} is an array.  Whenever an operand is an array, an
arithmetic operation produces an array as its result.@refill


@node Define procedure, Conditionals, Define function, Flow control
@subsection Defining Procedures

Any Yorick function may be invoked as a procedure; the return value is
simply discarded.  Calling @kbd{damped_wave} as a procedure would be
pointless, since it has no side effects.  The converse case is a
function to be called @emph{only} for its side effects.  Such a
function need not have an explicit @kbd{return} statement:@refill

@example
func q_out(Q, file_name)
@{
  file= create(file_name);
  write, file, "Q= "+pr1(Q);
  write, file, "   theta       amplitude";
  write, file, theta, damped_wave(theta,Q);
@}
@end example

The @kbd{pr1} function (for ``print one value'') returns a string
representation of its numeric argument, and the @kbd{+} operator
between two strings concatenates them.

You would invoke @kbd{q_out} with the line:

@example
q_out, 3, "q.out"
@end example

Besides lacking an explicit @kbd{return} statement, the @kbd{q_out}
function has two other peculiarities worth mentioning:

First, the variable @kbd{theta} is never defined.  But neither are the
functions @kbd{create} and @kbd{write}.  Any symbol not defined within
a function is @emph{external} to the function.  As already noted,
parameters and variables defined within the function are @emph{local}
to the function.  Here, @kbd{theta} is the 200 element array of phase
angles defined before q_out was called.  You can change theta (both
its dimensions and its values) before the next call to @kbd{q_out};
that is, an external reference may change between calls to a function
that uses it.@refill

Second, @kbd{file} is never explicitly closed.  When a function
returns, its local variables (such as @kbd{file}) disappear; when a
file object disappears, the associated file automatically closes.@refill


@node Conditionals, Loops, Define procedure, Flow control
@subsection Conditional Execution

The design of the @kbd{q_out} function can be improved.  As written,
each output file will contain only a single wave.  You might want the
option of writing several waves into a single file.  Consider this
alternative:

@example
func q_out(Q, file)
@{
  if (!is_stream(file)) file= create(file);
  write, file, "Q= "+pr1(Q);
  write, file, "   theta       amplitude";
  write, file, theta, damped_wave(theta,Q);
  return file;
@}
@end example

The @kbd{if} statement executes its body (the redefinition of
@kbd{file}) if and only if its condition (@kbd{!is_stream(file)}) is
true.  Any scalar number may serve as a condition -- a non-zero
value is ``true'', and the value zero is ``false''.@refill

The @kbd{is_stream} function returns 1 (true) when its argument is a
file object (a ``data stream''), and 0 (false) otherwise.  In
particular, if @kbd{file} is a text string (like @kbd{"q.out"}),
@kbd{is_stream} returns 0.  The unary operator @kbd{!} is logical
negation, that is, ``not''.@refill

Hence, if the @kbd{file} argument is not already a file object, the
new @kbd{q_out} presumes it is the name of a file, which it creates,
redefining @kbd{file} as the associated file object.  Thus, after the
first line of the function body, @kbd{file} will be a file object,
even if a file name was passed into the function.  Furthermore, since
the parameter @kbd{file} is local to @kbd{q_out}, none of this hocus
pocus will have any effect outside @kbd{q_out}.@refill

The second trick in the new @kbd{q_out} is the reappearance of a
@kbd{return} statement.  The original calling sequence:@refill
@example
q_out, 3, "q.out"
@end example
@noindent
has the same result as before -- the @kbd{if} condition is true, so
the file is created, then the wave data is written.  This time the
file object is returned, only to be discarded because @kbd{q_out}
was invoked as a procedure.  When the file object disappears, the
file closes.  But if @kbd{q_out} were invoked as a function, the file
object can be saved, which keeps the file open:@refill

@example
f= q_out(3,"q.out")
q_out,2,f
q_out,1,f
close,f
@end example

Now the file @file{q.out} contains the Q=3 wave, followed by the Q=2
and Q=1 waves.  In the second and third calls to @kbd{q_out}, the
@kbd{file} parameter is already a file object, so the @kbd{if}
condition is false, and @kbd{create} is not called.  Notice that the
file does not close when the return value from the second (or third)
call is discarded; the variable @kbd{f} refers to the same file object
as the discarded return value.  Without an explicit call to
@kbd{close}, a file only closes when the @emph{final} reference to it
disappears.@refill


@menu
* if-else constructs::          
* logical operators::           
@end menu

@node if-else constructs, logical operators, Conditionals, Conditionals
@subsubsection General @kbd{if} and @kbd{else} constructs

The most general form of the @kbd{if} statement is:

@example
if (condition) statement_if_true;
else statement_if_false;
@end example

When you need to choose among several alternatives, make the @kbd{else}
clause itself an @kbd{if} statement:@refill

@example
if (condition_1) statement_if_1;
else if (condition_2) statement_if_2;
else if (condition_3) statement_if_3;
...
else statement_if_none;
@end example

The final @kbd{else} is always optional -- if it is not present,
nothing at all happens if none of the conditions is satisfied.@refill

Often you need to execute more than one statement conditionally.
Quite generally in Yorick, you may group several statements into a
single compound statement by means of curly braces:

@example
@{ statement_1; statement_2; statement_3; statement_4; @}
@end example

Ordinarily, both curly braces and each of the statements should be
written on a separate line, with the statements indented to make their
membership in the compound more obvious.  Further, in an if-else
construction, when one branch requires more than one statement, you
should write every branch as a compound statement with curly braces.
Therefore, for a four branch @kbd{if} in which the second @kbd{if}
requires two statements, and the @kbd{else} three, write this:@refill

@example
if (condition_1) @{
  statement_if_1;
@} else if (condition_2) @{
  statement_if_2_A;
  statement_if_2_B;
@} else if (condition_3) @{
  statement_if_3;
@} else @{
  statement_if_none_A;
  statement_if_none_B;
  statement_if_none_C;
@}
@end example

The @kbd{else} statement has a very unusual syntax: It is the only
statement in Yorick which depends on the form of the @emph{previous}
statement; an @kbd{else} must follow an @kbd{if}.  Because Yorick
statements outside functions (and compound statements) are executed
immediately, you must be very careful using @kbd{else} in such a
situation.  If the @kbd{if} has already been executed (as it would be
in the examples without curly braces), the following @kbd{else} leads
to a syntax error!@refill

The best way to avoid this puzzling problem is to always use the curly
brace syntax of the latest example when you use @kbd{else} outside a
function.  (You don't often need it in such a context anyway.)


@node logical operators,  , if-else constructs, Conditionals
@subsubsection Combining conditions with @kbd{&&} and @kbd{||}

The logical operators @kbd{&&} (``and'') and @kbd{||} (``or'') combine
conditional expressions; the @kbd{!} (``not'') operator negates them.
The @kbd{!} has the highest precedence, then @kbd{&&}, then @kbd{||};
you will need parentheses to force a different order.@refill

(Beware of the bitwise ``and'' and ``or'' operators @kbd{&} and
@kbd{|} -- these should @emph{never} be used to combine conditions;
they are for set-and-mask bit fiddling.)@refill

The operators for comparing numeric values are @kbd{==} (equal),
@kbd{!=} (not equal), @kbd{>} (greater), @kbd{<} (less), @kbd{>=}
(greater or equal), and @kbd{<=} (less or equal).  These all have
higher precedence than @kbd{&&}, but lower than @kbd{!} or any
arithmetic operators.@refill

@example
if ((a<b && x>a && x<b) || (a>b && x<a && x>b))
  write, "x is between a and b"
@end example

Here, the expression for the right operand to @kbd{&&} will execute
only if its left operand is actually true.  Similarly, the right
operand to @kbd{||} executes only if its left proves false.
Therefore, it is important to order the operands of @kbd{&&} and
@kbd{||} to put the most computationally expensive expression on the
right --- even though the logical ``and'' and ``or'' functions are
commutative, the order of the operands to @kbd{&&} and @kbd{||} can be
critical.@refill

In the example, if @kbd{a>b}, the @kbd{x>a} and @kbd{x<b}
subexpressions will not actually execute since @kbd{a<b} proved false.
Since the left operand to @kbd{||} was false, its right operand will
be evaluated.@refill

Despite the cleverness of the @kbd{&&} and @kbd{||} operators in not
executing the expression for their right operands unless absolutely
necessary, the example has obvious inefficiencies: First, if
@kbd{a>=b}, then both @kbd{a<b} and @kbd{a>b} are checked.  Second, if
@kbd{a<b}, but @kbd{x} is not between @kbd{a} and @kbd{b}, the right
operand to @kbd{||} is evaluated anyway.  Yorick has a ternary operator
to avoid this type of inefficiency:@refill

@example
expr_A_or_B= (condition? expr_A_if_true : expr_B_if_false);
@end example

The @kbd{?:} operator evaluates the middle expression if the condition
is true, the right expression otherwise.  Is that so? Yes : No.  The
efficient betweeness test reads:

@example
if (a<b? (x>a && x<b) : (x<a && x>b))
  write, "x is between a and b";
@end example


@node Loops, Scoping, Conditionals, Flow control
@subsection Loops

Most loops in Yorick programs are implicit; remember that operations
between array arguments produce array results.  Whenever you write a
Yorick program, you should be suspicious of @emph{all} explicit loops.
Always ask yourself whether a clever use of array syntax could have
avoided the loop.

To illustrate an appropriate Yorick loop, let's revise @kbd{q_out} to
write several values of Q in a single call.  Incidentally, this sort
of incremental revision of a function is very common in Yorick program
development.  As you use a function, you notice that the surrounding
code is often the same, suggesting a savings if it were incorporated
into the function.  Again, a careful job leaves all of the previous
behavior of @kbd{q_out} intact:@refill

@example
func q_out(Q, file)
@{
  if (!is_stream(file)) file= create(file);
  n= numberof(Q);
  for (i=1 ; i<=n ; ++i) @{
    write, file, "Q= "+pr1(Q(i));
    write, file, "   theta       amplitude";
    write, file, theta, damped_wave(theta,Q(i));
  @}
  return file;
@}
@end example

Two new features here are the @kbd{numberof} function, which returns
the length of the array @kbd{Q}, and the array indexing syntax
@kbd{Q(i)}, which extracts the @kbd{i}-th element of the array
@kbd{Q}.  If @kbd{Q} is scalar (as it had to be before this latest
revision), @kbd{numberof} returns 1, and @kbd{Q(1)} is the same as
@kbd{Q}, so scalar @kbd{Q} works as before.@refill

But the most important new feature is the @kbd{for} loop.  It says to
initialize @kbd{i} to 1, then, as long as @kbd{i} remains less than or
equal to @kbd{n}, to execute the loop body, which is a compound of
three write statements.  Finally, after each pass, the increment
expression @kbd{++i} is executed before the @kbd{i<=n} condition is
evaluated.  @kbd{++i} is equivalent to @kbd{i=i+1}; @kbd{--i} means
@kbd{i=i-1}.@refill

A loop body may also be a single statement, in which case the curly
braces are unecessary.  For example, the following lines will write
the Q=3, Q=2, and Q=1 curves to the file @file{q.out}, then plot
them:@refill

@example
q_list= [3,2,1]
q_out, q_list, "q.out"
fma; for(i=1;i<=3;++i) plg, damped_wave(theta,q_list(i)), theta
@end example

A @kbd{for} loop with a @kbd{plg} body is the easiest way to overlay a
series of curves.  After the three simple statement types, @kbd{for}
statements see the most frequent direct use from the keyboard.


@menu
* while and do::                
* for::                         
* goto::                        How to break, continue, and goto from a loop body.
@end menu

@node while and do, for, Loops, Loops
@subsubsection The @kbd{while} and @kbd{do while} statements

The @kbd{while} loop is simpler than the @kbd{for} loop:

@example
while (condition) body_statement
@end example

The @kbd{body_statement} --- very oten a compound statement enclosed
in curly braces --- executes over and over until the @kbd{condition}
becomes false.  If the @kbd{condition} is false to begin with,
@kbd{body_statement} never executes.@refill

Occasionally, you want the @kbd{body_statement} to execute and set the
@kbd{condition} @emph{before} it is tested for the first time.  In
this case, use the @kbd{do while} statement:@refill

@example
do @{
  body_statement_A;
  body_statement_B;
  ...etc...
@} while (condition);
@end example


@node for, goto, while and do, Loops
@subsubsection The @kbd{for} statement

The @kbd{for} statement is a ``packaged'' form of a @kbd{while} loop.
The meaning of this generic @kbd{for} statement is the same as the
following @kbd{while}:@refill

@example
for (start_statements ; condition ; step_statements) body_statements

start_statments
while (condition) @{
  body_statements
  step_statements
@}
@end example

There only two reasons to prefer @kbd{for} over @kbd{while}: Most
importantly, @kbd{for} can show ``up front'' how a loop index is
initialized and incremented, rather than relegating the increment
operation (@kbd{step_statements}) to the end of the loop.  Secondly,
the @kbd{continue} statement (@pxref{goto}) branches just past the body of
the loop, which would include the @kbd{step_statements} in a
@kbd{while} loop, but not in a @kbd{for} loop.@refill

In order to make Yorick loop syntax agree with C, Yorick's @kbd{for}
statement has a syntactic irregularity: If the @kbd{start_statements}
and @kbd{step_statements} consist of more than one statement, then
commas (not semicolons) separate the statements.  (The C comma
operator is not available in any other context in Yorick.)  The two
semicolons separate the start, condition, and step clauses and must
always be present, but any or all of the three clauses themselves may
be blank.  For example, in order to increment two variables @kbd{i}
and @kbd{j}, a loop might look like this:@refill

@example
for (i=1000, j=1 ; i>j ; i+=1000, j*=2);
@end example

This example also illustrates that the @kbd{body_statements} may be
omitted; the point of this loop is merely to compute the first @kbd{i}
and @kbd{j} for which the condition is not satisfied.  The trailing
semicolon is necessary in this case, since otherwise the line would
be continued (on the assumption that the loop body was to follow).
@refill

The @kbd{+=} and @kbd{*=} are special forms of the @kbd{=} operator;
@kbd{i=i+1000} and @kbd{j=j*2} mean the same thing.  Any binary
operator may be used in this short-hand form in order to increment a
variable.  Like @kbd{++i} and @kbd{--i}, these are particularly useful
in loop increment expressions.@refill


@node goto,  , for, Loops
@subsubsection Using @kbd{break}, @kbd{continue}, and @kbd{goto}

The @kbd{break} statement jumps out of the loop containing it.  The
@kbd{continue} statement jumps to the end of the loop body,
``continuing'' with the next pass through the loop (if any).  In
deeply nested loops --- which are extremely rare in Yorick programs
--- you can jump to more general places using the @kbd{goto}
statement.  For example, here is how to break out or continue from one
or both levels of a doubly nested loop:@refill

@example
 for (i=1 ; i<=n ; ++i) @{
   for (j=1 ; j<=m ; ++j) @{
     if (skip_to_next_j_now) continue;
     if (skip_to_next_i_now) goto skip_i;
     if (break_out_of_inner_loop_now) break;
     if (break_out_of_both_loops_now) goto done;
     more_statements_A;
   @}
   more_statements_B;
  skip_i:
 @}
done:
 more_statements_C;
@end example

@noindent
The @kbd{continue} jumps just after @kbd{more_statements_A}, the
@kbd{break} just before @kbd{more_statements_B}.@refill

Break and continue statements may be used to escape from @kbd{while}
or @kbd{do while} loops as well.@refill

If @kbd{while} tests the condition before the loop body, and @kbd{do
while} checks after the loop body, you may have wondered what to do
when you need to check the condition in the middle of the loop body.
The answer is the ``do forever'' construction, plus the @kbd{break}
statement (note the inversion of the sense of the condition):@refill

@example
for (;;) @{
  body_before_test;
  if (!condition) break;
  body_after_test;
@}
@end example


@node Scoping,  , Loops, Flow control
@subsection Variable scope

By default, dummy parameters and variables which are defined in a
function body before any other use are @emph{local} variables.
Variables (or functions) used before their definition are
@emph{external} variables (@pxref{Define procedure}, @pxref{Define
function}).  A variable (or function) defined outside of all functions
is just that --- external to all functions and local to none.

Whenever a function is called, Yorick remembers the external values of
all its local variables, then replaces them by their local values.
Thus, all of its local variables are potentially ``visible'' as external
variables to any function it calls.  When it returns, the function
replaces all its local variables by the values it remembered.  Neither
that function, nor any function it calls can affect these remembered
values; Yorick provides no means of ``unmasking'' a local variable.

The default rule for determining whether a variable should have local or
external scope fails in two cases: First, you may want to redefine an
external variable without looking at its value.  Second, a few
procedures set the values of their parameters when they return; it may
appear to Yorick's parser that such a variable has been used without
being defined, even though you intend it to be local to the function.
The @kbd{extern} and @kbd{local} statements solve these two problems,
respectively.

@menu
* extern::                      
* local::                       
@end menu

@node extern, local, Scoping, Scoping
@subsubsection @kbd{extern} statements

Suppose you want to write a function which sets the value of the
@kbd{theta} array used by all the variants of the @kbd{q_out}
function:@refill

@example
func q_out_domain(start, stop, n)
@{
  extern theta;
  theta= span(start, stop, n);
@}
@end example

Without the @kbd{extern} statement, @kbd{theta} will be a local
variable, whose external value is restored when @kbd{q_out_domain}
returns (thus, the function would be a no-op).  With the @kbd{extern}
statement, @kbd{q_out_domain} has the intended side effect of setting
the value of @kbd{theta}.  The new @kbd{theta} would be used by
subsequent calls to @kbd{q_out}.@refill

Any number of variables may appear in a single @kbd{extern} statement:

@example
extern var1, var2, var3, var4;
@end example


@node local,  , extern, Scoping
@subsubsection @kbd{local} statements

The @kbd{save} and @kbd{restore} functions store and retrieve Yorick
variables in self-descriptive binary files (called PDB files).  To
create a binary file @file{demo.pdb}, save the variables @kbd{theta},
@kbd{E}, @kbd{m}, and @kbd{c} in it, then close the file:@refill

@example
f= createb("demo.pdb")
save, f, theta, E, m, c
close, f
@end example

To open this file and read back the @kbd{theta} variable:

@example
restore, openb("demo.pdb"), theta, c
@end example

For symmetry with @kbd{save}, the @kbd{restore} function has the unusual
property that it redefines its parameters (except the first).  Thus,
@kbd{theta} is redefined by this @kbd{restore} statement, just as it
would have been by a @kbd{theta=} statement.  The Yorick parser does not
understand this, which means that you must be careful when you place
such a function call inside a function:@refill

@example
func q_out_file(infile, Q, outfile)
@{
  if (!is_stream(infile)) infile= openb(infile);
  local theta;
  restore, infile, theta;
  return q_out(Q, outfile);
@}
@end example

This variant of @kbd{q_out} uses the @kbd{theta} variable read from
@kbd{infile}, instead of an external value of @kbd{theta}.  Without the
@kbd{local} declaration, @kbd{restore} would clobber the external value
of @kbd{theta}.  This way, when @kbd{q_out_file} calls @kbd{q_out}, it
has remembered the external value of @kbd{theta}, but @kbd{q_out}
``sees'' the value of @kbd{theta} restored from @kbd{infile}.  When
@kbd{q_out_file} finally returns, it replaces the original value of
@kbd{theta} intact.@refill

Any number of variables may appear in a single @kbd{local} statement:

@example
local var1, var2, var3, var4;
@end example


@node Environment,  , Flow control, Basics
@section The Interpreted Environment

The Yorick program accepts only complete input lines typed at your
keyboard.  Typing a command to Yorick presumes a ``command line
interface'' or a ``terminal emulator'' which is not a part of Yorick.
I designed Yorick on the assumption that you have a good terminal
emulator program.  In particular, Yorick is much easier to use if you
can recall and edit previous input lines; as in music, repitition with
variations is at the heart of programming.  My personal recommendation
is shell-mode in GNU Emacs.

Therefore, Yorick inherits most of its ``look and feel'' from your
terminal emulator.  Yorick's distinctive prompts and error messages
are described later in this section.

Any significant Yorick program will be stored in a text file, called
an @dfn{include} file, after the command which reads it.  Use your
favorite text editor to create and modify your include files.  Again,
GNU Emacs is my favorite --- use its c-mode to edit Yorick include
files as well as C programs.  Just as C source file names should end
in @file{.c} or @file{.h}, and Fortran source file names should end in
@file{.f}, so Yorick include file names should end in @file{.i}.

This section begins with additional stylistic suggestions concerning
include files.  In particular, Yorick's @kbd{help} command can find
documentation comments in your include files if you format them
properly.  All of the built-in Yorick functions, such as @kbd{sin},
@kbd{write}, or @kbd{plg}, come equipped with such comments.@refill


@menu
* Starting::                    Starting, stopping, and interrupting Yorick.
* Include::                     How to read Yorick statements from a file.
* Help::                        Using the help command.
* Info::                        Getting information about a variable.
* Prompts::                     What Yorick prompts mean.
* Shell commands::              Issuing shell commands from within Yorick.
* Errors::                      What to do when Yorick detects an error.
@end menu

@node Starting, Include, Environment, Environment
@subsection Starting, stopping, and interrupting Yorick

Start Yorick by typing its name to your terminal emulator.  When you
are done, use the @kbd{quit} function to exit gracefully:

@example
% yorick
 Yorick ready.  For help type 'help'.
> quit
%
@end example

You can interrupt Yorick at any time by typing Control-C; this causes
an immediate runtime error (@pxref{Errors}).  (Your terminal emulator
and operating system must be able to send Yorick a SIGINT signal in
order for this to work.  On UNIX systems, you can set this character
using the @kbd{intr} option of the @kbd{stty} command; Control-C is the
usual setting.)@refill


@node Include, Help, Starting, Environment
@subsection Include files

When you run Yorick in a window or Emacs environment, keep a window
containing the include file you are writing, in addition to the window
where Yorick is running.  When you want to test the latest changes to
your include file --- let's call it @file{damped.i} --- save the file,
then move to your Yorick window and type:

@example
#include "damped.i"
@end example

The special character @kbd{#} reminds you that the include directive
is not a Yorick statement, like all other inputs to Yorick.  Instead,
@kbd{#include} directs Yorick to switch its input stream from the
keyboard to the quoted file.  Yorick then treats each line of the file
exactly as if it were a line you had typed at the keyboard (including,
of course, additional @kbd{#include} lines).  When there are no more
lines in the file, the input stream switches back to the keyboard.

While you are debugging an include file, you will ordinarily include
it over and over again, until you get it right.  This does no harm,
since any functions or variables defined in the file will be replaced
by their new definitions the next time you include the file, just as
they would if you typed new definitions.

Ideally, your include files should consist of a series of function
definitions and variable initializations.  If you follow this
discipline, you can regard each include file as a library of
functions.  You type @kbd{#include} once in order to load this
library, making the functions defined there available, just like
Yorick's built in functions.  Many such libraries come with Yorick ---
Bessel functions, cubic spline interpolators, and other goodies.

@menu
* Sample include::              
* Comments::                    
* DOCUMENT::                    The help command recognizes special comments.
* Include path::                Directories Yorick searches for include files.
* Customizing::                 How to execute Yorick statements at startup.
@end menu

@node Sample include, Comments, Include, Include
@subsubsection A sample include file

Here is @file{damped.i}, which defines the damped sine wave functions
we've been designing in this chapter:

@example
/* damped.i */

local damped;
/* DOCUMENT damped.i --- compute and output damped sine waves
   SEE ALSO: damped_wave, q_out
 */

func damped_wave(phase, Q)
/* DOCUMENT damped_wave(phase, Q)
     returns a damped sine wave evaluated at PHASE, for quality factor Q.
     (High Q means little damping.)  The PHASE is 2*pi after one period of
     the natural frequency of the oscillator.  PHASE and Q must be
     conformable arrays.

   SEE ALSO: q_out
 */
@{
  nu= 0.5/Q;
  omega= sqrt(1.-nu*nu);
  return sin(omega*phase)*exp(-nu*phase);  /* always zero at phase==0 */
@}

func q_out(Q, file)
/* DOCUMENT q_out, Q, file
         or q_out(Q, file)
     Write the damped sine wave of quality factor Q to the FILE.
     FILE may be either a filename, to create the file, or a file
     object returned by an earlier create or q_out operation.  If
     q_out is invoked as a function, it returns the file object.

     The external variable
          theta
     determines the phase points at which the damped sine wave is
     evaluated; q_out will write two header lines, followed by
     two columns, with one line for each element of the theta
     array.  The first column is theta; the second is
     damped_wave(theta, Q).

     If Q is an array, the two header lines and two columns will
     be repeated for each element of Q.

   SEE ALSO: damped_wave
 */
@{
  if (!is_stream(file)) file= create(file); /* file name --> object */
  n= numberof(Q);
  for (i=1 ; i<=n ; ++i) @{ /* loop on elements of Q */
    write, file, "Q= "+pr1(Q(i));
    write, file, "   theta       amplitude";
    write, file, theta, damped_wave(theta,Q(i));
  @}
  return file;
@}
@end example

You would type

@example
#include "damped.i"
@end example

@noindent
to read the Yorick statements in the file.  The first thing you notice
is that there are comments --- the text enclosed by @kbd{/* */}.  If
you take the trouble to save a program in an include file, you will be
wise to make notes about what it's for and annotations of obscure
statements which might confuse you later.  Writing good comments is
arguably the most difficult skill in programming.  Practice it
diligently.


@node Comments, DOCUMENT, Sample include, Include
@subsubsection Comments

There are two ways to insert comments into a Yorick program.  These
are the C style @kbd{/* ... */} and the C++ style @kbd{//}:

@example
// C++ style comments begin with // (anywhere on a line)
// and end at the end of that line.

E= m*c^2;   /* C style comments begin with slash-star, and
               do not end until start-slash, even if that
               is several lines later.  */
/* C style comments need not annotate a single line.
 * You should pick a comment style which makes your
 * code attractive and easy to read.  */

F= m*a;          // Here is another C++ style comment...
divE= 4*pi*rho;  /* ... and a final C style comment. */
@end example

I strongly recommend C++ style comments when you ``comment
out'' a sequence of Yorick statements.  C style comments do not nest
properly, so you can't comment out a series of lines which contain
comments:

@example
/*
E= m*c^2;   /* ERROR -- this ends the outer comment --> */
F= m*a
*/ <-- then this causes a syntax error
@end example

The C++ style not only works correctly; it also makes it more obvious
that the lines in question are comments:

@example
// E= m*c^2;   /* Any kind of comment could go here.  */
// F= m*a;
@end example

Yorick recognizes one special comment: If the first line of an include
file begins with @kbd{#!}, Yorick ignores that line.  This allows Yorick
include scripts to be executable on UNIX systems supporting the ``pound
bang'' convention:

@example
#!/usr/local/bin/yorick -batch
/* If this file has execute permission, UNIX will use Yorick to
 * execute it.  The Yorick function get_argv can be used to accept
 * command line arguments (see help, get_argv).  You might want
 * to use -i instead of -batch on the first line.  Read the help
 * on process_argv and batch for more information.  */
write, "The square root of pi is", sqrt(pi);
quit;
@end example


@node DOCUMENT, Include path, Comments, Include
@subsubsection @kbd{DOCUMENT} comments

Immediately after (within a few lines of) a @kbd{func}, @kbd{extern}, or
@kbd{local} statement (@pxref{Scoping}), you may put a comment which
begins with the eleven characters @kbd{/* DOCUMENT}.  Although Yorick
itself doesn't pay any more attention to a @kbd{DOCUMENT} comment than
to any other comment, there is a function called @kbd{help} which does.
What Yorick does do when it sees a @kbd{func}, @kbd{extern}, or
@kbd{local} (outside of any function body), is to record the include
file name and line number where that function or variable(s) are
defined.@refill

Later, when you ask for help on some topic, the @kbd{help} function
asks Yorick whether it knows the file and line number where that topic
(a function or variable) was defined.  If so, it opens the file, goes
to the line number, and scans forward a few lines looking for a
@kbd{DOCUMENT} comment.  If it finds one, it prints the entire
comment.@refill

The file @kbd{damped.i} has three @kbd{DOCUMENT} comments: one for a
fictitious variable called @kbd{damped}, so that someone who saw the
file but didn't know the names of the functions inside could find out,
and one each for the @kbd{damped_wave} and @kbd{q_out} functions.
@refill

Near the end of most @kbd{DOCUMENT} comments, you will find a
@kbd{SEE ALSO:} field which feeds the reader the names of related
functions or variables which also have @kbd{DOCUMENT} comments.  If
you use these wisely, you can lead someone (often an older self) to
all of the documentation she needs to be able to use your package.@refill

This low-tech form of online documentation is surprisingly effective:
easy to create, maintain, and use.  As an automated step toward a more
formal document, the @kbd{mkdoc} function (in the Yorick library include
file @file{mkdoc.i}) collects all of the @kbd{DOCUMENT} comments in one
or more include files, alphabetizes them, adds a table of contents, and
writes them into a file suitable for printing.@refill


@node Include path, Customizing, DOCUMENT, Include
@subsubsection Where Yorick looks for include files

You can specify a complete path name (including directories) for the
file in an @kbd{#include} directive.  More usually, you will use a
relative path name.  In that case, Yorick tries to find the file
relative to these four directories, in this order:

@enumerate
@item
Your current working directory.
@item
@file{~/Yorick}, that is, the @file{Yorick} subdirectory of your home
directory.@refill
@item
@file{Y_SITE/include}, where @file{Y_SITE} is the directory where
Yorick was installed at your site (@kbd{help} will tell you where
this is).@refill
@item
@file{Y_SITE/contrib}
@end enumerate

You can use the @kbd{set_path} command in your @file{custom.i} file
in order to change this path, but you should be very cautious if you
do this.@refill

The @file{~/Yorick} directory is where you put all of the Yorick
include files you frequently use, which have not been placed in the
include or contrib directories at your site.  You can also override an
include file in one of these places by placing a file of the same name
in your @file{~/Yorick} directory.@refill


@node Customizing,  , Include path, Include
@subsubsection The @file{custom.i} file

When Yorick starts, the last thing it does before prompting you is to
include the file @file{custom.i}.  The default @file{custom.i} is in the
@file{Y_SITE/include/custom.i}.  (Yorick's @kbd{help} command will tell
you the actual name of the @file{Y_SITE} directory at your site.)@refill

If you create the directory @file{~/Yorick}, you can place your own
version of @kbd{custom.i} there to override the default.  Always begin
by copying the default file to your directory.  Then add your
customizations to the bottom of the default file.  Generally, these
customizations consist of @kbd{#include} directives for function libraries
you use heavily, plus commands like @kbd{pldefault} to set up your
plotting style preferences.@refill


@node Help, Info, Include, Environment
@subsection The @kbd{help} function

Use the @kbd{help} function to get online help.  Yorick will parrot
the associated @kbd{DOCUMENT} comment to your terminal:

@example
> #include "damped.i"
> help, damped
  DOCUMENT damped.i --- compute and output damped sine waves
  SEE ALSO: damped_wave, q_out
defined at:   LINE: 3  FILE: /home/icf/munro/damped.i
>
@end example

Every Yorick function (including @kbd{help}!) has a @kbd{DOCUMENT}
comment which describes what it does.  Most have @kbd{SEE ALSO:}
references to related help topics, so you can navigate your way
through a series of related topics.@refill

Whenever you want more details about a Yorick function, the first
thing to do is to see what @kbd{help} says about it.  Note that, in
addition to the @kbd{DOCUMENT} comment, @kbd{help} also reports the
full file name and line number where the function is defined.  That
way, if the comment doesn't tell you what you need to know, you can
go to the file and read the complete definition of the function.@refill

The help for @kbd{help} itself, which is the default topic, is of
particular interest, even to a Yorick expert: it tells you the
directory where you can find the include files for all of Yorick's
library functions.  Just type @kbd{help}, like it says when Yorick
starts.  One of the things you will find in Yorick's directory tree is
a @file{doc} directory, which contains not only the source for this
manual, but also alphabetized listings of all @kbd{DOCUMENT} comments.
Read the @kbd{README} file in the @file{doc} directory.@refill


@node Info, Prompts, Help, Environment
@subsection The @kbd{info} function

If you want to know the data type and dimensions of a variable, use
the @kbd{info} function.  Unlike @kbd{help}, which is intended to tell
you what a thing @emph{means}, @kbd{info} simply tells what a thing
@emph{is}.@refill

@example
> info, theta
 array(double,200)
> info, E
 array(double)
@end example

Here, @kbd{double} means ``double precision floating point number'',
which is the default data type for any real number.  The default
integer data type is called @kbd{long}.  (Both these names come from
the C language, which gives them a precise meaning.)@refill

Notice that the scalar value @kbd{E} is, somewhat confusingly, called
an ``array''.  In fact, a scalar is a special case of an array with
zero dimensions.  The @kbd{info} function is designed to print a Yorick
expression which will create a variable of the same data type and
shape as its argument.  Thus, @kbd{array(double,200)} in an expression
would evaluate to an array of 200 real numbers, while
@kbd{array(double)} is a real scalar (the values are always
zero).@refill

Using @kbd{info} on a non-numeric quantity (a file object, a function,
etc.) results in the same output as the @kbd{print} function.  If an
array of numbers might be large, try @kbd{info} before
@kbd{print}.@refill


@node Prompts, Shell commands, Info, Environment
@subsection Prompts

Yorick occasionally prompts you with something other than @kbd{>}.
The usual @kbd{>} prompt tells you that Yorick is waiting for a new
input line.  The other prompts alert you to unusual situations:

@table @kbd
@item cont>
The previous input line was not complete; Yorick is waiting for its
continuation before it does anything.  Type several close brackets or
control-C if you don't want to complete the line.
@item dbug>
When an error occurs during the execution of a Yorick program, Yorick
offers you the choice of entering ``debug mode''.  In this mode, you
are ``inside'' the function where the error occurred.  You can type
any Yorick statement you wish, but until you explicitly exit from
debug mode by means of the @kbd{dbexit} function, Yorick will prompt
you with @kbd{dbug>} instead of its usual prompt.  (@pxref{Simple debugging})
@item quot>
It is possible to continue a long string constant across multiple lines.
If you do, this will be your prompt until you type the closing @kbd{"}.
Don't ever do this intentionally; use the string concatenation operator
@kbd{+} instead, and break long strings into pieces that will fit on
a single line.
@item comm>
For some reason, you began a comment on the previous line, and Yorick
is waiting for the @kbd{*/} to finish the comment.  I can't imagine why
you would put comments in what you were typing at the terminal.
@end table


@node Shell commands, Errors, Prompts, Environment
@subsection Shell commands, removing and renaming files

Yorick has a @kbd{system} function which you can use to invoke
operating system utilities.  For example, typing @kbd{ls *.txt} to a
UNIX shell will list all files in your current working directory
ending with @file{.txt}.  Similarly, @kbd{pwd} prints the name of your
working directory:

@example
> system, "pwd"
/home/icf/munro
> system, "ls *.txt"
   damped.txt      junk.txt
@end example

This is so useful that there is a special escape syntax which
automatically generates the system call, so you don't need to type the
name @kbd{system} or all of the punctuation.  The rule is, that if the
first character of a Yorick statement is @kbd{$} (dollar), the
remainder of that line becomes a quoted string which is passed to the
@kbd{system} function.  Hence, you really would have typed:

@example
> $pwd
/home/icf/munro
> $ls *.txt
   damped.txt      junk.txt
@end example

Note that you cannot use @kbd{;} to stack @kbd{$} escaped lines ---
the semicolon will be passed to @kbd{system}.  Obviously, this syntax
breaks all of the ordinary rules of Yorick's grammar.

On UNIX systems, the @kbd{system} function (which calls the ANSI C
standard library function of the same name) usually executes your
command in a Bourne shell.  If you are used to a different shell, you
might be surprised at some of the results.  If you have some
complicated shell commands for which you need, say, the C-shell
@kbd{csh}, just start a copy of that shell before you issue your
commands:@refill

@example
> $csh
% ls *.txt
  damped.txt    junk.txt
% exit
>
@end example

As this example shows, you can start up an interactive program with
the @kbd{system} function.  When you exit that program, you return to
Yorick.

One system command which you cannot use is @kbd{cd} (or @kbd{pushd} or
@kbd{popd}) to change directories.  The working directory of the shell
you start under Yorick will change, but the change has no effect on
Yorick's own working directory.  Instead, use Yorick's own @kbd{cd}
function:

@example
> cd, "new/working/directory"
>
@end example

Also, if you write a Yorick program which manipulates temporary files,
you should not use the UNIX commands @kbd{mv} or @kbd{rm} to rename or
remove the files; any time you use the @kbd{system} command you are
restricting your program to a particular class of operating systems.
Instead, use Yorick's @kbd{rename} and @kbd{remove} functions, which
will work under any operating system.@refill


@node Errors,  , Shell commands, Environment
@subsection Error Messages

When Yorick cannot decipher the meaning of a statement, you have made
a @emph{syntax} error.  Syntax errors are mostly simple typos, but a
mechanical language like Yorick can be exasperatingly picky:

@example
> th= span(0,2*pi,200)
> for (i=1 ; i<=5 ; ++i) @{ r=cos(i*th); plg,r*sin(th),r*cos(th) @}
SYNTAX: parse error near @}
>
@end example

@noindent
The only mistake here is that Yorick wants a semicolon (or newline)
before the close curly brace completing a compound statement.  If you
think ``fixing'' this type of behavior would be simple, I suggest you
study parsers.  Every programming language has its quirks.

When Yorick detects a syntax error, the error message always begins with
@kbd{SYNTAX:}.  The entire block containing the error will be discarded;
no statements will be executed which might lead to the execution of the
statement containing the error.  If the error is in a function body, the
function will not be defined.  However, if the sytax error occurs
reading an include file, Yorick continues to parse the file looking for
additional syntax errors.  After about a dozen syntax errors in a single
file, Yorick gives up and waits for keyboard input.  Therefore, you may
be able to repair several syntax errors before you re-include the file.

All other errors are @emph{runtime} errors.

@menu
* Runtime errors::              
* Simple debugging::            
@end menu

@node Runtime errors, Simple debugging, Errors, Errors
@subsubsection Runtime errors

Runtime errors in Yorick are often simple typos, like syntax errors:

@example
> theta= span(0,2*pi,200)
> wave= sin(thta)*exp(-0.5*theta)
ERROR (*main*) expecting numeric argument
WARNING source code unavailable (try dbdis function)
now at pc= 1 (of 23), failed at pc= 5
 To enter debug mode, type <RETURN> now (then dbexit to get out)
> 
@end example

@noindent
Many errors of this sort would be detected as syntax errors if you had
to declare Yorick variables.  Yorick's free-and-easy attitude toward
declaration of variables is particularly annoying when the offending
statement is in a conditional branch which is very rarely executed.
When a bug like that ambushes you, be philosophical: Minutely declared
languages will just ambush you in more subtle ways.

Other runtime errors are more interesting; often such a bug will teach
you about the algorithm or even about the physical problem:

@example
> #include "damped.i"
> theta= span(0, 6*pi, 300)
> amplitude= damped_wave(theta, 0.25)
ERROR (damped_wave) math library exception handler called
  LINE: 19  FILE: /home/icf/munro/damped.i
 To enter debug mode, type <RETURN> now (then dbexit to get out)
>
@end example

@noindent
What is an oscillator with a Q of less than one half?  Maybe you don't
care about the so-called @emph{overdamped} case --- you really wanted
Q to be 2.5, not 0.25.  On the other hand, maybe you need to modify
the @kbd{damped_wave} function to handle the overdamped case.@refill


@node Simple debugging,  , Runtime errors, Errors
@subsubsection How to respond to a runtime error

When Yorick stops with a runtime error, you have a choice: You can
either type the next statment you want to execute, or you can type a
carriage return (that is, a blank line) to enter debug mode.  The two
possibilities would look like this:

@example
ERROR (damped_wave) math library exception handler called
  LINE: 19  FILE: /home/icf/munro/damped.i
 To enter debug mode, type <RETURN> now (then dbexit to get out)
> amplitude= damped_wave(theta, 2.5)
>
@end example

@example
ERROR (damped_wave) math library exception handler called
  LINE: 19  FILE: /home/icf/munro/damped.i
 To enter debug mode, type <RETURN> now (then dbexit to get out)
>
dbug>
@end example

In the second case, you have entered debug mode, and the @kbd{dbug>}
prompt appears.  In debug mode, Yorick leaves the function which was
executing and its entire calling chain intact.  You can type any Yorick
statement; usually you will print some values or plot some arrays to
try to determine what went wrong.  When you reference or modify a
variable which is local to the function, you will ``see'' its local
value:

@example
dbug> nu; 1-nu*nu
2
-3
dbug>
@end example

As soon as possible, you should escape from debug mode using the
@kbd{dbexit} function:

@example
dbug> dbexit
>
@end example

You may also be able to repair the function's local variables and
resume execution.  To modify the value of a variable, simply redefine
it with an ordinary Yorick statement.  The @kbd{dbcont} function
continues execution, beginning by re-executing the statement which
failed to complete.  Use the @kbd{help} function (@pxref{Help}) to learn
about the other debugging functions; the help for the @kbd{dbexit}
function describes them all.@refill



@comment -----------------------------------------------------------------

@node    Arrays, Embedding, Basics, Top
@chapter Using Array Syntax

Most Yorick statements look like algebraic formulas.  A variable name is
a string like @kbd{Var_1} --- upper or lower case characters (case
matters), digits, or underscores in any combination except that the
first character may not be a digit.  Expressions consist of the usual
arithmetic operations @kbd{+ - * /}, with parentheses to indicate the
order of operations (when that order is different than or unclear from
the ordinary rules of precedence in algebra).  Elementary mathematical
functions such as @kbd{exp(x)}, @kbd{cos(x)}, or @kbd{atan(x)} look just
like that.@refill

Usually, a Yorick variable is a parametric representation of a
mathematical function.  The variable is an array of numbers which are
values of the function at a number of points; few points to represent
the function coarsely, more for an accurate rendition.  The parameters
of the function are the indices into the array, which rarely make an
explicit appearance in Yorick programs.  Thus,

@example
theta= span(0.0, 2*pi, 100)
@end example

@noindent
defines a variable @kbd{theta} consisting of 100 evenly spaced values
starting with @kbd{0.0} and ending with @kbd{2*pi}.@refill

Now that @kbd{theta} has been defined as a list of 100 numbers, any
function of @kbd{theta} has a concrete representation as a list of 100
numbers --- namely the values of the function at the 100 particular
values of @kbd{theta}.  Hence, variables @kbd{x} and @kbd{y}
representing coordinates of the unit circle are defined with:@refill

@example
x= cos(theta);   y= sin(theta)
@end example

Here, @kbd{cos} and @kbd{sin} are built-in Yorick functions.  Like most
Yorick functions, they operate on an entire array of numbers, returning
an array of like shape.  Hence both @kbd{x} and @kbd{y} are now lists of
100 numbers -- the cosines and sines of the 100 numbers
@kbd{theta}.@refill

The semicolon marks the end of a Yorick statement, allowing several
statements to share a single line.  The end of a line (i.e.- a newline)
can also mark the end of a Yorick statement.  However, if any
parentheses are open, or if a binary operator or a comma is the last
token on the line, then the newline is treated like a space or a tab
character and does not terminate the Yorick statement.

If a line ends with backslash, the following newline will never
terminate the Yorick statement.  (That is, backslash is the continuation
character in Yorick.)  I recommend that you never use a backslash -- end
the line to be continued with a binary operator, or leave the comma
separating subroutine arguments at the end of the line, or split a
parenthetic expression across the line, and it will be continued
automatically.

@menu
* Creating Arrays::             How to originate arrays.
* Interpolating::               Interpolation functions.
* Indexing::                    How to reference array elements.
* Sorting::                     How to sort an array.
* Transposing::                 How to change the order of array dimensions.
* Broadcasting::                Making arrays conformable.
* Dimension Lists::             
@end menu

@node    Creating Arrays, Interpolating, Arrays, Arrays
@section Creating Arrays

Including the @kbd{span} function introduced in the previous section,
there are five common ways to originate arrays --- that is, to make an
array out of scalar values:

@table @kbd
@item [val1, val2, val3, ...]
The most primitive way to build an array is to enumerate the successive
elements of the array in square brackets.  The length of the array is
the number of values in the list.  An exceptional case is @kbd{[]},
which is called ``nil''.  A Yorick variable has the value nil before
it has been defined, and @kbd{[]} is a way to write this special value.
@refill

@item array(value, dimlist)
Use @kbd{array} to ``broadcast'' (@pxref{Broadcasting}) a value into an
array, increasing its number of dimensions.  A @kbd{dimlist} is a
standard list of arguments used by several Yorick functions
(@pxref{Dimension Lists}).  Often, the pseudo-index range function
(@pxref{Pseudo-Index}) is a clearer alternative to the @kbd{array}
function.@refill

@item span(start, stop, number)
Use @kbd{span} to generate a list of equally spaced values.

@item indgen(n)
@itemx indgen(lower:upper)
@itemx indgen(start:stop:step)
Use @kbd{indgen} (``index generator'') instead of @kbd{span} to generate
equally spaced integer values.  By default, the list starts with 1.@refill

@item spanl(start, stop, number)
Use @kbd{spanl} (``span logarithmically'') to generate a list of numbers
which increase or decrease by a constant ratio.@refill
@end table

@node    Interpolating, Indexing, Creating Arrays, Arrays
@section Interpolating

As I have said, a Yorick array often represents the values of a
continuous function at a number of discrete points.  In order to find
the values of the function at other points, you need to know how it
varies between (or beyond) the given points.  In general, to interpolate
(or extrapolate), you need a detailed understanding of how the function
was discretized in the first place.  However, when the list of values
accurately represents the function, linear interpolation between the
known points will suffice.  A function which is linear between
successive points is called ``piecewise linear''.

The @kbd{interp} function is a mechanism for converting a list of
function values at discrete points into a piecewise linear function
which can be evaluated at any point.

@example
theta= span(0, pi, 100);
x_circle= cos(theta);
y_circle= sin(theta);
x= span(-2, 2, 64);
y= interp(y_circle, x_circle, x);
@end example

This code fragment produces a @kbd{y} array with the same number of
points as @kbd{x} (64), with the values of the piecewise linear function
defined by the points @kbd{(x_circle, y_circle)}.  Outside the range
covered by @kbd{x_circle}, the piecewise linear function remains
constant -- the simplest possible extrapolation rule.@refill

Regarded as a function of its third argument, @kbd{interp} behaves just
like the @kbd{sin} or @kbd{cos} function -- its first two arguments are
really parameters specifying which piecewise linear function
@kbd{interp} will evaluate.@refill

The @kbd{integ} function works just like @kbd{interp}, except that it
returns the integral of the piecewise linear function.  The integration
constant is chosen so that @kbd{integ} returns zero at the first point
of the piecewise linear function.  (This point will actually have the
maximum value of x if the x array is decreasing.)  Thus, the integral
of the piecewise linear approximation to the semicircle and the exact
integral of the semicircle can be computed by:@refill

@example
yi= integ(y_circle, x_circle, x);
yi_exact= 0.5*(acos(max(min(x,1),-1)) - x*sqrt(1-min(x^2,1)));
@end example

Again, the piecewise linear function is assumed to remain constant
beyond the first and last points specified.  Hence, @kbd{integ} is a
linear function when extrapolating, and piecewise parabolic when
interpolating.@refill

Use @kbd{integ} only when you need the indefinite integral of a
piecewise linear function.  Yorick has more efficient ways to compute
definite integrals.  Again, think of @kbd{integ}, like @kbd{interp}, as
a continuous function of its third argument; the first two arguments are
parameters specifying which function.@refill

Neither @kbd{interp} nor @kbd{integ} makes sense unless its second
argument is either increasing or decreasing.  There is no way to decide
which branch of a multi-valued function should be returned.@refill

Internally, both @kbd{interp} and @kbd{integ} need a lookup function --
that is, a function which finds the index of the point in x_circle just
beyond each of the x values.  This lookup function can also be called
directly; its name is @kbd{digitize}.@refill



@node    Indexing, Sorting, Interpolating, Arrays
@section Indexing

Yorick has a bewildering variety of different ways to refer to
individual array elements or subsets of array elements.  In order to
master the language, you must learn to use them all.  Nearly all of the
examples later in this manual use one or more of these indexing
techniques, so trust me to show you how to use them later:

@itemize @bullet
@item
A scalar integer index refers to a specific array element.  In a
multi-dimensional array, this ``element'' is itself an array -- the
specified row, column, or hyperplane.

@item
An index which is nil or omitted refers to the entire range of the
corresponding array dimension.

@item
An index range of the form @kbd{start:stop} or @kbd{start:stop:step}
refers to an evenly spaced subset of the corresponding array
dimension.@refill

@item
An array of integers refers to an arbitrary subset, possibly including
repeated values, of the corresponding array dimension.

@item
The special symbol @kbd{-}, or @kbd{-:start:stop}, is the pseudo-index.
It inserts an index in the result which was not present in the array
being indexed.  Although this sounds recondite, the pseudo-index is
often necessary in order to make two arrays conformable for a binary
operation.@refill

@item
The special symbol @kbd{..} or @kbd{*} is a rubber-index.  A
rubber-index stands for zero or more dimensions of the array being
indexed.  This syntax allows you to specify a value for the final index
of an array, even when you don't know how many dimensions the array has.
The @kbd{..} version leaves the original dimension count intact; the
@kbd{*} version collapses all dimensions into a single long dimension in
the result.@refill

@item
The special symbol @kbd{+} marks an index for matrix multiplication.

@item
Many statistical functions, such as @kbd{sum}, @kbd{avg}, and @kbd{max}
can be applied along a specific dimension of an array.  These reduce the
rank of the resulting array, just like a scalar integer index value.@refill

@item
Several finite difference functions, such as @kbd{zcen} (zone center)
and @kbd{cum} (cumulative sums) can be applied along a specific array
dimension.  You can use these to construct numerical analogues to the
operations of differential and integral calculus.@refill
@end itemize

@menu
* Scalar Index::                Scalar indices and array order.
* Index Range::                 Selecting a range of indices.
* Nil Index::                   Nil index refers to an entire dimension.
* Index List::                  Selecting an arbitrary list of indices.
* Pseudo-Index::                Creating a pseudo-index.
* Negative Index::              Numbering a dimension from its last element.
* Rubber-Index::                Using a rubber index.
* Matrix Multiply::             Marking an index for matrix multiplication.
* Statistical::                 Rank reducing (statistical) range functions.
* Finite Difference::           Rank preserving (finite difference) range functions.
@end menu

@node    Scalar Index, Index Range, Indexing, Indexing
@subsection Scalar indices and array order

An array of objects is stored in consecutive locations in memory (where
each location is big enough to hold one of the objects).  An array
@kbd{x} of three numbers is stored in the order @kbd{[x(1), x(2), x(3)]}
in three consecutive slots in memory.  A three-by-two array @kbd{y}
means nothing more than an array of two arrays of three numbers each.
Thus, the six numbers are stored in two contiguous blocks of three
numbers each: @kbd{[[x(1,1), x(2,1), x(3,1)], [x(1,2), x(2,2),
x(3,2)]]}.@refill

A multi-dimensional array may be referenced using fewer indices than its
number of dimensions.  Hence, in the previous example, @kbd{x(5)} is the
same as @kbd{x(2,2)}, since the latter element is stored fifth.

Although most of Yorick's syntax follows the C language, array indexing
is designed to resemble FORTRAN array indexing.  In Yorick, as in
FORTRAN, the first (leftmost) dimension of an array is always the index
which varies fastest in memory.  Furthermore, the first element along
any dimension is at index 1, so that a dimension of length three can be
referenced by index 1 (the first element), index 2 (the second element),
or index 3 (the third element).

If this inconsistency bothers you, here is why Yorick indexing is like
FORTRAN indexing: In C, an array of three numbers, for example, is a
data type on the same footing as the data type of each of its three
members; by this trick C sidesteps the issue of multi-dimensional arrays
--- they are singly arrays of objects of an array data type.  While this
picture accurately reflects the way the multi-dimensional array is
stored in memory, it does not reflect the way a multi-dimensional array
is used in a scientific computer program.

In such a program, the fact that the array is stored with one or the
other index varying fastest is irrelevent --- you are equally likely to
want to consider as a ``data type'' a slice at a constant value of the
first dimension as of the second.  Furthermore, the length of every
dimension varies as you vary the resolution of the calculation in the
corresponding physical direction.



@node    Index Range, Nil Index, Scalar Index, Indexing
@subsection Selecting a range of indices

You can refer to several consecutive array elements by an index range:
@kbd{x(3:6)} means the four element subarray @kbd{[x(3), x(4), x(5),
x(6)]}.@refill

Occasionally, you also want to refer to a sparse subset of an array; you
can add an increment to an index range by means of a second colon:
@kbd{x(3:7:2)} means the three element subarray @kbd{[x(3), x(5),
x(7)]}.@refill

A negative increment reverses the order of the elements: @kbd{x(7:3:-2)}
represents the same three elements, but in the opposite order
@kbd{[x(7), x(5), x(3)]}.  The second element mentioned in the index
range may not actually be present in the resulting subset, for example,
@kbd{x(7:2:-2)} is the same as @kbd{x(7:3:-2)}, and @kbd{x(3:6:2)}
represents the two element subarray @kbd{[x(3), x(5)]}.@refill

Just as the increment defaults to 1 if it is omitted, the start and stop
elements of an index range also have default values, namely the first
and last possible index values.  Hence, if @kbd{x} is a one-dimensional
array with 10 elements, @kbd{x(8:)} is the same as @kbd{x(8:10)}.  With
a negative increment, the defaults are reversed, so that @kbd{x(:8:-1)}
is the same as @kbd{x(10:8:-1)}.@refill

A useful special case of the index range default rules is @kbd{x(::-1)},
which represents the array @kbd{x} in reverse order.@refill

Beware of a minor subtlety: @kbd{x(3:3)} is not the same thing as
@kbd{x(3)}.  An index range always represents an array of values, while
a scalar index represents a single value.  Hence, @kbd{x(3:3)} is an
array with a single element, @kbd{[x(3)]}.@refill



@node    Nil Index, Index List, Index Range, Indexing
@subsection Nil index refers to an entire dimension

When you index a multi-dimensional array, very often you want to let
one or more dimensions be ``spectators''.  In Yorick, you accomplish this
by leaving the corresponding index blank:

@example
x(3,)
x(,5:7)
y(,::-1,)
x(,)
@end example

In these examples, @kbd{x} is a 2-D array, and @kbd{y} is a 3-D array.
The first example, @kbd{x(3,)}, represents the 1-D array of all the
elements of @kbd{x} with first index 3.  The second represents a 2-D
array of all of the elements of @kbd{x} whose second indices are 5, 6,
or 7.  In the third example, @kbd{y(,::-1,)} is the @kbd{y} array with
the elements in reverse order along its middle index.  The fourth
expression, @kbd{x(,)}, means the entire 2-D array @kbd{x}, unchanged.
@refill




@node    Index List, Pseudo-Index, Nil Index, Indexing
@subsection Selecting an arbitrary list of indices

An index list is an array of index values.  Use an index list to specify
an arbitrary subset of an array: @kbd{x([5,1,2,1])} means the four
element array @kbd{[x(5), x(1), x(2), x(1)]}.  The @kbd{where} function
returns an index list:@refill

@example
list= where(x > 3.5)
y= x(list)
@end example

@noindent
These lines define the array @kbd{y} to be the subset of the @kbd{x}
array, consisting of the elements greater than 3.5.@refill

Like the result of an index range, the result of an index list is itself
an array.  However, the index list follows a more general rule: The
dimensionality of the result is the same as the dimensionality of the
index list.  Hence, @kbd{x([[5, 1], [2, 1]])} refers to the two
dimensional array @kbd{[[x(5), x(1)], [x(2), x(1)]]}.  The general rule
for index lists is:@refill

@display
Dimensions from the dimensions of the index list; values from the array
being indexed.
@end display

@noindent
Note that the scalar index value is a special case of an index list
according to this rule.

The rule applies to multi-dimensional arrays as well: If @kbd{x} is a
five-by-nine array, then @kbd{x(, [[5, 1], [2, 1]])} is a
five-by-two-by-two array.  And @kbd{x([[5, 1], [2, 1]], 3:6)} is a
two-by-two-by-four array.@refill



@node    Pseudo-Index, Negative Index, Index List, Indexing
@subsection Creating a pseudo-index

A binary operation applied between two arrays of numbers yields an array
of results in Yorick -- the operation is performed once for each
corresponding pair of elements of the operands.  Hence, if @kbd{rho} and
@kbd{vol} are each four-by-three arrays, the expression @kbd{rho*vol}
will be a four-by-three array of products, starting with
@kbd{rho(1,1)*vol(1,1)}.@refill

This extension of binary operations to array operands is not always
appropriate.  Instead of operating on the corresponding elements of
arrays of the same shape, you may want to perform the operation between
all pairs of elements.  The most common example is the outer product
of two vectors @kbd{x} and @kbd{y}:@refill

@example
outer= x*y(-,);
@end example

@noindent
Here, if @kbd{x} were a four element vector, and @kbd{y} were a three
element vector, @kbd{outer} would be the four-by-three array
@kbd{[[x(1)*y(1), x(2)*y(1), x(3)*y(1), x(4)*y(1)], [x(1)*y(2),
x(2)*y(2), x(3)*y(2), x(4)*y(2)], [x(1)*y(3), x(2)*y(3), x(3)*y(3),
x(4)*y(3)]]}.@refill

In Yorick, this type of multiplication is still commutative.  That is,
@kbd{x*y(-,)} is the same as @kbd{y(-,)*x}.  To produce the three-by-four
transpose of the array @kbd{outer}, you would write @kbd{x(-,)*y}.@refill

I call the @kbd{-} sign, when used as an index, a pseudo-index because
it actually inserts an additional dimension into the result array which
was not present in the array being indexed.  By itself, the expression
@kbd{y(-,)} is a one-by-three array (with the same three values as the
three element vector @kbd{y}).  You may insert as many pseudo-indices
into a list of subscripts as you like, at any location you like relative
to the actual dimensions of the array you are indexing.  Hence,
@kbd{outer(-,-,,-,)} would be a one-by-one-by-four-by-one-by-three array.
@refill

By default, a pseudo-index produces a result dimension of length one.
However, by appending an index range to the @kbd{-} sign, separated by
a colon, you can produce a new dimension of any convenient length:

@example
x= span(-10, 10, 100)(,-:1:50);
y= span(-5, 5, 50)(-:1:100,);
gauss2d= exp(-0.5*(x^2+y^2))/(2.0*pi);
@end example

@noindent
computes a normalized 2-D Gaussian function on a 100-by-50 rectangular
grid of points in the xy-plane.  The pseudo-index @kbd{-:1:50} has 50
elements, and @kbd{-:1:100} has 100.  For a pseudo-index of non-unit
length, the values along the actual dimensions are simply copied, so
that @kbd{span(-10, 10, 100)(,-:1:50)} is a 100-by-50 array consisting
of 50 copies of @kbd{span(-10, 10, 100)}.@refill

If only the result @kbd{gauss2d} were required, a single default
pseudo-index would have sufficed:@refill

@example
gauss2d= exp(-0.5*( span(-10,10,100)^2 +
                    span(-5,5,50)(-,)^2 )) / (2.0*pi);
@end example

However, the rectangular grid of points (@kbd{x},@kbd{y}) is often
required -- as input to plotting routines for example.@refill



@node    Negative Index, Rubber-Index, Pseudo-Index, Indexing
@subsection Numbering a dimension from its last element

Array index values are subtly asymmetric: An index of 1 represents the
first element, 2 represents the second element, 3 the third, and so on.
In order to refer to the last, or next to last, or any element relative
to the final element, you apparently need to find out the length of the
dimension.

In order to remedy this asymmetry, Yorick interprets numbers less than 1
relative to the final element of an array.  Hence, @kbd{x(1)} and
@kbd{x(2)} are the first and second elements of @kbd{x}, while
@kbd{x(0)} and @kbd{x(-1)} are the last and next to last elements, and
so on.@refill

With this convention for negative indices, many Yorick programs can
be written without the need to determine the length of a dimension:

@example
deriv= (f(3:0)-f(1:-2)) / (x(3:0)-x(1:-2));
@end example

@noindent
computes a point-centered estimate of the derivative of a function
@kbd{f} with values known at points @kbd{x}.  (A better way to compute
this derivative is to use the @kbd{pcen} and @kbd{dif} range functions
described below.  @xref{Finite Difference, , Rank preserving (finite
difference) range functions}.)@refill

In this example, the extra effort required to compute the array length
would be slight:

@example
n= numberof(f);
deriv= (f(3:n)-f(1:n-2)) / (x(3:n)-x(1:n-2));
@end example

@noindent
However, using the negative index convention produces faster code, and
generalizes to multi-dimensional cases in an obvious way.

The negative index convention works for scalar index values and for the
start or stop field of an index range (as in the example).  Dealing with
negative indices in an index list would slow the code down too much, so
the values in an index list may not be zero or negative.



@node    Rubber-Index, Matrix Multiply, Negative Index, Indexing
@subsection Using a rubber index

Many Yorick functions must work on arrays with an unknown number of
dimensions.  Consider a filter response function, which takes as input a
spectrum (brightness as a function of photon energy), and returns the
response of a detector.  Such a function could be passed a spectrum and
return a scalar value.  Or, it might be passed a two dimensional array
of spectra for each of a list of rays, and be expected to return the
corresponding list of responses.  Or a three dimensional array of
spectra at each pixel of a two dimensional image, returning a two
dimensional array of response values.

In order to write such a function, you need a way to say, ``and all other
indices this array might have''.  Yorick's rubber-index, @kbd{..}, stands
for zero or more actual indices of the array being indexed.  Any indices
preceding a rubber-index are ``left justified'', and any following it are
``right justified''.  Using this syntax, you can easily index an array, as
long as you know that the dimension (or dimensions) you are interested
in will always be first, or last -- even if you don't know how many
spectator dimensions might be present in addition to the one your
routine processes.

Thus, as long as the spectral dimension is always the final dimension
of the input @kbd{brightness} array,

@example
brightness(..,i)
@end example

@noindent
will always place the @kbd{i} index in the spectral dimension, whether
@kbd{brightness} itself is a 1-D, 2-D, or 3-D array.@refill

Similarly, @kbd{x(i,..)} selects a value of the first index of @kbd{x},
leaving intact all following dimensions, if any.  Constructions such as
@kbd{x(i,j,..,k,l)} are also legal, albeit rarely necessary.@refill

A second form of rubber-index collapses zero or more dimensions into a
single index.  The length of the collapsed dimension will be the product
of the lengths of all of the dimensions it replaces (or 1, if it
replaces zero dimensions).  The symbol for this type of rubber index is
an asterisk @kbd{*}.  For example, if @kbd{x} were a
five-by-three-by-four-by-two array, then @kbd{x(*)} would be a 1-D array
of 120 elements, while @kbd{x(,*,)} would be a five-by-twelve-by-two
array.@refill

If the last actual index in a subscripted array is nil, and if this
index does not correspond to the final actual dimension of the array,
Yorick will append a @kbd{..} rubber-index to the end of the subscript
list.  Hence, in the previous example, @kbd{x()} is equivalent to
@kbd{x(,..)}, which is equivalent to @kbd{x(..)}, which is equivalent to
simply @kbd{x}.  This rule is the only rogue in Yorick's array
subscripting stable, and I am mightily tempted to remove it on grounds
of linguistic purity.  When you mean, ``and any other dimensions which
might be present,'' use the @kbd{..} rubber-index, not a nil index.  Use
a trailing nil index only when you mean, ``and the single remaining
dimension (which I know is present).''@refill



@node    Matrix Multiply, Statistical, Rubber-Index, Indexing
@subsection Marking an index for matrix multiplication

Yorick has a special syntax for matrix multiplication, or, more
generally, inner product:

@example
A(,+)*B(+,)
B(+,)*A(,+)
x(+)*y(+)
P(,+,,)*Q(,,+)
@end example

@noindent
In the first example, @kbd{A} would be an L-by-M array, @kbd{B} would be
an M-by-N array, and the result would be the L-by-N matrix product.  In
the second example, the result would be the N-by-L transpose of the
first result.  The general rule is that all of the ``spectator''
dimensions of the left operand precede the spectator dimensions of the
right operand in the result.

The third example shows how to form the inner product of two vectors
@kbd{x} and @kbd{y} of equal length.  The fourth example shows how to
contract the second dimension of a 4-D array @kbd{P} with the third
dimension of the 3-D array @kbd{Q}.  If @kbd{P} were 2-by-3-by-4-by-5
and @kbd{Q} were 6-by-7-by-3, the result array would be
2-by-4-by-5-by-6-by-7.@refill

Unlike all of the other special subscript symbols (nil, @kbd{-},
@kbd{..}, and @kbd{*} so far), the @kbd{+} sign marking an index for use
in an inner product is actually treated specially by the Yorick parser.
The @kbd{+} subscript is a parse error unless the array (or expression)
being subscripted is the left or right operand of a binary @kbd{*}
operator, which is then parsed as matrix multiplication instead of
Yorick's usual element-by-element multiplication.  A parse error will
also result if only one of the operands has a dimension marked by
@kbd{+}.  Both operands must have exactly one marked dimension, and the
marked dimensions must turn out to be of equal length at run
time.@refill



@node    Statistical, Finite Difference, Matrix Multiply, Indexing
@subsection Rank reducing (statistical) range functions

The beauty of Yorick's matrix multiplication syntax is that you ``point''
to the dimension which is to be contracted by placing the @kbd{+} marker
in the corresponding subscript.  In this section and the following
section, I introduce Yorick's range functions, which share the ``this
dimension right here'' syntax with matrix multiplication.  The topic in
this section is the statistical range functions.  These functions reduce
the rank of an array, as if they were a simple scalar index, but instead
of selecting a particular element along the dimension, a statistical
range function selects a value based on an examination of all of the
elements along the selected dimension.  The statistical function is
repeated separately for each value of any spectator dimensions.  The
available functions are:

@table @kbd
@item min
@itemx max
returns the minimum (or maximum) value.  These are also available as
ordinary functions.

@item sum
returns the sum of all the values.  This is also available as an
ordinary function.

@item avg
returns the arithmetic mean of all the values.  The result will be a
real number, even if the input is an integer array.  This is also
available as an ordinary function.

@item ptp
returns the peak-to-peak difference (difference between the maximum
and the minimum) among all the values.  The result will be positive
if the maximum occurs at a larger index than the minimum, otherwise
the result will be negative.

@item rms
returns the root mean square deviation from the arithmetic mean of the
values.  The result will be a real number, even if the input is an
integer array.

@item mnx
@itemx mxx
returns the index of the element with the smallest (or largest) value.
The result is always an integer index value, independent of the data
type of the array being subscripted.  If more than one element reaches
the extreme value, the result will be the smallest index.
@end table

The @kbd{min}, @kbd{max}, @kbd{sum}, and @kbd{avg} functions may also
be applied using ordinary function syntax, which is preferred if you
want the function to be applied across all the dimensions of an array
to yield a single scalar result.@refill

Given the @kbd{brightness} array representing the spectrum incident on a
detector or set of detectors, the @kbd{mxx} function can be used to find
the photon energy at which the incident light is brightest.  Assume that
the final dimension of @kbd{brightness} is always the spectral
dimension, and that the 1-D array @kbd{gav} of photon energies (with the
same length as the final dimension of @kbd{brightness}) is also
given:@refill

@example
max_index_list= brightness(.., mxx);
gav_at_max= gav(max_index_list);
@end example

@noindent
Note that @kbd{gav_at_max} would be a scalar if @kbd{brightness} were
a 1-D spectrum for a single detector, a 2-D array if @kbd{brightness}
were a 3-D array of spectra for each point of an image, and so on.
@refill

An arbitrary index range (@kbd{start:stop} or @kbd{start:stop:step}) may
be specified for any range function, by separating the function name
from the range by another colon.  For example, to select only a relative
maximum of @kbd{brightness} for photon energies above 1.0, ignoring
possible larger values at smaller energies, you could use:
@refill

@example
i= min(where(gav > 1.0));
max_index_list= brightness(.., mxx:i:0);
gav_at_max= gav(max_index_list);
@end example

@noindent
Note the use of @kbd{min} invoked as an ordinary function in the first
line of this example.  (Recall that @kbd{where} returns a list of
indices where some conditional expression is true.)  In the second line,
@kbd{mxx:i:0} is equivalent to @kbd{mxx:i:}.  Because of the details of
Yorick's current implementation, the former executes slightly faster.
@refill

More than one range function may appear in a single subscript list.  If
so, they are computed from left to right.  In order to execute them in
another order, you must explicitly subscript the expression resulting
from the first application:

@example
x= [[1, 3, 2], [8, 0, 9]];
max_min= x(max, min);
min_max= x(, min)(max);
@end example

@noindent
The value of @kbd{max_min} is 3; the value of @kbd{min_max} is 2.



@node    Finite Difference,  , Statistical, Indexing
@subsection Rank preserving (finite difference) range functions

Because Yorick arrays almost invariably represent function values,
Yorick provides numercal equivalents to the common operations of
differential and integral calculus.  In order to handle functions of
several variables in a straightforward manner, these operators are
implemented as range functions.  Unlike the statistical range functions,
which return a scalar result, the finite difference range functions do
not reduce the rank of the subscripted array.  Instead, they preserve
rank, in the same way that a simple index range @kbd{start:stop}
preserves rank.  The available finite difference functions are:
@refill

@table @kbd
@item cum
returns the cumulative sums (sum of all values at smaller index, the
first index of the result having a value of 0).  The result dimension
has a length one greater than the dimension in the subscripted array.

@item psum
returns the partial sum (sum of all values at equal or smaller index)
up to each element.  The result dimension has the same length as the
dimension in the subscripted array.  This is the same as @kbd{cum},
except that the leading 0 value in the result is omitted.@refill

@item dif
returns the pairwise difference between successive elements, positive
when the function values increase along the dimension, negative when
they decrease.  The result dimension has a length one less than the
dimension of the subscripted array.  The @kbd{dif} function is the
inverse of the @kbd{cum} function.@refill

@item zcen
returns the pairwise average between successive elements.  The result
dimension has a length one less than the dimension of the subscripted
array.  The name is short for ``zone center''.

@item pcen
returns the pairwise average between successive elements.  However, the
two endpoints are copied unchanged, so that the result dimension has a
length one greater than the dimension of the subscripted array.  The
name is short for ``point center''.

@item uncp
returns the inverse of the @kbd{pcen} operation.  (Gibberish will be the
result of applying this function to an array dimension which was not
produced by the @kbd{pcen} operation.)  The result dimension has a
length one less than the dimension of the subscripted array.  The name
is short for ``uncenter point centered''.
@end table

The derivative @i{dy/dx} of a function @i{y(x)}, where @i{y} and @i{x}
are represented by 1-D arrays @kbd{y} and @kbd{x} of equal length is:@refill

@example
deriv= y(dif)/x(dif);
@end example

@noindent
Note that @kbd{deriv} has one fewer element than either @kbd{y} or
@kbd{x}.  The derivative is computed as if @i{y(x)} were the piecewise
linear function passing through the given points @kbd{(x,y)}; there is
one fewer line segment (slope) than point.@refill

The values @kbd{x} and @kbd{y} can be called ``point-centered'', while the
values @kbd{deriv} can be called ``zone-centered''.  The @kbd{zcen} and
@kbd{pcen} functions provide a simple mechanism for moving back and
forth between point-centered and zone-centered quantities.  Usually,
there will be several reasonable ways to point-center zone centered data
and vice-versa.  For example:@refill

@example
deriv_pc1= deriv(pcen);
deriv_pc2= y(dif)(pcen)/x(dif)(pcen);
deriv_pc3= y(pcen)(dif)/x(pcen)(dif);
@end example

@noindent
For a well-resolved function, the differences among these three arrays
will be negligible.  That is, the differences are second order in
@kbd{x(dif)}, which is often the order of the errors in the calculation
that produced @kbd{x} and @kbd{y} in the first place.  If @kbd{x} and
@kbd{y} represent @i{y(x)} more accurately that this, then you must know
a better model of the shape of @i{y(x)} than the simple piecewise linear
model, and you should use that model to select @kbd{deriv_pc1},
@kbd{deriv_pc2}, and @kbd{deriv_pc3}, or some other expression.@refill

An indefinite integral may be estimated using the trapezoidal rule:

@example
indef_integ= (y(zcen)*x(dif))(psum);
@end example

@noindent
Once again, @kbd{indef_integ} has one fewer point than @kbd{x} or
@kbd{y}, because there is one fewer trapezoid than point.  This time,
however, @kbd{indef_integ} is not zone centered.  Instead,
@kbd{indef_integ} represents values at the upper (or lower) boundaries
@kbd{x(2:)} (or @kbd{x(:-1)}).  Often, you want to think of the integral
of @i{y(x)} as a point centered array of definite integrals from
@kbd{x(1)} up to each of the @kbd{x(i)}.  In this case (which actually
arises more frequently), use the @kbd{cum} function instead of
@kbd{psum} in order to produce a result @kbd{def_integs} with the same
number of points as the @kbd{x} and @kbd{y} arrays:@refill

@example
def_integs= (y(zcen)*x(dif))(cum);
@end example

For single definite integrals, the matrix multiply syntax can be used in
conjunction with the @kbd{dif} range function.  For example, suppose you
know the transmission fraction of the filter, @kbd{ff}, at several
photon energies @kbd{ef}.  That is, @kbd{ff} and @kbd{ef} are 1-D arrays
of equal length, specifying a filter transmission function as the
piecewise linear function connecting the given points.  The final
dimension of an array @kbd{brightness} represents an incident spectrum
(any other dimensions represent different rays, say one ray per pixel of
an imaging detector).  The 1-D array @kbd{gb} represents the group
boundary energies -- that is, the photon energies at the boundaries of
the spectral groups represented in @kbd{brightness}.  The following
Yorick statements compute the detector response:@refill

@example
filter= integ(ff, ef, gb)(dif);
response= brightness(..,+)*filter(+);
@end example

For this application, the correct interpolation routine is @kbd{integ}.
The integrated transmission function is evaluated at the boundaries
@kbd{gb} of the groups; the effective transmission fraction for each
group is the difference between the integral at the upper bin boundary
and the lower bin boundary.  The @kbd{dif} range function computes these
pairwise differences.  Since the @kbd{gb} array naturally has one more
element than the final dimension of @kbd{brightness} (there is one more
group boundary energy than group), and since @kbd{dif} reduces the
length of a dimension by one, the @kbd{filter} array has the same length
as the final dimension of @kbd{brightness}.@refill

Note that the @kbd{cum} function cannot be used to integrate
@kbd{ff(ef)}, because the points @kbd{gb} at which the integral must be
evaluated are not the same as the points @kbd{ef} at which the integrand
is known.  Whenever the points at which the integral is required are the
same (or a subset of) the points at which the integrand is known, you
should perform the integral using the @kbd{zcen}, @kbd{dif}, and
@kbd{cum} index functions, instead of the more general @kbd{integ}
interpolator.@refill




@node    Sorting, Transposing, Indexing, Arrays
@section Sorting

The function @kbd{sort} returns an index list:

@example
list= sort(x);
@end example

The list has the same length as the input vector @kbd{x}, and list(1) is
the index of the smallest element of @kbd{x}, list(2) the index of the
next smallest, and so on.  Thus, @kbd{x(list)} will be @kbd{x} sorted
into ascending order.@refill

By returning an index list instead of the sorted array, @kbd{sort}
simplifies the co-sorting of other arrays.  For example, consider a
series of elaborate experiments.  On each experiment, thermonuclear
yield and laser input energy are measured, as well as fuel mass.  These
might reasonably be stored in three vectors @kbd{yield}, @kbd{input},
and @kbd{mass}, each of which is a 1D array with as many elements as
experiments performed.  The order of the elements in the arrays maight
naturally be the order in which the experiments were performed, so that
@kbd{yield(3)}, @kbd{input(3)}, and @kbd{mass(3)} represent the third
experiment.  The experiments can be sorted into order of increasing
gain (yield per unit input energy) as follows:

@example
list= sort(yield/input);
yield= yield(list);
input= input(list);
mass= mass(list);
@end example

The inverse list, which will return them to their orginal order, is:

@example
invlist= list;  /* faster than  array(0, dimsof(list)) */
invlist(list)= indgen(numberof(list));
@end example

The @kbd{sort} function actually sorts along only one index of a
multi-dimensional array.  The dimensions of the returned list are the
same as the dimensions of the input array; the values are indices
relative to the beginning of the entire array, not indices for the
dimension being sorted.  Thus, @kbd{x(sort(x))} is the array @kbd{x}
sorted so that the elements along its first dimension are in ascending
order.  In order to sort along another dimension, pass @kbd{sort} a
second argument -- @kbd{x(sort(x,2))} will be @kbd{x} sorted into
increasing order along its second dimension, @kbd{x(sort(x,3))} along
its third dimension, and so on.@refill

A related function is @kbd{median}.  It takes one or two arguments, just
like @kbd{sort}, but its result -- which is, of course, the median
values along the dimension being sorted -- has one fewer dimension than
its input.@refill



@node    Transposing, Broadcasting, Sorting, Arrays
@section Transposing

In a carefully designed Yorick program, array dimensions usually wind up
where you need them.  However, you may occasionally wind up with a
five-by-seven array, instead of the seven-by-five array you wanted.
Yorick has a very general @kbd{transpose} function:

@example
x623451= transpose(x123456);
x561234= transpose(x123456, 3);
x345612= transpose(x123456, 5);
x153426= transpose(x123456, [2,5]);
x145326= transpose(x123456, [2,5,3,4]);
x653124= transpose(x123456, [2,5], [1,4,6]);
@end example

Here, @kbd{x123456} represents a six-dimensional array (hopefully these
will be rare).  The same array with its first and last dimensions
transposed is called @kbd{x623451}; this is the default result of
@kbd{transpose}.  The @kbd{transpose} function can take any number of
additional arguments to describe an arbitrary permutation of the indices
of its first argument -- the array to be transposed.@refill

A scalar integer value, as in the second and third lines, represents a
cyclic permutaion of all the dimensions; the first dimension of the
input becomes the Nth dimension of the result, for an argument value of
N.

An array of integer values represents a cyclic permutation of the
specified dimensions.  Hence, in the fifth example, @kbd{[2,5,3,4]}
means that the second dimension becomes the fifth, the fifth becomes the
third, the third becomes the fourth, and the fourth becomes the second.
An arbitrary permutation may be built up of a number of cyclic
permutations, as shown in the sixth example.@refill

One additional problem can arise in Yorick -- you may not know how many
dimensions the array to be transposed has.  In order to deal with this
possibility, either a scalar argument or any of the numbers in a cyclic
permutation list may be zero or negative to count from the last
dimension.  That is, 0 represents the last dimension, -1 the next to
last, -2 the one before that, and so on.

Typical transposing tasks are: (1) Move the first dimension to be last,
and all the others back one cyclically.  (2) Move the last dimension
first, and all the others forward one cyclically.  (3) Transpose the
first two dimensions, leaving all others fixed.  (4) Transpose the final
two dimensions, leaving all others fixed.  These would be accomplished,
in order, by the following four lines:

@example
x234561= transpose(x123456, 0);
x612345= transpose(x123456, 2);
x213456= transpose(x123456, [1,2]);
x123465= transpose(x123456, [0,-1]);
@end example



@node    Broadcasting, Dimension Lists, Transposing, Arrays
@section Broadcasting and conformability

Two arrays need not have identical shape in order for a binary operation
between them to make perfect sense:

@example
y= a*x^3 + b*x^2 + c*x + d;
@end example

The obvious intent of this assignment statement is that @kbd{y} should
have the same shape as @kbd{x}, each value of @kbd{y} being the value of
the polynomial at the corresponding @kbd{y}.@refill

Alternatively, array valued coefficients @kbd{a}, @kbd{b}, ...,
represent an array of several polynomials -- perhaps Legendre
polynomials.  Then, if @kbd{x} is a scalar value, the meaning is again
obvious; @kbd{y} should have the same shape as the coefficient arrays,
each @kbd{y} being the value of the corresponding polynomial.@refill

A binary operation is performed once for each element, so that
@kbd{a+b}, say, means@refill

@example
a(i,j,k,l) + b(i,j,k,l)
@end example

for every @kbd{i, j, k, l} (taking @kbd{a} and @kbd{b} to be four
dimensional).  The lengths of corresponding indices must match in order
for this procedure to make sense; Yorick signals a ``conformability
error'' when the shapes of binary operands do not match.@refill

However, if @kbd{a} had only three dimensions, @kbd{a+b} still makes
sense as:@refill

@example
a(i,j,k) + b(i,j,k,l)
@end example

This sense extends to two dimensional, one dimensional, and finally
to scalar @kbd{a}:

@example
a + b(i,j,k,l)
@end example

which is how Yorick interpreted the monomial @kbd{x^3} in the first
example of this section.  The shapes of @kbd{a} and @kbd{b} are
conformable as long as the dimensions which they have in common all
have the same lengths; the shorter operand simply repeats its values
for every index of a dimension it doesn't have.  This repitition is
called ``broadcasting''.

Broadcasting is the key to Yorick's array syntax.  In practical
situations, it is just as likely for the @kbd{a} array to be missing the
second (@kbd{j}) dimension of the @kbd{b} array as its last (@kbd{l})
dimension.  To handle this case, Yorick will broadcast any unit-length
dimension in addition to a missing final dimension.  Hence, if the
@kbd{a} array has a second dimension of length one, @kbd{a+b}
means:@refill

@example
a(i,1,k,l) + b(i,j,k,l)
@end example

for every @kbd{i, j, k, l}.  The pseudo-index can be used to generate
such unit length indices when necessary (@pxref{Pseudo-Index}).@refill



@node    Dimension Lists,  , Broadcasting, Arrays
@section Dimension Lists

You should strive to write Yorick programs in such a way that you never
need to refer to the lengths of array dimensions.  Array dimensions are
usually of no direct significance in a calculation; your programs will
tend to be clearer if only the arrays themselves appear.

In practice, unfortunately, you can't always get by without mentioning
dimension lengths.  Two functions are important:

@table @kbd
@item numberof(x)
returns the total number of items in the array @kbd{x}.

@item dimsof(x)
returns a list consisting of the number of dimensions of the array @kbd{x},
followed by the length of each of those dimensions.  Thus, if @kbd{x} were
a nine-by-two-by-six array, @kbd{dimsof(x)} would return @kbd{[3,9,2,6]},
while if @kbd{x} were a scalar value, @kbd{dimsof(x)} would return
@kbd{[0]}.@refill

@item dimsof(x, y, z, ...)
With multiple arguments, the @kbd{dimsof} function returns the dimension
list of the array @kbd{x+y+z+...}, or @kbd{[]} if the input arrays are not
conformable.@refill
@end table

The @kbd{array} function (@pxref{Creating Arrays}), and the more arcane
functions @kbd{add_variable}, @kbd{add_member}, and @kbd{reshape} all
have parameter lists ending with one or more ``dimension list''
parameters.  Each parameter in a dimension list can be either a scalar
integer value, representing the length of a single dimension, or a
list of integers in the format returned by @kbd{dimsof} to represent
zero or more dimensions.  Several arguments can be used to build up
a complicated dimension list:@refill

@example
x1= array(0.0, 9, 2, 6);     /* 9-by-2-by-6 array of 0.0 */
x2= array(0.0, [3,9,2,6]);  /* another 9-by-2-by-6 array */
x3= array(0.0, 9, [0], [2,2,6]);   /* ...and yet another */

flux= array(0.0, 3, dimsof(z), numberof(groups));
@end example

In the final example, the @kbd{flux} might represent the three
components of a flux vector, at each of a number of positions @kbd{z},
and for each of a number of photon energies @kbd{groups}.  The first
dimension of @kbd{flux} has length three, corresponding to the three
components of each flux vector.  The last dimension has the same length
as the @kbd{groups} array.  In between are zero or more dimensions --
whatever the dimensions of the array of positions @kbd{z}.

By using the rubber index syntax (@pxref{Rubber-Index}), you can extract
meaningful slices of the @kbd{flux} array without ever needing to know
how many dimensions @kbd{z} had, let alone their lengths.




@comment -----------------------------------------------------------------

@node Embedding, Concept Index, Arrays, Top
@chapter Embedding Compiled Routines Inside Yorick

(Very preliminary notes.  Not heavily tested either.  See the
distribution Drat and MathC, and Math directories for examples.)

You can create a custom version of Yorick containing your own C or
Fortran compiled code.  If you are careful, your custom version will be
easily portable to any site where Yorick has been installed.  You will
considerably ease portability problems (read ``future hassles for
yourself'') by writing in C, which is a portable language, as opposed to
Fortran, which is not.

If you do choose Fortran, stick to a strict subset of ANSI Fortran 77,
in which you do not attempt to pass character variables into or out of
interface routines, nor put them in common blocks.  Also, try not to
use common blocks to pass inputs to or receive outputs from your
interface routines.

Whether you write in Fortran or C, @emph{do not} attempt to do I/O of
any sort in your compiled code.  The whole idea of embedding routines
inside Yorick is to let Yorick handle all I/O -- text and graphics.

In order to build a custom Yorick, you need to find the Yorick home
directory @file{Y_HOME} on the platform where you will be compiling.
You may need to ask whoever installed Yorick where this is.  If Yorick
was installed as recommended, the home directory will be the
@file{yorhome} sibling of the @file{bin} directory from which Yorick was
launched.  The name of Yorick's launch directory is contained in the
@kbd{Y_LAUNCH} variable; start Yorick on the machine where you will be
compiling and type @kbd{Y_LAUNCH} to print this name.@refill

Make a directory in which to build your custom version of Yorick, and
put your C and/or Fortran source files there.  Copy @file{Y_HOME/Maketmpl}
into that directory, change its name to "Makefile", and modify its first
section to tell make how to compile your source code.

You next need to write a Yorick include file which will be loaded
whenever your custom Yorick starts.  This file is read not only by
Yorick when it starts, but also by the Codger automatic wrapper code
generator when you make the custom version.  Codger generates a table of
all of the compiled objects (functions, global variables, or Fortran
common blocks) which can be referenced from the interpreter.  It will
also generate wrapper code to call your compiled functions, if you
decide not to do this yourself.  In this include file:

@example
extern my_func;
/* DOCUMENT my_func(input)
     returns the frobnostication of the array INPUT.
 */
@end example

connects @kbd{my_func} to a compiled function @kbd{Y_my_func} of type
BuiltIn, which you are responsible for writing.  See
@file{Y_HOME/ydata.h} for the definition of the BuiltIn function type.
This function must pop its arguments off of Yorick's interpreter stack
using routines declared in @file{Y_HOME/ydata.h}, and push its result
back onto the stack.  If you want codger to generate @file{Y_my_func}
for you automatically, do this instead:@refill

@example
func my_func(input)
/* DOCUMENT my_func(input)
     returns the frobnostication of the array INPUT.
 */
@{
  return my_func_raw(input, numberof(input));
@}
extern my_func_raw;
/* PROTOTYPE
   double my_func_C_name(double array input, long length)
 */
@end example

This generates a wrapper for a C function which takes a single array as
input and returns a scalar result.  If the function had been Fortran,
it would have looked like this (Fortran passes all arguments by reference
-- that is, as if they were arrays):

@example
func my_func(input)
/* DOCUMENT my_func(input)
     returns the frobnostication of the array INPUT.
 */
@{
  return my_func_raw(input, numberof(input));
@}
extern my_func_raw;
/* PROTOTYPE FORTRAN
   double my_func_Fortran_name(double array input, long array length)
 */
@end example

Legal data types for the function return result in the @kbd{PROTOTYPE}
comment are: void (i.e.- a subroutine), char, short, int, long, float,
or double.

Legal data types for the function parameters in the @kbd{PROTOTYPE}
comment are: void (only if there are no other parameters), char, short,
int, long, float, double, string (char *, guaranteed 0-terminated), or
pointer (void *).  These may be followed by the word "array", which
becomes "*" in the C source code, to indicate an array of that type.
The parameter name is optional.

The @kbd{DOCUMENT} comment should start with @kbd{/* DOCUMENT}.  They
will be returned by the interpreted command @kbd{help, my_func}, and be
included in the poor- man's document produced by Yorick's "mkdoc"
command (see @file{Y_HOME/include/mkdoc.i}).

@example
extern my_global;
reshape, my_global, datatype;
@end example

attaches the interpreted variable @kbd{my_global} to a C-compiled global of
the same name, which has the data type @kbd{datatype} (this must have been
declared in a previous struct or be one of the primitive types).  If you
want @kbd{my_global} to be attached to a global variable of a different
name, use:

@example
extern my_global;
/* EXTERNAL my_global_C_name */
reshape, my_global, datatype;
@end example

To attach to a Fortran common block, say

@example
	double var1, var2, var3
	common /my_common/ var1, var2, var3
	save /my_common/
@end example

(note that this doesn't make sense unless the common block is saved outside
the scope of the functions in which it is used) use:

@example
struct my_common_type @{ double var1, var2, var3; @}
extern my_common;
/* EXTERNAL FORTRAN my_common */
reshape, my_common, my_common_type;
@end example

If you mix double, integer, and real data in a single common block, you
can ensure that you won't have any alignment difficulties by putting
all the doubles first, followed by integers and reals.  If you don't do
this, you're relying on the existence of a Fortran compiler switch which
forces proper data alignment -- some machine someday won't have this.

If you've done it right, to port your code to another machine, you just
move your source directory, change @kbd{Y_HOME} in the Makefile to point
to the public Yorick directory on the new machine, type "make Makefile"
to stuff the correct compiler options into the second part of the
Makefile (the part you didn't write), then type "make" to build your code
on the new machine.

@comment -----------------------------------------------------------------

@node    Concept Index,  , Embedding, Top
@unnumbered Concept Index

@printindex cp

@contents
@bye
