Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Array indexing with assumed shape

Andrew_Smith
Valued Contributor I
564 Views
F95 gave us assumed-shape arrays which are great.

But we nearly alway need to compute the size to do anything with them.

If I want the last element for instance.

So I was wondering, has there been any thoughts for a Future language development (F201x) to add some king of relative indexing.

maybe:

real, intent(in) :: arr(:)
real x, z(2)

x = arr(>1) !Last element
x = arr(<1) !First element
z = arr(>2:2) !Last two elements with stride two
0 Kudos
3 Replies
jimdempseyatthecove
Honored Contributor III
564 Views
Use LBOUND and UBOUND

x = arr(UBOUND(arr)) !Last element
x = arr(LBOUND(arr)) !First element
z = arr(UBOUND(arr)-2:UBOUND(arr):2) !Last two elements with stride two

Jim Dempsey
0 Kudos
John4
Valued Contributor I
564 Views

As Jim Dempsey suggested, there are already intrinsic functions that do just what you want (although not in the fancy way you might expect).

The LBOUND/UBOUND functions return an array of indices by default. Which means, as an example, that the result of array(UBOUND(array)) is not a scalar but a slice.

If you specify the dimension (as a second argument), then the result of LBOUND/UBOUND is scalar.

If you want, you can simplify things a little bit by providing your own wrappers, as in the example below.

[fortran]implicit none

integer :: i, N = 13
real, allocatable :: a(:)

allocate (a(N))

a = [real :: (i, i = 1, N)]

print *, 'first: ', a(LBOUND(a))
print *, 'last: ', a(UBOUND(a))
print *, 'last two, etc.:', a(UBOUND(a,1)-2::2)

print *
print *, 'first: ', first(a)
print *, 'last: ', last(a)
print *, 'last two, etc.:', rstride(a, 2)
print *, 'last three, etc.:', rstride(a, 3)

contains
    pure function first(a) result(x)
        real :: x
        real, intent(IN) :: a(:)
        x = a(LBOUND(a,1))
    end function

    pure function last(a) result(x)
        real :: x
        real, intent(IN) :: a(:)
        x = a(UBOUND(a,1))
    end function

    pure function rstride(a, s) result(x)
        real, intent(IN) :: a(:)
        integer, intent(IN) :: s
        real :: x(s)
        x = a(UBOUND(a,1) - s * (s - 1)::s)
    end function
end
[/fortran]

0 Kudos
jimdempseyatthecove
Honored Contributor III
564 Views
John, thanks for pointing out my error of ommission of the ",1". I got sloppy there. The compiler would have caught this quickly.

Jim
0 Kudos
Reply