 |
» |
|
|
 |
There are several different categories of array in Fortran 90.
Each category is based on the shape of the array as defined by its
array specifier. Explicit-shape arrays |  |
An
explicit-shape array has explicitly declared
bounds for each dimension; they are neither taken from an actual
array argument ("assumed") nor otherwise specified
later, prior to use ("deferred"). Each dimension
of an explicit-shape array is of the form: [lower bound:] upper bound |
For
a given dimension, the values of the lower bound and upper bound
define the range of the array in that dimension. The bounds may
be positive, negative, or zero. Normally the lower bound will be
less than the upper bound; if the lower bound is the same as the
upper bound then that dimension will contain only one element; if
it is greater, then the dimension contains no elements, the extent
of the dimension will be zero, and the array will be zero-sized.
If a lower bound is not specified then it will assume the default
value of 1. More generally, the bounds of
a dimension may be any specification expression. A specification
expression is always a scalar and of type integer; it is either
a constant expression, or one in which all variables are available
at the time the subprogram is activated. Chapter 5 describes
specification expressions in more detail. There are various forms of explicit-shape array; the simplest
form is represented by an array declaration in which the name of
the array is not a dummy argument and all the bounds are constant
expressions. This form of array may have the SAVE
attribute and may be declared in any program unit. An
automatic array is an explicit-shape array that is not a dummy argument,
and which has at least one nonconstant bound. Automatic arrays may
be declared in a subroutine or function, but they may not have the
SAVE attribute
nor can they be initialized. A
dummy array is identified by the appearance of its name in a dummy
argument list; its bounds may be constants or expressions. Dummy
arrays may only be declared in a subroutine or function. An
adjustable array is a particular form of a dummy array; its name
is specified in a dummy argument list but at least one of its bounds
is a nonconstant specification expression. Explicit-shape arrays may also be used as function results;
these are described in the section “Array functions” and also in Chapter 7. The following subroutine demonstrates how explicit-shape arrays
may be declared. SUBROUTINE sort(list1,list2,m,n) |
! examples of arrays with explicit shape |
! a rank-one array, having an explicit shape |
! represented by the vector [ 98 ] |
REAL :: list1(100), list2(0:m-1,-m:n) |
! two dummy arrays with explicit shape, list1 |
! is a rank-one array with an extent of 100 and |
! list2 is a rank-two array with an extent of |
! m * (m+n+1). Note that list2 is also an |
! work is an automatic array as it does not |
! appear in the dummy argument list and its |
! bounds are not constant |
INTEGER, PARAMETER :: buffsize = 0 |
REAL :: buffer (1: buffsize) |
! the array buffer has explicit shape, in this |
! example however it has no elements and is |
Assumed-shape arrays |  |
An
assumed-shape array is a dummy argument that assumes the shape of
the corresponding actual argument. This should be compared with
an explicit-shape dummy array in which the shape of the array is
specified locally. Each dimension of an assumed-shape array has the form: where lower bound is a specification
expression; it may be omitted and would then take the default value
of 1. Note that it is the shape of the actual argument that is assumed
and not its bounds and that the actual and dummy argument may have
different lower (and upper) bounds for each dimension. An assumed-shape array subscript may extend from the specified
lower bound to an upper bound that is
equal to the lower bound plus the extent in that dimension of the
actual argument minus one. A procedure that declares an assumed-shape dummy argument
must have an explicit interface in the calling program unit; this
is explained more thoroughly in Chapter 7. The following subroutine demonstrates various forms of an
assumed-shape array declaration. SUBROUTINE initialize (a,b,c,n) |
! examples of assumed-shape arrays |
! the array a is a rank-one assumed-shape array, |
! it assumes (or inherits) its shape and size |
! from the corresponding actual argument; its |
! lower bound is 1 regardless of the lower bound |
! defined for the actual argument |
! a rank-one assumed-shape array, the lower |
! bound is ABS(n) and the upper bound will be |
! the lower bound plus the extent of the |
! corresponding actual argument minus one |
REAL, DIMENSION(:,:,:,:,:) :: c |
! an assumed-shape array with 5 dimensions |
! (rank=5), and all the lower bounds are 1 |
END SUBROUTINE initialize |
As mentioned previously, if a procedure has an argument that
is an assumed-shape array, its interface must be known to the calling
program unit. For example, if subroutine initialize
is an external subroutine, then it must appear in an interface block
as follows: REAL :: omega(-2:+3, -1:+3, 0:3, 1:3, 2:3) |
SUBROUTINE initialize (a,b,c,n) |
INTEGER :: a(:)COMPLEX :: b(ABS(n):) |
REAL, DIMENSION(:,:,:,:,:) :: c |
END SUBROUTINE initialize |
(parts,coeffs,omega,lbound(omega,1)) |
Interface blocks are described further in Chapters 7
and 10. Deferred-shape arrays |  |
A
deferred-shape array is either an allocatable array or it is a pointer
array. The array specification for a deferred-shape array is of
the form: It
defines the rank of the array but not the bounds. The array is therefore
said to have deferred-shape. The
shape of the array becomes defined either when the array is allocated
or when a pointer array becomes associated with a target. Note that
the form of array specifier for assumed-shape arrays and deferred-shape
arrays is similar, but a deferred-shape array has either the ALLOCATABLE
attribute which defines an allocatable array or it has the POINTER
attribute which defines a pointer array; an assumed-shape array
may have neither of these attributes. A
pointer array is an array that has the POINTER
attribute and may therefore be used to point to some target object.
Initially a pointer array has no shape and may not be referenced
until it becomes associated either through an ALLOCATE
statement or through a pointer assignment statement. Chapter 3
describes in more detail the concept of pointers and how they may
become associated, and disassociated, while Chapter 10
explains how the POINTER
statement may be used to declare a pointer. Once a pointer array has become associated it may be used
in any context in which an array is allowed. Note that a pointer
array is not an array of pointers; that is, its elements do not
have the POINTER
attribute. To create an array of pointers, define a derived type
consisting of a single pointer component and declare an array of
this derived type. The following declarations illustrate different pointer array
declarations: REAL, POINTER, DIMENSION(:) :: p1 |
! p1 is declared as a pointer to a rank-one |
! array of type real, p1 is not associated |
INTEGER, POINTER :: p2(:,:) |
! p2 is a pointer to an integer array of |
! p2 must be associated with a target before it |
TYPE(err_type), POINTER, DIMENSION(:,:,:) :: err |
! err is a pointer to a rank-3 array of type |
INTEGER, POINTER :: p3(n) |
! this is ILLEGAL, pointers cannot have an |
An
allocatable array has only its name and rank declared at compile-time,
plus the ALLOCATABLE
attribute. It can be allocated and deallocated as required by use
of the ALLOCATE
and DEALLOCATE
statements. These statements give the user the ability to manage
space dynamically at execution time. The
ALLOCATABLE statement
and attribute, the ALLOCATE
statement, and the DEALLOCATE
statement are described in Chapter 10. An allocatable array has an allocation status which is initially
set to not-allocated. The array may not
be referenced while it is in this state except as an argument to
the ALLOCATED
intrinsic inquiry function, which may be used to determine the allocation
status of an allocatable array; this intrinsic function is described
in Chapter 11. Once the allocatable array is allocated,
its allocation status becomes allocated
and the array may be used in any context in which an array may appear.
If an allocatable array is deallocated then its allocation status
returns to not-allocated. It is an error
to either allocate an allocatable array whose status is allocated,
or to deallocate an allocatable array when its status is not-allocated. The allocation status of a local allocatable array that does
not have the SAVE
attribute becomes undefined if the allocation
status of the array is allocated when
the procedure in which it is defined exits. In HP Fortran 90
such an array will be automatically deallocated; this is a Fortran 95
feature that has been added as an extension. Although pointer arrays provide more functionality, allocatable
arrays are simpler and provide more opportunities for compiler optimization. The following subroutine contains an example of an allocatable
array declaration and uses the ALLOCATED
intrinsic function to illustrate how its allocation status may change. ! demonstrate the use of an allocatable array |
REAL, ALLOCATABLE, DIMENSION(:,:) :: matrix |
! the array matrix is rank-2 allocatable |
! array, it has no shape and no storage |
! a1 is assigned the value .FALSE. as the |
! allocation status of the array is |
! dynamically create the array matrix; after |
! it has been allocated the array will have |
! a2 is assigned the value .TRUE. as the |
! allocatable array does exist and its |
! allocation status is therefore allocated |
! a3 is assigned the value .FALSE. as the |
! allocation status of the array is |
Assumed-size arrays |  |
An
assumed-size array is an older FORTRAN 77
feature that has been modernized in Fortran 90 with the
introduction of assumed-shape arrays; the use of assumed-size arrays
in new code is discouraged. An assumed-size array is a dummy argument whose size is not
specified; this is in contrast to an explicit-shape dummy array
where the extents of each dimension are specified, and an assumed-shape
array where the extents of each dimension are assumed from the corresponding
actual argument. The form of an assumed-size array specifier is
the same as for an explicit-shape array except that the upper bound
of the last dimension is an asterisk (*). All dummy array arguments and their corresponding actual argument
share the same initial element and are storage associated. In the
case of explicit-shape and assumed-size arrays, the actual and dummy
array do not have to have the same shape or even rank; however the
size of the dummy array must not exceed the size of the actual argument
and therefore a subscript in the last dimension of an assumed-size
array may extend from the lower bound to a value that does not cause
the reference to go beyond the storage associated with the actual
argument. Because
the last dimension of an assumed-size array has no upper bound,
the dimension has no extent and the array consequently has no shape.
The name of an assumed-size array therefore cannot be used in contexts
in which a shape is required, such as the name of a function result
or in a whole array reference. The following example shows how an assumed-size array may
be declared. ! an example of an assumed-size array |
! declares a to be a rank-two array, the array |
! has no shape and its size must not be greater |
! than the size of associated dummy argument; |
! the bounds of the first dimension range from 1 |
! through to n, the lower bound of the second |
! dimension starts at 3, and its upper bound is |
|