Fortran array ubound function

Hi Fortran experts,

I am quite new to fortran, recently I am going through some fortran training materials and unable to make sense of a fortran array function: UBOUND.

in below subroutine, SUBROUTINE cholin(kb)

n=UBOUND(kb,1); iw=UBOUND(kb,2)-1
kb is an array, what is the difference between n and iw?

I am thinking n will be dimension 1 array, for a 3 x 3 arrary, n will be 9
and iw will be two dimension array, so iw= 3-1 equals 2. is it right?

it seems quite difficult to find materials that explains these functions in details.

Thanks in advance for anyone that could give some explanations.

Martin

SUBROUTINE cholin(kb)

!—Choleski Factorization on a Lower Triangle Stored as a Band—

USE precision; IMPLICIT NONE

REAL(iwp),INTENT(in out)::kb(:,:); INTEGER::i,j,k,l,ia,ib,n,iw; REAL(iwp)::x

n=UBOUND(kb,1); iw=UBOUND(kb,2)-1

DO i=1,n
x=.0_iwp
DO j=1,iw; x=x+kb(i,j)**2; END DO
kb(i,iw+1)=SQRT(kb(i,iw+1)-x)
DO k=1,iw
x=.0_iwp
IF(i+k<=n)THEN
IF(k/=iw)THEN
DO l=iw-k,1,-1
x=x+kb(i+k,l)*kb(i,l+k)
END DO
END IF
ia=i+k; ib=iw-k+1
kb(ia,ib)=(kb(ia,ib)-x)/kb(i,iw+1)
END IF
END DO
END DO
RETURN
END SUBROUTINE cholin

Hi Martin and welcome!

The second argument of ubound is optional. In case it’s absent, the result is an array with the upper bounds of every dimension. In your example with an 3x3 array, this would return [3, 3], because both dimensions are 3 elements long (a 2x4 array would return [2, 4] etc.).
If the second argument is present, it “selects” the dimension you are looking for. It’s the same as if you would take the array with all upper bounds and then take the n-th entry.

When want to know what a function is doing, I look it up at the Fortran Wiki. Many times there are good examples (not so in this case).

1 Like

Fortran-lang has an example, but I think a simpler example like this would be a useful addition:

program main ! output in comments
implicit none
real :: x(4),y(-4:3),z(5,-3:2,7)
print*,lbound(x),ubound(x)     ! 1 4
print*,lbound(y),ubound(y)     ! -4 3
print*,lbound(z)               ! 1 -3 1
print*,ubound(z)               ! 5 2 7
print*,lbound(z,2),ubound(z,2) ! -3 2
end program main
3 Likes

I am frequently able to make sense out of the descriptions for the standard. I’ll admit this one is hard to parse, but is the “ultimate source of truth”

16.9.196 UBOUND (ARRAY [, DIM, KIND])

Description. Upper bound(s).

Class. Inquiry function.

Arguments.

ARRAY shall be assumed-rank or an array. It shall not be an unallocated allocatable array or a pointer that is not associated. If ARRAY is an assumed-size array, DIM shall be present with a value less than the rank of ARRAY.

DIM (optional) shall be an integer scalar with a value in the range 1 ≤ DIM ≤ n, where n is the rank of ARRAY. The corresponding actual argument shall not be an optional dummy argument, a disassociated pointer, or an unallocated allocatable.

KIND (optional) shall be a scalar integer constant expression.

Result Characteristics. Integer. If KIND is present, the kind type parameter is that specified by the value of KIND; otherwise the kind type parameter is that of default integer type. The result is scalar if DIM is present; otherwise, the result is an array of rank one and size n, where n is the rank of ARRAY.

Result Value.

Case (i): If DIM is present, ARRAY is a whole array, and dimension DIM of ARRAY has nonzero extent, the result has a value equal to the upper bound for subscript DIM of ARRAY. Otherwise, if DIM
is present and ARRAY is assumed-rank, the value of the result is as if ARRAY were a whole array,
with the extent of the final dimension of ARRAY when ARRAY is associated with an assumed-size
array being considered to be −1. Otherwise, if DIM is present, the result has a value equal to the
number of elements in dimension DIM of ARRAY.

Case (ii): If ARRAY has rank zero, UBOUND (ARRAY) has a value that is a zero-sized array. Otherwise, UBOUND (ARRAY) has a value whose ith element is equal to UBOUND (ARRAY, i), for i = 1, 2, . . . , n, where n is the rank of ARRAY. UBOUND (ARRAY, KIND=KIND) has a value whose ith
element is equal to UBOUND (ARRAY, i, KIND=KIND), for i = 1, 2, . . . , n, where n is the rank of ARRAY.

Examples. If A is declared by the statement
REAL A (2:3, 7:10)
then UBOUND (A) is [3, 10] and UBOUND (A, DIM = 2) is 10.
NOTE 1
If ARRAY is assumed-rank and has rank zero, DIM cannot be present since it cannot satisfy the requirement 1 ≤ DIM ≤ 0.

1 Like

But beware! Although Fortran allows an array to be declared with lower bounds other than default 1 in each dimension, there are many circumstances when the bounds are forced to start with 1. Not only in array expressions mentioned in Fortran Wiki page cited above but also when an array is passed to a subprogram. Passing the array as a pointer makes it yet another story. Consider following example:

program arr3
  integer, target :: tab(-1:3) = [0,1,2,3,4]
  print *, 'Array as declared originally: ', lbound(tab), ubound(tab)
  call sub(tab, tab)  ! same array passed differently

contains
  subroutine sub(t,t2)
    integer, intent(in) :: t(:)
    integer, intent(in), pointer :: t2(:)
    print *, 'Array passed assumed-shape: ', lbound(t), ubound(t)
    print *, 'Array passed as a pointer:  ', lbound(t2), ubound(t2)
  end subroutine sub
end program arr3

gives following output:

 Array as declared originally:         -1           3
 Array passed assumed-shape:            1           5
 Array passed as a pointer:            -1           3
3 Likes

so in your example, z(5,-3:2,7), ubound(z,2), the 2 indicates the 2nd dimension which is -3:2, correct?

Thanks
Martin

Yes. The line could also be written with the 2nd argument named:

print*,lbound(z,dim=2),ubound(z,dim=2) ! -3 2

thanks for your very detailed explanation.

after some struggle I seems to get it.

Thanks for your time

Martin

great, thanks for your help.