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!
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 continueThe 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).
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!
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.
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).
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.