boxofchalk1
boxofchalk1

Reputation: 493

Linear Indexing of Multi-Dimension Arrays in Fortran

Let A be a multi-dimensional array of DIMENSION(m,n,p). Is linear indexing of A (using a single index) allowed in Fortran? If so, what is correspondence between the linear index and the multi-dimensional index?

In other words, is A(i) allowed, and which element does A(i) correspond to (in which order are the dimensions traversed)?

Upvotes: 3

Views: 3403

Answers (4)

Enlico
Enlico

Reputation: 28384

I would add the following possibility, even though I've never used it, since I find it confusing. Someone (Nek5000, see page 22) claims it's faster.

do i=1,nx1*ny1*nz1*nelv
    u(i,1,1,1) = vx(i,1,1,1)
enddo

which is equivalent but superior (WHY?) to:

do e=1,nelv
    do k=1,nz1
        do j=1,ny1
            do i=1,nx1
                u(i,j,k,e) = vx(i,j,k,e)
            enddo
        enddo
    enddo
enddo

which is equivalent but vastly superior (WHY?) to:

do i=1,nx1
    do j=1,ny1
        do k=1,nz1
            do e=1,nelv
                u(i,j,k,e) = vx(i,j,k,e)
            enddo
        enddo
    enddo
enddo

Upvotes: 1

Fortranner
Fortranner

Reputation: 2605

You can pass a 3D array to a function or subroutine as if it were a 1D array, as shown in the code below. I don't recommend using this feature, but you will see it in pre-Fortran 90 code.

program xarray
implicit none
! demonstrate storage association
integer, parameter :: n1 = 2, n2 = 4, n3 = 3
integer :: i1,i2,i3,arr(n1,n2,n3)
forall (i1=1:n1,i2=1:n2,i3=1:n3) arr(i1,i2,i3) = i1 + 10*i2 + 100*i3
print*,"arr =",arr
! output: arr = 111 112 121 122 131 132 141 142 211 212 221 222 231 232 241 242 311 312 321 322 331 332 341 342
call print_array(arr,n1*n2*n3)
end program xarray

subroutine print_array(arr,n)
implicit none
integer, intent(in) :: arr(n)
integer, intent(in) :: n
print*,"arr(1), arr(n) =",arr(1),arr(n)
! output: arr(1), arr(n) = 111 342
end subroutine print_array

Upvotes: 4

francescalus
francescalus

Reputation: 32366

For the array declared dimension A(m,n,p) it isn't allowed to reference like A(i). However, the linear indexing, the so-called array element order is an important concept. As stated in another answer the left-most index is the most rapidly varying. A(1,1,1) comes immediately before A(2,1,1), ..., A(1,2,1), etc.

The array element order becomes useful because of various associations, and the like. For example - not that I would recommend them except with real need - equivalence and argument association with an assumed-size array allow much the same thing.

As a more modern feature, one can have pointer bounds remapping. And, of course, with a copy, the reshape intrinsic.

Upvotes: 3

dfeuer
dfeuer

Reputation: 48580

http://www.obliquity.com/computer/fortran/array.html explains that arrays are stored in "column-major" form, so that the left most index changes the most quickly, followed by the second to leftmost, etc. (this is the opposite of C, I believe). It seems quite unwise to try to index a multidimensional array as though it were one-dimensional, but as the above-linked page explains, your compiler will produce code that does just that (and is therefore very fast) as long as you nest your loops in the right order.

Upvotes: 6

Related Questions