#
NArray: Manipulating multidimensional data in Tcl

NArray is an extension to help Tcl cope with large in-memory numeric
arrays. NArray's require only a few more bytes than the storage
required by the array. In addition to providing array referencing
and setting, narray allows functions to be mapped over each element
of the array. These functions are compiled into byte code for
performance about 100x faster than straight tcl and only 5-10x slower
than C. (These numbers are ball-park figures, actual results depend
on the situation.)

### NARRAY LAYOUT AND INDEXES

An narray is stored in memory as a vector of NArrayFloat's (usually
float's -- see narray.h). Storage is "C" style, such that an index
into an narray *index0 ?index1 ...?* references the *?indexN
+ dimN * ( indexN-1 + dimN-1 (...index1 + dim1? * index0)...)*
element. Each indexN can be greater than *dimN* or
even negative, as long as the sum *?indexN + dimN * ( indexN-1 + dimN-1
(...index1 + dim1? * index0)...)* is within the bounds of the vector.
In addition, there may be fewer indexes than dimensions.
### NARRAY INVOCATION

The NArray package can be loaded into Tcl or Wish via the
native package facility:
package require narray

### NARRAY CREATION

Narray's can be created with the following command:
**narray create** * arrayName dim0 ?dim1 ...?*

Creates a command *arrayName* that represent a multi-
dimensional array with dimensions of length * dim0
?dim1 ...?*. Returns *arrayName*.
### NARRAY COMMAND

The narray command creates a new Tcl command whose name is
the same as the name of the narray. This command may be
used to invoke various operations on the narray. It has
the following general form:
*arrayName option ?arg arg ...?*
The following commands are possible for narray's:
*arrayName* **aref** *index0 ?index1 ...?*
Return the element at *index0 ?index1 ...?*.
*arrayName* **aset** *index0 ?index1 ...? value*
Set the element at *index0 ?index1 ...?* to *value*.
*arrayName* **vref** *variable*
Return the value of the variable *variable*.
*arrayName* **vset** *variable value*
Set the variable *variable* to *value*.
*arrayName* **vars**
Return a list of variables in *arrayName*.
*arrayName* **map** *code ?{array_var0 array0} ...?*
Compile code and apply it to each element of *arrayName*.
Make the narray *array0* available to code as
*array_var0*.
*arrayName* **dimensions**
Return the dimensions of *arrayName*.
*arrayName* **collapse** *direction result*
Sum over all elements in the indicated direction,
saving the result to the narray result.
*arrayName* **export** *offset size result*
Extract a subset of *arrayName* of the specified size
and at the specified offset indices into the narray
*result*.
*arrayName* **import** *offset source*
Import the contents of the narray source into
*arrayName* at the specified offset indices.
*arrayName* **status**
Return some status information about *arrayName*
(currently, the kilobytes used by the narray and
its debug status.)
*arrayName* **debug** *level*
Set the debug flags of *arrayName* to level. The
debug flags are a bitwise OR of:
1 Print parsing information

2 Trace stack machine execution

4 Print compiled code before executing it

### NARRAY LANGUAGE

The *arrayName* **map** command compiles and applies a sequence
of code to each element in a narray. Statements in the language
are seperated by semi-colons or by newlines. The narray language
includes standard math (including **+=, -=, *=, /=** and **?:**).
**=** is used for assignment. The following forms may appear on the
left hand side of an assigment:
*var*
The variable *var*. Variables may contain numeric values only.
**[**?*index0, index1, ...*?**]**
The current element, modified by *index0, index1, ...*
For example, **[]** is the current element,
**[-1]** is the previous element, and **[0,1]** is
the element in the same row but next column in a 2D matrix.
*array_var*[?*index0, index1, ...?***]**
Accesses elements of the narray *array_var*.
The value of variables and array elements may be referenced by
prefixing a **$** to them. For example, **$foo** is the value of
the variable **foo**. In addtion **@***N* may be used to
reference the value of the *N*'th index of the current element.
For example, **@0** is the row number and **@1** is the column
number (for a 2D matrix.)
Functions may be called as *func***(**?*arg0, ...*?**)**
Strings enclosed by "e;'s may be passed to functions. The following
functions are available:

**sin(***x*)
The sine of *x*.
**cos(***x*)
The cosine of *x*.
**tan(***x*)
The tangent of *x*.
**asin(***x*)
The arc sine of *x*.
**acos(***x*)
The arc cosine of *x*.
**atan(***x*)
The arg tangent of *x*.
**sinh(***x*)
The hyperbolic sine of *x*.
**cosh(***x*)
The hyperbolic cosine of *x*.
**tanh(***x*)
The hyperbolic tangent of *x*.
**exp(***x*)
**e** ^ *x*.
**log(***x*)
The natural log of *x*.
**log10(***x*)
The base 10 log of *x*.
**sqrt(***x*)
The square root of *x*.
**ceil(***x*)
The smallest integral value not less than *x*.
**floor(***x*)
The largest integral value not greater than *x*.
**atan2(***x, y*)
The arc tangent function of two variables.
**pow(***x, y*)
*x* raised to the *y* power.
**fmod(***x, y*)
The floating-point remainder of *x* / *y*.
**printf(***format_string, ?arg?, ...*)
A limited form of printf that understands the d, f, g, and s formats.
**fprintf(***file_number, format_string, ?arg?, ...*)
Like **printf**, but output goes to the file handle identified by
*file_number*. Tcl's file handles are of the form
**file***file_number*.
**tcl_eval(***string, ?arg?, ...***)**
Concatenate *string* and
any arguments (numeric arguments are converted to strings and preceded
by a space) and evaluate in Tcl in the current context.
### VARIABLES

The following variables are set by this extension:
narray_library
The location of the Tcl library. This can be over-
ridden by the environment variable NARRAY_LIBRARY.
narray_version
The version number of the narray extension, in the
form *major.minor*.
### LIBRARY COMMANDS

The file *narray.tcl* contains these useful library routines:
**pnarray** *arrayName*
Print the narray arrayName.
**narray_delete** *arrayName*
Delete the narray arrayName. This is the same as
rename arrayName {}.
Here's an example:
% package require narray ;# load narray package
0.81
% narray create cube 64 64 64 ;# cube is an 64x64x64 float array
cube
% cube status ;# 64x64x64 * sizeof(float) = 1MB
1024.12KB used, debug 0
% cube aref 0 0 0 ;# return the element (0,0,0)
0
% cube aset 0 0 0 10 ;# set (0,0,0) to 10
10
% cube map { [] += 5; } ;# add 5 to each element
% cube aref 0 0 0 ;# (0,0,0) is now 15
15
% cube vset sum 0 ;# set the variable sum to 0
0
% cube map { sum += $[]; } ;# sum the elements
% cube vref sum ;# get the value of the variable sum
1.31073e+06 ;# the sum of the elements is 1310730
% expr 64*64*64*5+10 ;# just checking...
1310730

### OBTAINING NARRAY

The narray extension can be obtained from the
Neosoft archives or via
anonymous ftp
from our site.
### HISTORY

The narray extension was originally written circa 1994 by Sam Shen at
Lawrence Berkeley Laboratories. It was then adopted by
Nick Maliszewskyj <nickm@nist.gov>
and Przemek Klosowski
<przemek@nist.gov>
at the National Institute of Standards and Technology.
Please contact Nick or Przemek if you have questions,
modifications, bug reports, or fixes.
Last modified 1-Sep-1998.