In many cases, passing the whole extent of an array to a function/subroutine is too tedious (e.g., you have ten arrays with different extents). Sometimes, you don't even know their extents. To overcome this, Fortran 90 offers the so-called assumed-shape arrays. Of course, they must be formal arguments.
lower-bound : :
and the corresponding formal argument is declared asINTEGER, DIMENSION(-3:3) :: x
then the caller sees array x() as a collection of the following elements:INTEGER, DIMENSION(2:) :: y
Since the extent is lost when passing to an assumed-shape array, the callee would know array y() has 7 elements as follows:x(-3) x(-2) x(-1) x(0) x(1) x(2) x(3)
This is simply because the callee has an assumed-shape array with a lower bound 2. As a result, when the callee uses y(2), y(3), ..., y(8), it actually uses x(-3), x(-2), ..., x(3), respectively.y(2) y(3) y(4) y(5) y(6) y(7) y(8)
Suppose the caller has the following:
The callee could declare an assumed-shape array like the following:INTEGER, DIMENSION(-3:3) :: x .......... CALL SomeOne(x, -3)
In this case, the extent of array y() agrees with that of actual argument array x().SUBROUTINE SomeOne(y, LowerBound) IMPLICIT NONE INTEGER, DIMENSION(LowerBound:), INTENT(IN) :: y .......... END SUBROUTINE SomeOne
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, 21) .......... CONTAINS SUBROUTINE First(x, y, z, Lower, LL) IMPLICIT NONE INTEGER, INTENT(IN) :: Lower INTEGER, INTENT(IN) :: LL INTEGER, DIMENSION(Lower:), INTENT(IN) :: x REAL, DIMENSION(1:), INTENT(OUT) :: y LOGICAL, DIMENSION(LL:), INTENT(INOUT) :: z .......... END SUBROUTINE First END PROGRAM Example
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) CONTAINS REAL FUNCTION Sum(x, n) IMPLICIT NONE INTEGER, INTENT(IN) :: n REAL, DIMENSION(:), 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
SUBROUTINE Example(a, Lower) IMPLICIT NONE INTEGER, DIMENSION(Lower:Lower+SIZE(a)-1), INTENT(INOUT) :: a .......... END SUBROUTINE
PROGRAM Bound IMPLICIT NONE INTEGER, DIMENSION(-10:10) :: a INTEGER, DIMENSION(10:20) :: b INTEGER, DIMENSION(1:100) :: c INTEGER, DIMENSION(1:40) :: d WRITE(*,*) "Array a()'s info:" CALL DisplayInfo(a) WRITE(*,*) "Array b()'s info:" CALL DisplayInfo(b) WRITE(*,*) "Array c()'s info:" CALL DisplayInfo(c) CONTAINS SUBROUTINE DisplayInfo(x) IMPLICIT NONE INTEGER, DIMENSION(:), INTENT(IN) :: x WRITE(*,*) " Size = ", SIZE(x) WRITE(*,*) " Lower bound = ", LBOUND(x) WRITE(*,*) " Upper bound = ", UBOUND(x) WRITE(*,*) END SUBROUTINE END PROGRAM Bound