Vladimir F's answer says all we really need to know about the array matrix
of the question. We can, however, be more general and cover other cases and their limitations.
Before that, some terminology. Arrays have rank (the number of dimensions or subscripts), extents (the number of elements in each dimension), and upper and lower bounds. Scalars have rank zero.
matrix
question has:
- rank 2
- extents
a
and b
- lower bounds
1
and 1
; upper bounds a
and b
.
Each of these properties can be queried (rank only from Fortran 2018) using intrinsic functions:
RANK(a)
returns a scalar integer with the rank of a
SIZE(a,dim=i)
returns a scalar integer with the extent of a
's i
-th dimension (SIZE(a)
returns the total number of elements in all of a
)
SHAPE(a)
returns an integer array, with size equal to the rank of a
(zero for scalar a
), with each element corresponding to one dimension's extent
LBOUND(a)
and UBOUND(a)
return similar integer arrays with each element the dimension's lower and upper bounds
LBOUND(a,i)
and UBOUND(a,i)
return scalar integers with the lower and upper bounds of the i
-th dimension.
For an explicit shape array, unless the lower bound of a dimension is specified it will be 1
and the dimension's extent will be the same as the specified upper bound. Similarly, for an assumed shape dummy argument array the lower bound is 1
unless otherwise given, regardless of the bound of the actual argument:
real, intent(in) :: a(:,:) ! Lower bounds 1
The extents are the same as for the actual argument.
Deferred shape arrays (allocatable and pointer) can also inquired of using these intrinsics, but allocatables must be allocated and pointers must be pointer associated:
real, intent(in), allocatable :: a(:,:) ! Same bounds as the actual argument if allocated
real, intent(out), allocatable :: b(:,:) ! Definitely not allocated: no bounds
Here a
, unlike an assumed shape argument, may have lower bounds different from 1
, but LBOUND
will safely tell us.
For assumed size arguments, things are different:
real, intent(in) :: a(2:5,*)
Here, we can't use SHAPE
to ask about a
, but we can safely use LBOUND
, and we can use UBOUND
and SIZE
in some ways:
LBOUND(a) ! Allowed: can ask about lower bound for all dimensions
LBOUND(a,1)
LBOUND(a,2) ! Both allowed individually
UBOUND(a) ! Not allowed: this would include asking about the second upper bound
UBOUND(a,1) ! Allowed: first bound is defined
UBOUND(a,2) ! Not allowed: bad second bound
SIZE(a) ! Not alllowed: as for UBOUND
SIZE(a,1) ! Allowed
SIZE(a,2) ! Not allowed
RANK(a) ! Allowed (we know it will be 2).
(Fortran 2018) Assumed rank arguments are slightly different still:
real, dimension(..), intent(in) :: a
print *, RANK(a) ! Allowed
print *, SHAPE(a) ! ""
print *, LBOUND(a) ! ""
print *, UBOUND(a) ! ""
print *, SIZE(a) ! ""
print *, LBOUND(a,1) ! Allowed only if a is rank at least 1
print *, UBOUND(a,1) ! ""
print *, SIZE(a,1) ! ""
If the assumed rank variable is a scalar, no value for the dimension is allowed (0
, which would be necessary, is not a valid dimension in any case).
But things can get weird: SHAPE(a)
may return -1
for some element:
implicit none
real a(6)
call s1(a)
contains
subroutine s1(a)
real a(2,*)
call s2(a)
end subroutine s1
subroutine s2(a)
real a(..)
print *, SHAPE(a)
end subroutine s2
end program
If you do get a -1
you know you cannot use UBOUND
to get the upper bound of the corresponding dimension or SIZE
to get its extent. You may use LBOUND
, however, to get its lower bound.
Finally, array expressions always have lower bound 1 in each dimension and upper bound equal to the extent:
real a(4:7)
print *, LBOUND(a), UBOUND(a)
print *, LBOUND(a(:)), UBOUND(a:))
print *, LBOUND(a+1), UBOUND(a+1)