<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<TITLE> A Guide to the S-Lang Language: Arrays</TITLE>
<LINK HREF="slang-12.html" REL=next>
<LINK HREF="slang-10.html" REL=previous>
<LINK HREF="slang.html#toc11" REL=contents>
</HEAD>
<BODY>
<A HREF="slang-12.html">Next</A>
<A HREF="slang-10.html">Previous</A>
<A HREF="slang.html#toc11">Contents</A>
<HR>
<H2><A NAME="s11">11. Arrays</A></H2>

<P> 
<P>An array is a container object that can contain many values of one
data type.  Arrays are very useful objects and are indispensable
for certain types of programming.  The purpose of this chapter is
to describe how arrays are defined and used in the <B>S-Lang</B> language.
<P>
<H2><A NAME="ss11.1">11.1 Creating Arrays</A>
</H2>

<P> 
<P>The <B>S-Lang</B> language supports multi-dimensional arrays of all data
types.  Since the <CODE>Array_Type</CODE> is a data type, one can even
have arrays of arrays.  To create a multi-dimensional array of
<EM>SomeType</EM> use the syntax
<BLOCKQUOTE><CODE>
<PRE>
      SomeType [dim0, dim1, ..., dimN]
</PRE>
</CODE></BLOCKQUOTE>

Here <EM>dim0</EM>, <EM>dim1</EM>, ... <EM>dimN</EM> specify the size of
the individual dimensions of the array.  The current implementation
permits arrays consist of up to <CODE>7</CODE> dimensions.  When a
numeric array is created, all its elements are initialized to zero.
The initialization of other array types depend upon the data type,
e.g., <CODE>String_Type</CODE> and <CODE>Struct_Type</CODE> arrays are
initialized to <CODE>NULL</CODE>.
<P>As a concrete example, consider
<BLOCKQUOTE><CODE>
<PRE>
     a = Integer_Type [10];
</PRE>
</CODE></BLOCKQUOTE>

which creates a one-dimensional array of <CODE>10</CODE> integers and
assigns it to <CODE>a</CODE>.
Similarly, 
<BLOCKQUOTE><CODE>
<PRE>
     b = Double_Type [10, 3];
</PRE>
</CODE></BLOCKQUOTE>

creates a <CODE>30</CODE> element array of double precision numbers
arranged in <CODE>10</CODE> rows and <CODE>3</CODE> columns, and assigns it to
<CODE>b</CODE>.
<P>
<H3>Range Arrays</H3>

<P>
<P>There is a more convenient syntax for creating and initializing a
1-d arrays.  For example, to create an array of ten
integers whose elements run from <CODE>1</CODE> through <CODE>10</CODE>, one
may simply use:
<BLOCKQUOTE><CODE>
<PRE>
     a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
</PRE>
</CODE></BLOCKQUOTE>

Similarly, 
<BLOCKQUOTE><CODE>
<PRE>
     b = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
</PRE>
</CODE></BLOCKQUOTE>

specifies an array of ten doubles.  
<P>An even more compact way of specifying a numeric array is to use a
<EM>range-array</EM>.  For example,
<BLOCKQUOTE><CODE>
<PRE>
     a = [0:9];
</PRE>
</CODE></BLOCKQUOTE>

specifies an array of 10 integers whose elements range from <CODE>0</CODE>
through <CODE>9</CODE>.  The most general form of a range array is
<BLOCKQUOTE><CODE>
<PRE>
     [first-value : last-value : increment]
</PRE>
</CODE></BLOCKQUOTE>

where the <EM>increment</EM> is optional and defaults to <CODE>1</CODE>. This
creates an array whose first element is <EM>first-value</EM> and whose
successive values differ by <EM>increment</EM>.  <EM>last-value</EM> sets
an upper limit upon the last value of the array as described below.
<P>If the range array <CODE>[a:b:c]</CODE> is integer valued, then the
interval specified by <CODE>a</CODE> and <CODE>b</CODE> is closed.  That is, the
kth element of the array x_k is given by x_k=a+ck and
must satisfy a&lt;=x_k&lt;=b.  Hence, the number of elements in an
integer range array is given by the expression 1 + (b-a)/c.
<P>The situation is somewhat more complicated for floating point range
arrays.  The interval specified by a floating point range array
<CODE>[a:b:c]</CODE> is semi-open such that <CODE>b</CODE> is not contained in
the interval.  In particular, the kth element of <CODE>[a:b:c]</CODE> is
given by x_k=a+kc such that a&lt;=x_k&lt;b when
c&gt;=0, and b&lt;x_k&lt;=a otherwise.  The number of elements
in the array is one greater than the largest k that
satisfies the open interval constraint.
<P>Here are a few examples that illustrate the above comments:
<BLOCKQUOTE><CODE>
<PRE>
       [1:5:1]         ==&gt; [1,2,3,4,5]
       [1.0:5.0:1.0]   ==&gt; [1.0, 2.0, 3.0, 4.0]
       [5:1:-1]        ==&gt; [5,4,3,2,1]
       [5.0:1.0:-1.0]  ==&gt; [5.0, 4.0, 3.0, 2.0];
       [1:1]           ==&gt; [1]
       [1.0:1.0]       ==&gt; []
       [1:-3]          ==&gt; []
</PRE>
</CODE></BLOCKQUOTE>
<P>
<H3>Creating arrays via the dereference operator</H3>

<P>
<P>Another way to create an array is apply the dereference operator
<CODE>@</CODE> to the <CODE>DataType_Type</CODE> literal <CODE>Array_Type</CODE>.  The
actual syntax for this operation resembles a function call
<BLOCKQUOTE><CODE>
variable a = @Array_Type (<EM>data-type</EM>, <EM>integer-array</EM>);
</CODE></BLOCKQUOTE>

where <EM>data-type</EM> is of type <CODE>DataType_Type</CODE> and
<EM>integer-array</EM> is a 1-d array of integers that specify the size
of each dimension.  For example,
<BLOCKQUOTE><CODE>
<PRE>
     variable a = @Array_Type (Double_Type, [10, 20]);
</PRE>
</CODE></BLOCKQUOTE>

will create a <CODE>10</CODE> by <CODE>20</CODE> array of doubles and assign it
to <CODE>a</CODE>.  This method of creating arrays derives its power from
the fact that it is more flexible than the methods discussed in this
section.  We shall encounter it again in section ??? in the context
of the <CODE>array_info</CODE> function.
<P>
<P>
<H2><A NAME="ss11.2">11.2 Reshaping Arrays</A>
</H2>

<P> 
It is sometimes possible to change the `shape' of an array using
the <CODE>reshape</CODE> function.  For example, a 1-d 10 element array
may be reshaped into a 2-d array consisting of 5 rows and 2
columns.  The only restriction on the operation is that the arrays
must be commensurate.  The <CODE>reshape</CODE> function follows the
syntax
<BLOCKQUOTE><CODE>
reshape (<EM>array-name</EM>, <EM>integer-array</EM>);
</CODE></BLOCKQUOTE>

where <EM>array-name</EM> specifies the array to be reshaped to have
the dimensions given by <CODE>integer-array</CODE>, a 1-dimensional array of
integers.  It is important to note that this does <EM>not</EM> create a
new array, it simply reshapes the existing array.  Thus,
<BLOCKQUOTE><CODE>
<PRE>
       variable a = Double_Type [100];
       reshape (a, [10, 10]);
</PRE>
</CODE></BLOCKQUOTE>

turns <CODE>a</CODE> into a <CODE>10</CODE> by <CODE>10</CODE> array.
<P>
<P>
<H2><A NAME="ss11.3">11.3 Indexing Arrays</A>
</H2>

<P> 
An individual element of an array may be referred to by its
<EM>index</EM>.  For example, <CODE>a[0]</CODE> specifies the zeroth element
of the one dimensional array <CODE>a</CODE>, and <CODE>b[3,2]</CODE> specifies
the element in the third row and second column of the two
dimensional array <CODE>b</CODE>.  As in C array indices are numbered from
<CODE>0</CODE>.  Thus if <CODE>a</CODE> is a one-dimensional array of ten
integers, the last element of the array is given by <CODE>a[9]</CODE>.
Using <CODE>a[10]</CODE> would result in a range error.
<P>A negative index may be used to index from the end of the array,
with <CODE>a[-1]</CODE> referring to the last element of <CODE>a</CODE>,
<CODE>a[-2]</CODE> referring to the next to the last element, and so on.
<P>One may use the indexed value like any other variable.  For
example, to set the third element of an integer array to <CODE>6</CODE>, use
<BLOCKQUOTE><CODE>
<PRE>
     a[2] = 6;
</PRE>
</CODE></BLOCKQUOTE>

Similarly, that element may be used in an expression, such as
<BLOCKQUOTE><CODE>
<PRE>
     y = a[2] + 7;
</PRE>
</CODE></BLOCKQUOTE>

Unlike other <B>S-Lang</B> variables which inherit a type upon assignment,
array elements already have a type.  For example, an attempt to
assign a string value to an element of an integer array will result
in a type-mismatch error.
<P>One may use any integer expression to index an array.  A simple
example that computes the sum of the elements of 10 element 1-d
array is
<BLOCKQUOTE><CODE>
<PRE>
      variable i, sum;
      sum = 0;
      for (i = 0; i &lt; 10; i++) sum += a[i];
</PRE>
</CODE></BLOCKQUOTE>
<P>Unlike many other languages, <B>S-Lang</B> permits arrays to be indexed by
other integer arrays.   Suppose that <CODE>a</CODE> is a 1-d array of 10
doubles.  Now consider:
<BLOCKQUOTE><CODE>
<PRE>
      i = [6:8];
      b = a[i];
</PRE>
</CODE></BLOCKQUOTE>

Here, <CODE>i</CODE> is a 1-dimensional range array of three integers with
<CODE>i[0]</CODE> equal to <CODE>6</CODE>, <CODE>i[1]</CODE> equal to <CODE>7</CODE>,
and <CODE>i[2]</CODE> equal to <CODE>8</CODE>.  The statement <CODE>b = a[i];</CODE>
will create a 1-d array of three doubles and assign it to <CODE>b</CODE>.
The zeroth element of <CODE>b</CODE>, <CODE>b[0]</CODE> will be set to the sixth
element of <CODE>a</CODE>, or <CODE>a[6]</CODE>, and so on.  In fact, these two simple
statements are equivalent to
<BLOCKQUOTE><CODE>
<PRE>
     b = Double_Type [3];
     b[0] = a[6];
     b[1] = a[7];
     b[2] = a[8];
</PRE>
</CODE></BLOCKQUOTE>

except that using an array of indices is not only much more
convenient, but executes much faster.
<P>More generally, one may use an index array to specify which
elements are to participate in a calculation.  For example, consider
<BLOCKQUOTE><CODE>
<PRE>
     a = Double_Type [1000];
     i = [0:499];
     j = [500:999];
     a[i] = -1.0;
     a[j] = 1.0;
</PRE>
</CODE></BLOCKQUOTE>

This creates an array of <CODE>1000</CODE> doubles and sets the first
<CODE>500</CODE> elements to <CODE>-1.0</CODE> and the last <CODE>500</CODE> to
<CODE>1.0</CODE>.  Actually, one may do away with the <CODE>i</CODE> and <CODE>j</CODE>
variables altogether and use
<BLOCKQUOTE><CODE>
<PRE>
     a = Double_Type [1000];
     a [[0:499]] = -1.0;
     a [[500:999]] = 1.0;
</PRE>
</CODE></BLOCKQUOTE>

It is important to understand the syntax used and, in particular,
to note that <CODE>a[[0:499]]</CODE> is <EM>not</EM> the same as
<CODE>a[0:499]</CODE>.  In fact, the latter will generate a syntax error.
<P>Often, it is convenient to use a <EM>rubber</EM> range to specify
indices.  For example, <CODE>a[[500:]]</CODE> specifies all elements of
<CODE>a</CODE> whose index is greater than or equal to <CODE>500</CODE>.  Similarly,
<CODE>a[[:499]]</CODE> specifies the first 500 elements of <CODE>a</CODE>.
Finally, <CODE>a[[:]]</CODE> specifies all the elements of <CODE>a</CODE>;
however, using <CODE>a[*]</CODE> is more convenient.
<P>Now consider a multi-dimensional array.  For simplicity, suppose
that <CODE>a</CODE> is a <CODE>100</CODE> by <CODE>100</CODE> array of doubles.  Then
the expression <CODE>a[0, *]</CODE> specifies all elements in the zeroth
row.  Similarly, <CODE>a[*, 7]</CODE> specifies all elements in the
seventh column.  Finally, <CODE>a[[3:5][6:12]]</CODE> specifies the
<CODE>3</CODE> by <CODE>7</CODE> region consisting of rows <CODE>3</CODE>, <CODE>4</CODE>,
and <CODE>5</CODE>, and columns <CODE>6</CODE> through <CODE>12</CODE> of <CODE>a</CODE>.
<P>We conclude this section with a few examples.
<P>Here is a function that computes the trace (sum of the diagonal
elements) of a square 2 dimensional <CODE>n</CODE> by <CODE>n</CODE> array:
<BLOCKQUOTE><CODE>
<PRE>
      define array_trace (a, n)
      {
         variable sum = 0, i;
         for (i = 0; i &lt; n; i++) sum += a[i, i];
         return sum;
      }
</PRE>
</CODE></BLOCKQUOTE>

This fragment creates a <CODE>10</CODE> by <CODE>10</CODE> integer array, sets
its diagonal elements to <CODE>5</CODE>, and then computes the trace of
the array: 
<BLOCKQUOTE><CODE>
<PRE>
      a = Integer_Type [10, 10];
      for (j = 0; j &lt; 10; j++) a[j, j] = 5;
      the_trace = array_trace(a, 10);
</PRE>
</CODE></BLOCKQUOTE>

We can get rid of the <CODE>for</CODE> loop as follows:
<BLOCKQUOTE><CODE>
<PRE>
      j = Integer_Type [10, 2];
      j[*,0] = [0:9];
      j[*,1] = [0:9];
      a[j] = 5;
</PRE>
</CODE></BLOCKQUOTE>

Here, the goal was to construct a 2-d array of indices that
correspond to the diagonal elements of <CODE>a</CODE>, and then use that
array to index <CODE>a</CODE>.  To understand how
this works, consider the middle statements.  They are equivalent
to the following <CODE>for</CODE> loops:
<BLOCKQUOTE><CODE>
<PRE>
      variable i;
      for (i = 0; i &lt; 10; i++) j[i, 0] = i;
      for (i = 0; i &lt; 10; i++) j[i, 1] = i;
</PRE>
</CODE></BLOCKQUOTE>

Thus, row <CODE>n</CODE> of <CODE>j</CODE> will have the value <CODE>(n,n)</CODE>,
which is precisely what was sought.
<P>Another example of this technique is the function:
<BLOCKQUOTE><CODE>
<PRE>
      define unit_matrix (n)
      {
         variable a = Integer_Type [n, n];
         variable j = Integer_Type [n, 2];
         j[*,0] = [0:n - 1];
         j[*,1] = [0:n - 1];
         
         a[j] = 1;
         return a;
      }
</PRE>
</CODE></BLOCKQUOTE>

This function creates an <CODE>n</CODE> by <CODE>n</CODE> unit matrix,
that is a 2-d <CODE>n</CODE> by <CODE>n</CODE> array whose elements are all zero
except on the diagonal where they have a value of <CODE>1</CODE>.
<P>
<P>
<P>
<H2><A NAME="ss11.4">11.4 Arrays and Variables</A>
</H2>

<P>
<P>When an array is created and assigned to a variable, the
interpreter allocates the proper amount of space for the array,
initializes it, and then assigns to the variable a <EM>reference</EM>
to the array.   So, a variable that represents an array has a value
that is really a reference to the array.  This has several
consequences, some good and some bad.  It is believed that the
advantages of this representation outweigh the disadvantages.
First, we shall look at the positive aspects.
<P>When a variable is passed to a function, it is always the value of
the variable that gets passed.  Since the value of a variable
representing an array is a reference, a reference to the array gets
passed.  One major advantage of this is rather obvious: it is a
fast and efficient way to pass the array.  This also has another
consequence that is illustrated by the function
<BLOCKQUOTE><CODE>
<PRE>
      define init_array (a, n)
      {
         variable i;
         
         for (i = 0; i &lt; n; i++) a[i] = some_function (i);
      }
</PRE>
</CODE></BLOCKQUOTE>

where <CODE>some_function</CODE> is a function that generates a scalar
value to initialize the <EM>ith</EM> element.  This function can be
used in the following way:
<BLOCKQUOTE><CODE>
<PRE>
      variable X = Double_Type [100000];
      init_array (X, 100000);
</PRE>
</CODE></BLOCKQUOTE>

Since the array is passed to the function by reference, there is no
need to make a separate copy of the <CODE>100000</CODE> element array. As
pointed out above, this saves both execution time and memory. The
other salient feature to note is that any changes made to the
elements of the array within the function will be manifested in the
array outside the function.  Of course, in this case, this is a
desirable side-effect.
<P>To see the downside of this representation, consider:
<BLOCKQUOTE><CODE>
<PRE>
      variable a, b;
      a = Double_Type [10];
      b = a;
      a[0] = 7;
</PRE>
</CODE></BLOCKQUOTE>

What will be the value of <CODE>b[0]</CODE>?  Since the value of <CODE>a</CODE>
is really a reference to the array of ten doubles, and that
reference was assigned to <CODE>b</CODE>, <CODE>b</CODE> also refers to the same
array.  Thus any changes made to the elements of <CODE>a</CODE>, will also
be made implicitly to <CODE>b</CODE>.
<P>This begs the question: If the assignment of one variable which
represents an array, to another variable results in the assignment
of a reference to the array, then how does one make separate copies
of the array?  There are several answers including using an index
array, e.g., <CODE>b = a[*]</CODE>; however, the most natural method is
to use the dereference operator:
<BLOCKQUOTE><CODE>
<PRE>
      variable a, b;
      a = Double_Type [10];
      b = @a;
      a[0] = 7;
</PRE>
</CODE></BLOCKQUOTE>

In this example, a separate copy of <CODE>a</CODE> will be created and
assigned to <CODE>b</CODE>.  It is very important to note that <B>S-Lang</B>
never implicitly dereferences an object.  So, one must explicitly use
the dereference operator.  This means that the elements of a
dereferenced array are not themselves dereferenced.  For example,
consider dereferencing an array of arrays, e.g.,
<BLOCKQUOTE><CODE>
<PRE>
      variable a, b;
      a = Array_Type [2];  
      a[0] = Double_Type [10];
      a[1] = Double_Type [10];
      b = @a;
</PRE>
</CODE></BLOCKQUOTE>

In this example, <CODE>b[0]</CODE> will be a reference to the array that
<CODE>a[0]</CODE> references because <CODE>a[0]</CODE> was not explicitly
dereferenced.
<P>
<H2><A NAME="ss11.5">11.5 Using Arrays in Computations</A>
</H2>

<P> 
<P>Many functions and operations work transparently with arrays.
For example, if <CODE>a</CODE> and <CODE>b</CODE> are arrays, then the sum
<CODE>a + b</CODE> is an array whose elements are formed from the sum of
the corresponding elements of <CODE>a</CODE> and <CODE>b</CODE>.  A similar
statement holds for all other binary and unary operations.
<P>Let's consider a simple example.  Suppose, that we wish to solve a
set of <CODE>n</CODE> quadratic equations whose coefficients are given by
the 1-d arrays <CODE>a</CODE>, <CODE>b</CODE>, and <CODE>c</CODE>.  In general, the
solution of a quadratic equation will be two complex numbers.  For
simplicity, suppose that all we really want is to know what subset of
the coefficients, <CODE>a</CODE>, <CODE>b</CODE>, <CODE>c</CODE>, correspond to
real-valued solutions.  In terms of <CODE>for</CODE> loops, we can write:
<BLOCKQUOTE><CODE>
<PRE>
     variable i, d, index_array;
     index_array = Integer_Type [n];
     for (i = 0; i &lt; n; i++)
       {
          d = b[i]^2 - 4 * a[i] * c[i];
          index_array [i] = (d &gt;= 0.0);
       }
</PRE>
</CODE></BLOCKQUOTE>

In this example, the array <CODE>index_array</CODE> will contain a
non-zero value if the corresponding set of coefficients has a
real-valued solution.  This code may be written much more compactly
and with more clarity as follows:
<BLOCKQUOTE><CODE>
<PRE>
     variable index_array = ((b^2 - 4 * a * c) &gt;= 0.0);
</PRE>
</CODE></BLOCKQUOTE>
<P><B>S-Lang</B> has a powerful built-in function called <CODE>where</CODE>.  This
function takes an array of integers and returns a 2-d array of
indices that correspond to where the elements of the input array
are non-zero.  This simple operation is extremely useful. For
example, suppose <CODE>a</CODE> is a 1-d array of <CODE>n</CODE> doubles, and it
is desired to set to zero all elements of the array whose value is
less than zero. One way is to use a <CODE>for</CODE> loop:
<BLOCKQUOTE><CODE>
<PRE>
     for (i = 0; i &lt; n; i++) 
       if (a[i] &lt; 0.0) a[i] = 0.0;
</PRE>
</CODE></BLOCKQUOTE>

If <CODE>n</CODE> is a large number, this statement can take some time to
execute.  The optimal way to achieve the same result is to use the
<CODE>where</CODE> function:
<BLOCKQUOTE><CODE>
<PRE>
     a[where (a &lt; 0.0)] = 0;
</PRE>
</CODE></BLOCKQUOTE>

Here, the expression <CODE>(a &lt; 0.0)</CODE> returns an array whose
dimensions are the same size as <CODE>a</CODE> but whose elements are
either <CODE>1</CODE> or <CODE>0</CODE>, according to whether or not the
corresponding element of <CODE>a</CODE> is less than zero.  This array of
zeros and ones is then passed to <CODE>where</CODE> which returns a 2-d
integer array of indices that indicate where the elements of
<CODE>a</CODE> are less than zero.  Finally, those elements of <CODE>a</CODE> are
set to zero.
<P>As a final example, consider once more the example involving the set of
<CODE>n</CODE> quadratic equations presented above.  Suppose that we wish
to get rid of the coefficients of the previous example that
generated non-real solutions.  Using an explicit <CODE>for</CODE> loop requires
code such as:
<BLOCKQUOTE><CODE>
<PRE>
     variable i, j, nn, tmp_a, tmp_b, tmp_c;
     
     nn = 0;
     for (i = 0; i &lt; n; i++) 
       if (index_array [i]) nn++;
     
     tmp_a = Double_Type [nn];
     tmp_b = Double_Type [nn];
     tmp_c = Double_Type [nn];
     
     j = 0;
     for (i = 0; i &lt; n; i++)
       {
          if (index_array [i]) 
            {
               tmp_a [j] = a[i];
               tmp_b [j] = b[i];
               tmp_c [j] = c[i];
               j++;
            }
       }
     a = tmp_a;
     b = tmp_b;
     c = tmp_c;
</PRE>
</CODE></BLOCKQUOTE>

Not only is this a lot of code, it is also clumsy and error-prone.
Using the <CODE>where</CODE> function, this task is trivial:
<BLOCKQUOTE><CODE>
<PRE>
     variable i;
     i = where (index_array != 0);
     a = a[i];
     b = b[i];
     c = c[i];
</PRE>
</CODE></BLOCKQUOTE>
<P>All the examples up to now assumed that the dimensions of the array
were known.  Although the intrinsic function <CODE>length</CODE> may be
used to get the total number of elements of an array, it cannot be
used to get the individual dimensions of a multi-dimensional array.
However, the function <CODE>array_info</CODE> may be used to
get information about an array, such as its data type and size.
The function returns three values: the data type, the number of
dimensions, and an integer array containing the size
of each dimension.  It may be used to determine the number of rows
of an array as follows:
<BLOCKQUOTE><CODE>
<PRE>
     define num_rows (a)
     {
        variable dims, type, num_dims;
        
        (dims, num_dims, type) = array_info (a);
        return dims[0];
     }  
</PRE>
</CODE></BLOCKQUOTE>

The number of columns may be obtained in a similar manner:
<BLOCKQUOTE><CODE>
<PRE>
     define num_cols (a)
     {
        variable dims, type, num_dims;
        
        (dims, num_dims, type) = array_info (a);
        if (num_dims &gt; 1) return dims[1];
        return 1;
     }     
</PRE>
</CODE></BLOCKQUOTE>
<P>Another use of <CODE>array_info</CODE> is to create an array that has the
same number of dimensions as another array:
<BLOCKQUOTE><CODE>
<PRE>
     define make_int_array (a)
     {
        variable dims, num_dims, type;
        
        (dims, num_dims, type) = array_info (a);
        return @Array_Type (Integer_Type, dims);
     }
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P>
<P>
<HR>
<A HREF="slang-12.html">Next</A>
<A HREF="slang-10.html">Previous</A>
<A HREF="slang.html#toc11">Contents</A>
</BODY>
</HTML>
