defines only the type and rank of the array, not its shape. This information has to be made available by an explicit interface, often using an interface block (see Interface blocks). Thus we write just SUBROUTINE sub(da) REAL, DIMENSION(:, :) :: da and this is as if da were dimensioned (11,21). However, we can specify any lower bound and the array maps accordingly. REAL, DIMENSION(0:, 0:) :: da The shape, not bounds, is passed, where the default lower bound is 1 and the default upper bound is the corresponding extent. Automatic arrays A partial replacement for the uses to which EQUIVALENCE was put is provided by this facility, useful for local, temporary arrays, as in SUBROUTINE swap(a, b) REAL, DIMENSION(:) :: a, b REAL, DIMENSION(SIZE(a)) :: work work = a a = b b = work END SUBROUTINE swap The actual storage is typically maintained on a stack. ALLOCATABLE and ALLOCATE Fortran provides dynamic allocation of storage; it relies on a heap storage mechanism (and replaces another use of EQUIVALENCE). An example for establishing a work array for a whole program is MODULE work_array INTEGER n REAL, DIMENSION(:,:,:), ALLOCATABLE :: work END MODULE PROGRAM main USE work_array READ (input, *) n ALLOCATE(work(n, 2*n, 3*n), STAT=status) : DEALLOCATE (work) The work array can be propagated through the whole program via a USE statement in each program unit. We may specify an explicit lower bound and allocate several entities in one statement. To free dead storage we write, for instance, DEALLOCATE(a, b) Deallocation of arrays is automatic when they go out of scope. Elemental operations, assignments and procedures We have already met whole array assignments and operations: REAL, DIMENSION(10) :: a, b a = 0. ! scalar broadcast; elemental assignment b = SQRT(a) ! intrinsic function result as array object In the second assignment, an intrinsic function returns an array-valued result for an array-valued argument. We can write array-valued functions ourselves (they require an explicit interface): PROGRAM test REAL, DIMENSION(3) :: a = (/ 1., 2., 3./), & b = (/ 2., 2., 2. /), r r = f(a, b) PRINT *, r CONTAINS FUNCTION f(c, d) REAL, DIMENSION(:) :: c, d REAL, DIMENSION(SIZE(c)) :: f f = c*d ! (or some more useful function of c and d) END FUNCTION f END PROGRAM test Elemental procedures are specified with scalar dummy arguments that may be called with array actual arguments. In