An array can certainly be passed to a function or a subroutine for further
processing. Just recall that an array has
three components: a name, a type and an extent.
For the first two, they are similar to passing a variable, and the third one
can be made available when declaring an array formal argument. However,
the problem is that since an extent consists of a lower bound and an upper
bound, in order to declare an array formal argument correctly, these
two bounds must also be passed.
Now, the array formal arguments in subroutine First() have identical extents as their corresponding actual arguments in the main program.
PROGRAM Example IMPLICIT NONE INTEGER, PARAMETER :: LOWER_BOUND = 20 INTEGER, PARAMETER :: UPPER_BOUND = 50 INTEGER, DIMENSION(LOWER_BOUND:UPPER_BOUND) :: Data REAL, DIMENSION(1:LOWER_BOUND) :: Values LOGICAL, DIMENSION(21:UPPER_BOUND) :: Answers .......... CALL First(Data, Value, Answers, LOWER_BOUND, UPPER_BOUND, 21) .......... CONTAINS SUBROUTINE First(x, y, z, Lower, Upper, LL) IMPLICIT NONE INTEGER, INTENT(IN) :: Lower INTEGER, INTENT(IN) :: Upper INTEGER, INTENT(IN) :: LL INTEGER, DIMENSION(Lower:Upper), INTENT(IN) :: x REAL, DIMENSION(1:Lower), INTENT(OUT) :: y LOGICAL, DIMENSION(LL:Upper), INTENT(INOUT) :: z .......... END SUBROUTINE First END PROGRAM Example
Data() is an array of 1000 elements. But, when it is read in with the first two READ(*,*)s, the actual number of elements may not be 1000 and in fact it could be very small, say 10! Therefore, when function Sum() is used to calculate the sum of all of these values, we need three actual arguments rather than two. The first passes the array, the second passes the actual size, and the third passes the extent.
For function Sum(), n receives the actual number of values in an array whose extent is 1:SIZE, where SIZE is received via the third formal argument.
PROGRAM Test IMPLICIT NONE INTEGER, PARAMETER :: MAX_SIZE = 1000 REAL, DIMENSION(1:MAX_SIZE) :: Data INTEGER :: ActualSize INTEGER :: i READ(*,*) ActualSize READ(*,*) (Data(i), i=1, ActualSize) WRITE(*,*) "Sum = ", Sum(Data, ActualSize, MAX_SIZE) CONTAINS REAL FUNCTION Sum(x, n, SIZE) IMPLICIT NONE INTEGER, INTENT(IN) :: SIZE, n REAL, DIMENSION(1:SIZE), INTENT(IN) :: x REAL :: Total INTEGER :: i Total = 0.0 DO i = 1, n Total = Total + x(i) END DO Sum = Total END FUNCTION Sum END PROGRAM Test
Array Input() and Avg() have extents 1:100 and 1:98 (i.e., two elements less than that of Input()), respectively. The READ(*,*) statement reads in the actual number of elements and the input data.PROGRAM Elements IMPLICIT NONE INTEGER, PARAMETER :: BOUND_1 = 100 INTEGER, PARAMETER :: BOUND_2 = BOUND_1 - 2 REAL, DIMENSION(1:BOUND_1) :: Input REAL, DIMENSION(1:BOUND_2) :: Avg INTEGER :: n, i READ(*,*) n, (Input(i), i=1, n) DO i = 1, n-2 Avg(i) = Average(Input(i), Input(i+1), Input(i+2)) END WRITE(*,*) (Avg(i), i=1, n-2) CONTAINS REAL FUNCTION Average(a, b, c) IMPLICIT NONE REAL, INTENT(IN) :: a, b, c Average = (a + b + c)/3.0 END FUNCTION Average END PROGRAM Elements
The DO-loop only iterates n-2 times. For iteration i, Input(i), Input(i+1) and Input(i+2) are sent to function Average(). Thus, formal arguments a, b and c receive Input(i), Input(i+1) and Input(i+2), respectively. Function Average() returns the average of these three elements. The result is then stored in Avg(i).
In summary, Avg(1) contains the average of Input(1), Input(2) and Input(3); Avg(2) contains the average of Input(2), Input(3) and Input(4); Avg(3) contains the average of Input(3), Input(4) and Input(5); and so on.
SUBROUTINE Bad(x, m, n) IMPLICIT NONE INTEGER, INTENT(INOUT) :: m, n INTEGER, DIMENSION(m:n), INTENT(INOUT) :: x .......... m = ..... ! BAD MOVE n = ..... ! BAD MOVE END SUBROUTINE Bad