Numeric Arrays

An array is a multi-dimensioned structure of variables that are given a common name. The array can have one to six dimensions. Each location in an array contains one value, and each value has the characteristics of a single variable, either REAL, INTEGER or COMPLEX (string arrays are discussed in the chapter, "String Manipulation"). Note that many of the statements that deal with arrays require the MAT binary.

A one-dimensional array consists of n elements, each identified by a single subscript. A two-dimensional array consists of m times n elements where m and n are the maximum number of elements in the two respective dimensions. Arrays require a subscript in each dimension, in order to locate a given element of the array. Arrays are limited to six dimensions, and the subscript range for each dimension must lie between -32767 and 32767. REAL arrays require eight bytes of memory for each element, plus overhead, and COMPLEX arrays require 16 bytes of memory for each element, plus overhead. It is easy to see that large arrays can demand massive memory resources.

An undeclared array is given as many dimensions as it has subscripts in its lowest-numbered occurrence. Each dimension of an undeclared array has an upper bound of ten. Space for these elements is reserved whether you use them or not.
NOTE
For more information about numeric arrays, array operations, matrices, and vectors, refer to HP BASIC Advanced Programming Techniques.

Dimensioning an Array

Before you use an array, you should tell the system how much memory to reserve for it. This is called "dimensioning" an array. You can dimension arrays with the DIM, COM, ALLOCATE, INTEGER, REAL or COMPLEX statements. For example:

 
COMPLEX Array_complex(2,4)
 

An array is a type of variable and as such follows all rules for variable names. Unless you explicitly specify INTEGER or COMPLEX type in the dimensioning statement, arrays default to REAL type. The same array can only be dimensioned once in a context (there is one exception to this rule: If you ALLOCATE an array, and then DEALLOCATE it, you can dimension the array again). However, as we explain later in this section, arrays can be REDIMensioned.

When you dimension an array, the system reserves space in internal memory for it. The system also sets up a table which it uses to locate each element in the array. The location of each element is designated by a unique combination of subscripts, one subscript for each dimension. For a two-dimensional array, for instance, each element is identified by two subscript values. An example of dimensioning a two-dimensional array is as follows:

 
OPTION BASE 0  default numbering of subscripts begins with 0
DIM Array(3,5)  declares elements (0,0) to (3,5)
 
 
OPTION BASE 1 default numbering of subscripts begins with 1
Array(2,3) defines elements (1,1) to (2,3)
 
 
OPTION BASE 0 default numbering of subscripts begins with 0
DIM A(1:4,1:4,1:4) defines elements (1,1,1) to (4,4,4)
 

Each context defaults to an option base of 0 (but arrays appearing in COM statements with an (*) keep their original base. However, you can set the option base to 1 using the OPTION BASE statement. You can have only one OPTION BASE statement in a context, and it must precede all explicit variable declarations.

Some Examples of Arrays

When we discuss two-dimensional arrays, the first dimension will always represent rows, and the second dimension will always represent columns. Note also in the above example that the first two dimensions use the default setting of 1 for the lower bound, while the third dimension explicitly defines 0 as the lower bound. The numbers in parentheses are the subscript values for the particular elements. These are the numbers you use to identify each array element.

The following examples illustrate some of the flexibility you have in dimensioning arrays.

 
10   OPTION BASE 1
20   DIM A(3,4,0:2)
 

Planes of a Three-Dimensional REAL Array

Dimension Size Lower Bound Upper Bound

1st

3

1

3

2nd

4

1

4

3rd

3

0

2

 
10   OPTION BASE 1
20   COM B(1:5,2:6)

Two-Dimensional REAL ARRAY
(1,2) (1,3) (1,4) (1,5) (1,6)
(2,2) (2,3) (2,4) (2,5) (2,6)
(3,2) (3,3) (3,4) (3,5) (3,6)
(4,2) (4,3) (4,4) (4,5) (4,6)
(5,2) (5,3) (5,4) (5,5) (5,6)

The array above has these features:

Dimension Size Lower Bound Upper Bound

1st

5

1

5

2nd

5

2

6

 
10   OPTION BASE 1
20   ALLOCATE INTEGER C(2:4,-2:2)


A Dynamically Allocated, 
Two-Dimensional 
INTEGER Array:
(2,-2) (2,-1) (2,0) (2,1) (2,2)
(3,-2) (3,-1) (3,0) (3,1) (3,2)
(4,-2) (4,-1) (4,0) (4,1) (4,2)

... with these attributes:
Dimension Size Lower Bound Upper Bound

1st

3

2

4

2nd

5

-2

2

NOTE
Throughout this chapter we will be using DIM statements without specifying what the current option base setting is. Unless explicitly specified otherwise, all examples in this chapter use option base 1.

As an example of a four-dimensional array, consider a five-story library. On each floor there are 20 stacks, each stack contains 10 shelves, and each shelf holds 100 books. To specify the location of a particular book you would give the number of the floor, the stack, the shelf, and the particular book on that shelf. We could dimension an array for the library with the statement:

 
DIM Library(5,20,10,100)
 

This means that there are 100,000 book locations. To identify a particular book you would specify its subscripts. For instance, Library(2,12,3,35) would identify the 35th book on the 3rd shelf of the 12th stack on the 2nd floor.

Problems with Implicit Dimensioning

In any context, an array must have a dimensioned size. It may be explicitly dimensioned through COM, INTEGER, REAL, COMPLEX or ALLOCATE. It can also be implicitly dimensioned through a subscripted reference to it in a program statement other than a MAT or a REDIM statement. MAT and REDIM statements cannot be used to implicitly dimension an array.

Finding Out the Dimensions of an Array

There are a number of statements that allow you to determine the size of an array. To find out how many dimensions are in an array, use the RANK function. For example, this program

 
10 OPTION BASE 0
20 DIM F(1,4,-1:2)
30 PRINT RANK (F)
40 END

would print 3.

The SIZE function returns the size (number of elements) of a particular dimension. For instance,

SIZE (F,2)
 

would return 5, the number of elements in F's second dimension.

To find out what the lower bound of a dimension is, use the BASE function. Referring again to array F,

 
BASE (F,1)
 

would return a 0, while,

 
BASE (F,3)
 

would return a -1.

By using the SIZE and BASE functions together, you can determine the upper bounds of any dimension (e.g., SIZE+BASE-1=Upper Bound).

These functions are powerful tools for writing programs that perform functions on an array regardless of the array's size or shape.

Using Individual Array Elements

This section deals with assigning and extracting individual elements from arrays.

Assigning an Individual Array Element

Initially, every element in an array equals zero. There are a number of different ways to change these values. The most obvious is to assign a particular value to each element. This is done by specifying the element's subscripts.

 
A(3,4)=13 the element in row 3, column 4, has the value 13
 

Extracting Single Values From Arrays

As with entering values into arrays, there are a number of ways to extract values as well. To extract the value of a particular element, simply specify the element's subscripts.

 
X=A(3,4,2)
 

BASIC automatically converts variable types. For example, if you assign an element from a COMPLEX array to an INTEGER variable, the system will round the real part and ignore the imaginary part of the COMPLEX number.

Filling Arrays

This section discusses three methods for filling an entire array:

Assigning Every Element in an Array the Same Value

For some applications, you may want to initialize every element in an array to some particular value. You can do this by assigning a value to the array name. However, you must precede the assignment with the MAT keyword.

 
MAT A= (10)

MAT C= (CMPLX(1,2))
 

Note that the numeric expression on the right-hand side of the assignment must be enclosed in parentheses and that this expression may be INTEGER, REAL or COMPLEX.

Using the READ Statement to Fill an Entire Array

You can assign values to an array using READ and DATA. DATA allows you to create a stream of data items, and READ enables you to enter the data stream into an array.


110   DIM A(3,3)
120   DATA -4,36,2.3,5,89,17,-6,-12,42
130   READ A(*)
140   PRINT USING "3(3DD.DD,3DD.DD,3DD.DD,/)";A(*)
150   END
 

The asterisk in line 140 is used to designate the entire array rather than a single element. Note also that the right-most subscript varies fastest. In this case, it means that the system fills an entire row before going to the next one. The READ/DATA statements are discussed further in the chapter "Data Storage and Retrieval".

Executing the previous program produces the following results:

 

-4.00    36.00    2.30
 5.00    89.00   17.00
-6.00   -12.00   42.00
 

Copying Entire Arrays into Other Arrays

Another way to fill an array is to copy all elements from one array into another (copying sub-sets of arrays is discussed in the subsequent section called "Copying Subarrays"). Suppose, for example, that you have the two arrays A and B shown below.
| 0 0 0 | | 3 5 |

  A=

| 0 0 0 |          

B=

| 8 2 |
| 0 0 0 | | 1 7 |

Note that A is a 3×3 array which is filled entirely with 0's, while B is a 3×2 array filled with non-zero values. To copy B to A, we would execute:

 
MAT A= B
 

Again, you must precede the assignment with MAT. The system will automatically redimension the "result array" (the one on the left-hand side of the assignment) so that it is the same size as the "operand array" (the one on the right side of the equation.) There are two restrictions on redimensioning an array.

If BASIC cannot redimension the result array to the proper size, it returns an error.

Automatic redimensioning of an array will not affect the lower bounds, only the upper bounds. So the BASE values of each dimension of the result array will remain the same. Also keep in mind that the size restriction applies to the dimensioned size of the result array and the current size of the operand array. Suppose we dimension arrays A, B and C to the following sizes:

 

10   OPTION BASE 1
20   DIM A(3,3),B(2,2),C(2,4)
     .
     .
 

We can execute,

 
MAT A= B
 

since A is dimensioned to 9 elements and B is only 4 elements. The copy automatically redimensions A to a 2×2 array. Nevertheless, we can still execute:

 
MAT A= C
 

This works because the nine elements originally reserved for A remain available until the program is scratched. A now becomes a 2×4 matrix. After MAT A= C, we could not execute:

 
MAT B= A
 

or

 
MAT B= C
 

since in each of these cases, we are trying to copy a larger array into a smaller one. But we could execute

 
MAT C= A
 

after the original MAT A= B assignment, since C's dimensioned size (8) is larger than A's current size (4).

Printing Arrays

Printing an Entire Array

Certain operations (e.g., PRINT, OUTPUT, ENTER and READ) allow you to access all elements of an array merely by using an asterisk in place of the subscript list. The statement,

 
PRINT A(*);
 

would display every element of A on the current PRINTER IS device. The elements are displayed in order, with the rightmost subscripts varying fastest. The semi-colon at the end of the statement is equivalent to putting a semi-colon between each element. When they are displayed, therefore, they will be separated by a space. (The default is to place elements in successive columns.)

Examples of Formatting Arrays for Display

This section provides two subprograms which have both been given the name Printmat. The first subprogram is used to display a two-dimensional INTEGER array and the second subprogram is used to display a three-dimensional INTEGER array.

To display a two dimensional array, you can use the following subprogram:


240   SUB Printmat(INTEGER Array(*))
250   OPTION BASE 1
260   FOR Row=BASE(Array,1) TO SIZE(Array,1)+BASE(Array,1)-1
270     FOR Column=BASE(Array,2) TO SIZE(Array,2)+BASE(Array,2)-1
280       PRINT USING "DDDD,XX,#";Array(Row,Column)
290     NEXT Column
300     PRINT
310   NEXT Row
320   SUBEND
 

Assuming that you intended to display a 5×5 array, your results should look similar to this:

 

11   12   13   14   15
21   22   23   24   25
31   32   33   34   35
41   42   43   44   45
51   52   53   54   55
 

If you were to expand the above subprogram to print three-dimensional INTEGER arrays, your subprogram would be similar to the following:

 
250   SUB Printmat(INTEGER Array(*))
260     OPTION BASE 1 
270     FOR Zplane=BASE(Array,3) TO SIZE(Array,3)+BASE(Array,3)-1
280       PRINT TAB(6),"Plane ";Zplane
290       PRINT
300       FOR Yplane=BASE(Array,2) TO SIZE(Array,2)+BASE(Array,2)-1
310         FOR Xplane=BASE(Array,1) TO SIZE(Array,1)+BASE(Array,1)-1
320           PRINT USING "DDDD,XX,#";Array(Zplane,Yplane,Xplane)
330         NEXT Xplane
340         PRINT
350       NEXT Yplane
360       PRINT
370     NEXT Zplane
380   SUBEND
 

If you had a three dimensional array with the following dimensions:

 
DIM Array1(3,3,3)
 

filled with all 3's, the results from executing the above subprogram would be as follows:

 
   Plane 1
3     3     3
3     3     3
3     3     3

   Plane 2
3     3     3
3     3     3
3     3     3
 
   Plane 3
3     3     3
3     3     3
3     3     3
 

Passing Entire Arrays

The asterisk is also used to pass an array as a parameter to a function or subprogram. For instance, to pass an array A to the Printmat subprogram listed earlier, we would write:

 
Printmat (A(*))
 

Copying Subarrays

An earlier section discussed copying the contents of an entire array into another entire array.

 
MAT Array55= Array33
 

Each element of Array33 is copied into the corresponding element of Array55 which is redimensioned if necessary.

Now suppose you would like to copy a portion of one array and place it in a special location within another array. This process is called copying subarrays. Copying Subarray into Subarray Copying a Subarray into Another Subarray

Topics discussed in this section are:

Dimensions for the arrays covered in the above topics will assume an option base of 1 (OPTION BASE 1) unless stated differently.

Subarray Specifier

A subarray is a subset of an array (an array within an array). A subarray is indicated after the array name as follows:


Array_name(subarray_specifier)

String_array$(subarray_specifier)
 

The above subarray could take on many "sizes" and "shapes" depending on what you used as dimensions for the array and the values used in the subarray_specifier. Note that "size" refers to the number of elements in the subarray and "shape" refers to the number of dimensions and elements in each dimension, respectively [e.g. both of these subscript specifiers have the same shape: (-2:1,-1:10) and (1:4,9:20)]. Before looking at ways you can express a subarray, let's learn a few terms related to the subarray specifier.

subscript range

is used to specify a set of elements starting with a beginning element position and ending with a final element position. For example, 5:8 represents a range of four elements starting with element 5 and ending at element 8.

subscript expression

is an expression which reduces the RANK of the subarray. For example if you wanted to select a one-element subarray from a two-dimensional array which is located in the 2nd row and 3rd column, you would use the following subarray specifier: (2,3:3). The subscript expression in this subarray specifier is 2 which restricts the subarray to row 2 of the array.

default range

is denoted by an asterisk (i.e. (1,*)) and represents all of the elements in a dimension from the dimension's lower bound to its upper bound. For example, suppose you wanted to copy the entire first column of a two dimensional array, you would use the following subarray specifier: (*,1), where * represents all the rows in the array and 1 represents only the first column.

Some examples of subarray specifiers are as follows:

(1,*)

a subscript expression and a default range which designate the first row of a two-dimensional array.

(1:2)

a given subscript range which represents the first two elements of a one-dimensional array.

(*,-1:2)

a default range and subscript range which represents all of the elements in the first four columns of a two-dimensional array (base of 2nd dimension assumed to be -1).

(3,1:2)

a subscript expression and subscript range which represent the first two elements in the third row of a two-dimensional array.

(1,*,*)

a subscript expression and two default ranges which represent a plane consisting of all the rows and columns of the first plane in the first-dimension.

(1,1:2,*)

a subscript expression, subscript range and default range which represent the first two rows in the first plane of the first-dimension.

(1,2,*)

two subscript expressions and a default range which represent the entire second row in the first plane of the first-dimension.

(1:2,3:4)

two subscript ranges which represent elements located in the third and fourth columns of the first and second rows of a two-dimensional array.

For more information on string arrays, see the "String Manipulation" chapter found in this manual.

Copying an Array into a Subarray

In order to copy a source array into a subarray of a destination array, the destination array's subarray must have the same size and shape as the source array.

A destination and source array are dimensioned as follows:

 
100  OPTION BASE 1
110  DIM Des_array(-3:1,5),Sor_array(2,3)
 

Suppose these arrays contain the following INTEGER values:

you would copy the source array Sor_array into a subarray of the destination array Des_array by using program line 190 given below:

 
190 MAT Des_array(-1:0,2:4)= Sor_array
 

Des_array would have the following values in it as the result of executing the above statement:

Copying a Subarray into an Array

A subarray can be copied into an array as long as the array can be re-dimensioned to be the size and shape of the subarray specifier.

A destination and source array are dimensioned as follows:

 

100  OPTION BASE 1
110  DIM Des_array(8),Sor_array(-5:4)
 

Suppose both of these one-dimensional arrays contain the following values:

you would copy a subarray of the source array (Sor_array) into a destination array (Des_array) by using program line 190 given below:

 
190 MAT Des_array= Sor_array(-4:1)
 

Des_array will be re-dimensioned to have six elements with the following values in it as a result of executing the above statement.

Copying a Subarray into another Subarray

Subarray specifiers must have the same size and shape when you are copying one subarray into another.

A destination and source array are dimensioned as follows:

 

100   OPTION BASE 1
110   DIM Des_array(3,2,2),Sor_array(2,3,2)
120   .
130   .
 

Suppose these three-dimensional arrays contain the following values:

in order to properly copy a source subarray (Sor_array(*,2,*)) into a destination subarray using asterisks to represent the ranges of dimensions, you would use line 190 given below:

 
190   MAT Des_array(3,*,*)= Sor_array(*,2,*)
 

A three dimensional array with the following values in it would be the result of executing the above statement.

Copying a Portion of an Array into Itself

If you are going to copy a subarray of an array into another portion of the same array, the two subarray locations should not overlap (e.g., MAT Array(2:4,1:3)= Array(1:3,2:4) is an improper assignment). No error message will result from this misuse, but the result is undefined.

A destination and source array are dimensioned as follows:

 
100   OPTION BASE 1
110   DIM Array(4,4)
 

Suppose this two dimensional array contains the following values:

to copy a slice of this array into another portion of the same array, you would use program line 190 given below:

 
190   MAT Array(3:4,1:2)= Array(1:2,3:4)
 

Array will have the following values in it as a result of executing the above statement.
                  | 11 12 13 14 |
| 21 22 23 24 |
| 13 14 33 34 |
| 23 24 43 44 |

Note that you cannot copy a subarray into the array it is part of with an implied re-dimensioning of the array. A statement of the form:

 
MAT Array= Array(subarray_specifier)
 

will always generate a run-time error.

Rules for Copying Subarrays

This section should help limit the number of syntax and runtime errors you could make when copying subarrays. A previous section titled "Subarray Specifier" provided you with examples of the correct way of writing subarray specifiers for copying subarrays. In this section, you will be given rules to things you should not do when copying subarrays. The rules are as follows:

Redimensioning Arrays

In our discussion of copying arrays we saw that the system automatically redimensions an array if necessary. BASIC also allows you to explicitly redimension an array with the REDIM statement. As with automatic redimensioning, the following two rules apply to all REDIM statements:

Suppose A is the 3×3 array shown below.
| 1 2 3 |

  A=

| 4 5 6 |
| 7 8 9 |

To redimension it to a 2×4 array, you would execute:

 
REDIM A(2,4)
 

The new array now looks like the figure below:

  A=

| 1 2 3 4 |
| 5 6 7 8 |

Note that it retains the values of the elements, though not necessarily in the same locations. For instance, A(2,1) in the original array was 4, whereas in the redimensioned array it equals 5. For example, if we REDIMed A again, this time to a 2×2 array, we would get:

 
REDIM A(0:1,0:1)
 

  A=

| 1 2 |
| 3 4 |

We could then initialize all elements to 0:

 
MAT A= (0)
 

  A=

| 0 0 |
| 0 0 |

It is also important to realize that elements that are out of range in the REDIMed array still retain their values. The fifth through ninth elements in A still equal 5 through 9 even though they are now inaccessible. If we REDIM A back to a 3×3 array, these values will reappear. For example:

 
REDIM A(3,3)
 

results in:
| 0 0 0 |

  A=

| 0 5 6 |
| 7 8 9 |

One of the major strengths of the REDIM statement is that it allows you to use variables for the subscript ranges: this is not allowed when you originally dimension an array. In effect, this enables you to dynamically dimension arrays. This should not be confused with the ALLOCATE statement which allows you to dynamically reserve memory for arrays. In the example below, for instance, we enter the dimensions from the keyboard.

 

10   OPTION BASE 1
20   COMPLEX A(100,100)
30   INPUT "Enter lower and upper bounds of dimensions",
     Low1,Up1,Low2,Up2
40   IF (Up1-Low1+1)*(Up2-Low2+1)>10000 THEN Too_big
50   REDIM A(Low1:Up1,Low2:Up2)
 

Line 40 tests to see whether the new dimensions are too big. If so, program control is passed to a line labeled "Too_big". If line 40 were not present, the REDIM statement would return an error if the dimensions were too large.