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. |
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
REDIM
ensioned.
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.
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)
(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.
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.
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.
This section deals with assigning and extracting individual elements from arrays.
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
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.
This section discusses three methods for filling an entire array:
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
.
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
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).
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.)
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
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(*))
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 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.
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:
|
a subscript expression and a default range which designate the first row of a two-dimensional array. |
|
a given subscript range which represents the first two elements of a one-dimensional array. |
|
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). |
|
a subscript expression and subscript range which represent the first two elements in the third row of a two-dimensional array. |
|
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. |
|
a subscript expression, subscript range and default range which represent the first two rows in the first plane of the first-dimension. |
|
two subscript expressions and a default range which represent the entire second row in the first plane of the first-dimension. |
|
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.
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:
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.
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.
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.
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:
(1,2,3)
is not allowed, it will produce a syntax error).
This rule applies to all subscript specifiers.
(*,*,*)
is not allowed, it will produce
a syntax error). This rule applies to all subscript specifiers.
MAT
statement, there
must be the same number of ranges in each subarray specifier. For
example:
MAT Des_array1(1:10,2:3)= Sor_array(5:14,*,3)
is the correct way of copying a subarray into another subarray provided the
default range given in the source array (Sor_array
) has
only two elements in it. Note that the source array is a three-dimensional
array. However, it still meets the criteria of having the same number of
ranges as the destination array because two of its entries are ranges and
one is an expression.
MAT
statement, the subscript
ranges in the source array must be the same shape as the subscript
ranges in the destination array. For example, the following example is
legal:
MAT Des_array(1:5,0:1)= Sor_array(3,1:5,6:7)
however, the following example is not legal:
MAT Des_array(0:1,1:5)= Sor_array(1:5,0:1)
because both of its subarray specifiers do not have the same shape (i.e. the rows and columns in the destination array do not match the rows and columns in the source array).
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:
REDIM
ed array must maintain the same number of dimensions.
REDIM
an array so that it contains more elements
than it was originally dimensioned to hold.
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
REDIM
ed 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
REDIM
ed 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.