Define an array in Fortran:
real, dimension(a,b) :: matrix
How do I obtain a
and b
given matrix
?
Read about Fortran 90 intrinsic functions SHAPE, SIZE, UBOUND, LBOUND.
Probably you want size(matrix,1)
and size(matrix,2)
or ubound(matrix,1)
and ubound(matrix,2)
. However, that is the last index of the array (upper bound).
The starting index for the array you show is implicitly 1. Arrays that start at a different index are declared like:
real, dimension(0:a,0:b) :: matrix
You get the starting indexes (lower bounds) using lbound(matrix,1)
and lbound(matrix,2)
.
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:
a
and b
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 extentLBOUND(a)
and UBOUND(a)
return similar integer arrays with each element the dimension's lower and upper boundsLBOUND(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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With