How to obtain the starting index of a Fortran array? How to obtain the starting index of a Fortran array? arrays arrays

How to obtain the starting index of a Fortran array?


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:

  • 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 allocatedreal, 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 dimensionsLBOUND(a,1)LBOUND(a,2)  ! Both allowed individuallyUBOUND(a)    ! Not allowed: this would include asking about the second upper boundUBOUND(a,1)  ! Allowed: first bound is definedUBOUND(a,2)  ! Not allowed: bad second boundSIZE(a)      ! Not alllowed: as for UBOUNDSIZE(a,1)    ! AllowedSIZE(a,2)    ! Not allowedRANK(a)      ! Allowed (we know it will be 2).

(Fortran 2018) Assumed rank arguments are slightly different still:

real, dimension(..), intent(in) :: aprint *, RANK(a)     ! Allowedprint *, SHAPE(a)    ! ""print *, LBOUND(a)   ! ""print *, UBOUND(a)   ! ""print *, SIZE(a)     ! ""print *, LBOUND(a,1) ! Allowed only if a is rank at least 1print *, 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)