10. Arrays

Many scientific computations use vectors and matrices. The data type Fortran uses for representing such objects is the array. A one-dimensional array corresponds to a vector, while a two-dimensional array corresponds to a matrix. To fully understand how this works in Fortran 77, you will have to know not only the syntax for usage, but also how these objects are stored in memory in Fortran 77.

One-dimensional arrays

The simplest array is the one-dimensional array, which is just a linear sequence of elements stored consecutively in memory. For example, the declaration
      real a(20)
declares a as a real array of length 20. That is, a consists of 20 real numbers stored contiguously in memory. By convention, Fortran arrays are indexed from 1 and up. Thus the first number in the array is denoted by a(1) and the last by a(20). However, you may define an arbitrary index range for your arrays using the following syntax:
      real b(0:19), weird(-162:237)
Here, b is exactly similar to a from the previous example, except the index runs from 0 through 19. weird is an array of length 237-(-162)+1 = 400.

The type of an array element can be any of the basic data types. Examples:

      integer i(10)
      logical aa(0:1)
      double precision x(100)

Each element of an array can be thought of as a separate variable. You reference the i'th element of array a by a(i). Here is a code segment that stores the 10 first square numbers in the array sq:

      integer i, sq(10)

      do 100 i = 1, 10
         sq(i) = i**2
  100 continue

A common bug in Fortran is that the program tries to access array elements that are out of bounds or undefined. This is the responsibility of the programmer, and the Fortran compiler will not detect any such bugs!

Two-dimensional arrays

Matrices are very important in linear algebra. Matrices are usually represented by two-dimensional arrays. For example, the declaration
      real A(3,5)
defines a two-dimensional array of 3*5=15 real numbers. It is useful to think of the first index as the row index, and the second as the column index. Hence we get the graphical picture:
   (1,1)  (1,2)  (1,3)  (1,4)  (1,5)
   (2,1)  (2,2)  (2,3)  (2,4)  (2,5)
   (3,1)  (3,2)  (3,3)  (3,4)  (3,5)
Two-dimensional arrays may also have indices in an arbitrary defined range. The general syntax for declarations is:
     name (low_index1 : hi_index1, low_index2 : hi_index2)
The total size of the array is then
     size = (hi_index1-low_index1+1)*(hi_index2-low_index2+1)

It is quite common in Fortran to declare arrays that are larger than the matrix we want to store. (This is because Fortran does not have dynamic storage allocation.) This is perfectly legal. Example:

      real A(3,5)
      integer i,j
c
c     We will only use the upper 3 by 3 part of this array.
c
      do 20 j = 1, 3
         do 10 i = 1, 3
            a(i,j) = real(i)/real(j)
   10    continue
   20 continue
The elements in the submatrix A(1:3,4:5) are undefined. Do not assume these elements are initialized to zero by the compiler (some compilers will do this, but not all).

Storage format for 2-dimensional arrays

Fortran stores higher dimensional arrays as a contiguos linear sequence of elements. It is important to know that 2-dimensional arrays are stored by column. So in the above example, array element (1,2) will follow element (3,1). Then follows the rest of the second column, thereafter the third column, and so on.

Consider again the example where we only use the upper 3 by 3 submatrix of the 3 by 5 array A(3,5). The 9 interesting elements will then be stored in the first nine memory locations, while the last six are not used. This works out neatly because the leading dimension is the same for both the array and the matrix we store in the array. However, frequently the leading dimension of the array will be larger than the first dimension of the matrix. Then the matrix will not be stored contiguously in memory, even if the array is contiguous. For example, suppose the declaration was A(5,3) instead. Then there would be two "unused" memory cells between the end of one column and the beginning of the next column (again we are assuming the matrix is 3 by 3).

This may seem complicated, but actually it is quite simple when you get used to it. If you are in doubt, it can be useful to look at how the address of an array element is computed. Each array will have some memory address assigned to the beginning of the array, that is element (1,1). The address of element (i,j) is then given by

      addr[A(i,j)] = addr[A(1,1)] + (j-1)*lda + (i-1)
where lda is the leading (i.e. column) dimension of A. Note that lda is in general different from the actual matrix dimension. Many Fortran errors are caused by this, so it is very important you understand the distinction!

Multi-dimensional arrays

Fortran 77 allows arrays of up to seven dimensions. The syntax and storage format are analogous to the two-dimensional case, so we will not spend time on this.

The dimension statement

There is an alternate way to declare arrays in Fortran 77. The statements
      real A, x
      dimension x(50)
      dimension A(10,20)
are equivalent to
      real A(10,20), x(50)
This dimension statement is considered old-fashioned style today.


[SCCM-001 Home Page] [Fortran Tutorial Home]
sarahw@hpsim.stanford.edu e for scaling a matrix that uses the subroutine scale:
      subroutine mscale(m, n, alpha, A, lda)
      integer m, n, lda
      real alpha, A(lda,*)
c
c Local variables
      integer j

      do 10 j = 1, n
         call scale(m, alpha, A(1,j) )
   10 continue

      return
      end
This version works even when m is not equal to lda since we scale one column at a time and only process the m first elements of each column (leaving the rest untouched).


Exercises

Exercise A
Write a main program that declares a matrix A by
       integer nmax
       parameter (nmax=40)
       real A(nmax, nmax)
Declare appropriate vectors x and y and initialize m=10, n=20, A(i,j) = i+j-2 for 1<=i<=m and 1<=j<=n, x(j) = 1 for 1<=j<=n. Compute y = A*x by calling the matvec subroutine given in the text. Print the answer y.

Exercise B
Write a subroutine that computes y = A*x by scalar products, i.e. the j index should be in the innermost loop. Test your routine on the example in Exercise A and compare your answers.


[Fortran Tutorial Home]
boman@sccm.stanford.edu