Arrays

A constant or variable is simply a symbolic name which refers to a particular memory location holding a particular type of data. An array, however, is a symbolic name which refers to a group of memory locations, all holding the same data type. Each individual memory location in an array is referenced by a subscript.

Mathematical Notation FORTRAN 77 Notation
a1, a2, …, an `A(1)`, `A(2)`, …, `A(N)`
b1,1, b1,2, …, bm,n `B(1,1)`, `B(1,2)`, …, `B(M,N)`

Array elements are referenced by the array name followed by the subscript in parentheses. In the case of multidimensional arrays, the subscripts are separated with commas.

One-Dimensional Arrays

In order to declare a one-dimensional array, two pieces of information are required: the data type and the number of elements in the array. There are two ways that this can be done. If the array holds numerical data and implicit typing is used, then the `DIMENSION` statement is all that is necessary.

`DIMENSION array-name(array-length)`

The array-name is the symbolic name used to reference the array and the array-length is the number of elements in the array. In this instance, the elements of the array have the subscripts 1, 2, 3, …, array-length. However, it is often convenient to have subscripts which have a different lower bound than one. In this case, the implicitly-typed array may be declared in this fashion:

`DIMENSION array-name(lower-bound:upper-bound)`

The subscripts range from lower-bound to upper-bound.

The array-length, lower-bound and upper-bound must be `INTEGER` constants. The array-length must be positive (although if the array-length is 1, then the array is really no different from a variable) but the lower-bound and upper-bound values may be negative, zero or positive as long as the upper-bound is greater than the lower-bound.

Example

Consider these statement which appear at the beginning of a program:

```      DIMENSION KOUNT(15),PERCNT(0:100)
```

Two arrays have been declared with a single `DIMENSION` statement. `KOUNT` is an `INTEGER` array of length 15. Its elements are `KOUNT(1)`, `KOUNT(2)`, …, `KOUNT(15)`. `PERCNT` is a `REAL` array of length 101. Its elements are `PERCNT(0)`, `PERCNT(1)`, …, `PERCNT(100)`.

If the array is to take a data type which is contrary to the implicit types, then the array can be declared in the same statement as the type declaration.

Example

Consider these declarations:

```      DOUBLE PRECISION LINE(-100:200)
INTEGER          DAYNO,MONNO
PARAMETER(DAYNO=31,MONNO=12)
CHARACTER*3      MONTH(MONNO)
LOGICAL          DAY(DAYNO)
```

The array `LINE` contains 301 `DOUBLE PRECISION` elements with subscripts ranging from `-100` to `200`. Two `INTEGER` constants are declared and then initialised in a `PARAMETER` statement. These constants are then used in the arrays declarations of the `CHARACTER` array `MONTH` and the `LOGICAL` array `DAY`. In the case of the `CHARACTER` array, each element is a three characters long. An alternative declaration of this array would be

```      CHARACTER        MONTH(MONNO)*3
```

It is also possible to use a combination of type declarations and `DIMENSION` statements to declare arrays but there is little to recommend it.

Example

```      REAL      MEASUR
DIMENSION MEASUR(-100:-1)
```

The symbolic name `MEASUR` is declared to be of type `REAL` and then declared to be an array of length 100 in the following `DIMENSION` statement. However, the same thing could be accomplished with one line.

```      REAL MEASUR(-100:-1)
```

In either case, the array elements are `MEASUR(-100)`, `MEASUR(-99)`, …, `MEASUR(-1)`.

Multidimensional Arrays

FORTRAN 77 arrays may have up to seven dimensions. The elements in each dimension are of the same type so it is not possible to have an array with `INTEGER` values in the first dimension, `REAL` values in the second dimension, `CHARACTER` values in the third dimension, etc.

Multidimensional arrays are declared in the same way as one-dimensional arrays. The array bounds or lengths of each dimension are separated by commas.

Example

```      INTEGER BATTLE(31,12,1939:1945)
```

`BATTLE` is a three-dimensional array. The first dimension has length 31, the second length 12 and the third length 7. The subscripts for the first dimension range from 1 to 31, the subscripts for the second dimension range from 1 to 12 and the subscripts for the third dimension range from 1939 to 1945.

Example

The judicious use of `PARAMETER` statements in setting array bounds can lead to programs which are easy to understand and update. Consider this program fragment:

```      INTEGER   I,J,NCOL,NROW
PARAMETER(NCOL=200,NROW=400)
REAL      MATRIX(NROW,NCOL),SUM
…
SUM = 0.0
DO 20, J = 1,NCOL
DO 10, I = 1,NROW
SUM = SUM + MATRIX(I,J)
10    CONTINUE
20 CONTINUE
…
```

It is quite common to use the dimensions of the arrays in loops and other calculations. By using named constants instead of the actual numbers, the program is easier to understand and if at some later date it is necessary to change the dimension bounds, then this change is done in the `PARAMETER` statement only. It isn't necessary to hunt through the entire program looking for instances where the array bounds are used.

Storage

Arrays are stored in contiguous memory locations in the computer. Consider a one-dimensional array `A(8)`. The elements are stored in the following manner:

 `A(1)` `A(2)` `A(3)` `A(4)` `A(5)` `A(6)` `A(7)` `A(8)`

Higher dimensional arrays are a little trickier. Consider now a two-dimensional array `B(3,4)`:

 `B(1,1)` `B(2,1)` `B(3,1)` `B(1,2)` `B(2,2)` `B(3,2)` `B(1,3)` `B(2,3)` `B(3,3)` `B(1,4)` `B(2,4)` `B(3,4)`

Similarly, a three-dimensional array `C(4,2,3)` is stored like this:

 `C(1,1,1)` `C(2,1,1)` `C(3,1,1)` `C(4,1,1)` `C(1,2,1)` `C(2,2,1)` `C(3,2,1)` `C(4,2,1)` `C(1,1,2)` `C(2,1,2)` `C(3,1,2)` `C(4,1,2)` `C(1,2,2)` `C(2,2,2)` `C(3,2,2)` `C(4,2,2)` `C(1,1,3)` `C(2,1,3)` `C(3,1,3)` `C(4,1,3)` `C(1,2,3)` `C(2,2,3)` `C(3,2,3)` `C(4,2,3)`

Unlike some other programming languages, FORTRAN 77 stores arrays in column-major form. That is to say, the left-most array index varies the most rapidly, followed by the next left-most array index, etc. Thus, the last index in an array varies the most slowly. Knowledge of how FORTRAN 77 stores arrays can lead to increased efficiency (and increased speed).

Example

Consider the following `REAL` array:

```      INTEGER   I,J,NCOL,NROW
PARAMETER(NCOL=4,NROW=2)
INTEGER   B(NROW,NCOL)
```

The nested `DO` loops

```      DO 20, J = 1,NCOL
DO 10, I = 1,NROW
B(I,J) = I + J
10    CONTINUE
20 CONTINUE
```

access the array in the following order:

1. `B(1,1) = 1 + 1`
2. `B(2,1) = 2 + 1`
3. `B(1,2) = 1 + 2`
4. `B(2,2) = 2 + 2`
5. `B(1,3) = 1 + 3`
6. `B(2,3) = 2 + 3`
7. `B(1,4) = 1 + 4`
8. `B(2,4) = 2 + 4`

Note that the order in which the array is accessed is exactly the same in which it is stored. This allows the compiler to generate simpler, more efficient machine code, which will run more quickly. However, if the loops are reversed

```      DO 10, I = 1,NROW
DO 20, J = 1,NCOL
B(I,J) = I + J
20    CONTINUE
10 CONTINUE
```

then the array is accessed in this order:

1. `B(1,1) = 1 + 1`
2. `B(1,2) = 1 + 2`
3. `B(1,3) = 1 + 3`
4. `B(1,4) = 1 + 4`
5. `B(2,1) = 2 + 1`
6. `B(2,2) = 2 + 2`
7. `B(2,3) = 2 + 3`
8. `B(2,4) = 2 + 4`

Accessing an array 'out of order' slows down the program because the compiler is forced to generate less-efficient machine code. Ordering loops carefully reduces processor overheads and lookup times.

General Considerations

• The number of subscripts in any array reference must match the array declaration.
• The subscript must always remain within the bounds declared.
• The subscript must be an `INTEGER` expression.
• An array element is undefined until it has a value assigned to it in some manner.
• An array may be accessed by its name only (without subscripts) in a few limited circumstances:
• in a type declaration if a `DIMENSION` statement is used to set the array bounds;
• in a `DATA` statement which initialises the entire array;
• in a `READ` or `WRITE` statement which reads in or writes out the entire array;
• as an actual argument in an external function reference or subroutine call;
• as a dummy argument in an external function or subroutine.