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

Array indices start

j_clausen
Beginner
1,712 Views
Dear all.

I have a question about the index numbering of arrays in Fortran. Consider this small code example:

module IndexModule
contains
subroutine Asub(A)
integer, allocatable :: A(:)
allocate(A(3))
A(1) = 1 ; A(2) = 2 ; A(3) = 3
end subroutine Asub
end module IndexModule

program IndexTest
use IndexModule
implicit none
integer, allocatable :: A(:)

call Asub(A)

!write(*,*) A(1), A(2), A(3)
write(*,*) A(0), A(1), A(2)
end program IndexTest

When I compile and run the program as it is shown it runs fine. But if I uncomment the commented write line I get and array bounds exceeded error. A closer incpection in the debugger reveals what is wrong. When A is allocated in the subroutine it has indices 1, 2, 3, as expected. But when it is returned to the mail program it has indices 0, 1, 2. Why is that? It should be mentioned that I use CVF 6.6 (with Windows XP) but plan to migrate to IVF in the near future. This behaviour has caused some nuicances in my programs, as I then have to check the lower bounds of my subroutine-generated arrays using lbound. Am I doing anything wrong?

Best regards, j_clausen
0 Kudos
1 Solution
Jugoslav_Dujic
Valued Contributor II
1,712 Views

Well, the Compaq Fortran had a bug in its implementation, so it does not quite make sense to consider it within the framework on the Standard.

The question "does the standard say anything about the indexing conventions" is too broad to be succinctly answered. The standard says quite a bit about "indexing conventions", because they have to be uniform across platforms, so that you can produce portable programs.

With my mind-reading hat on, I presume that you need the information about what happens when an array is passed to a routine. The short answer is that POINTER and ALLOCATABLE array preserve their bounds across routine boundaries, but assumed-shape dummies get remapped to lower bound of 1:

[fortran]integer, target::      I(2:5)
integer, pointer::     P(:)
integer, allocatable:: A(:)

P=>I

call Test(I, P, A)
write(*,*) "I: ", lbound(I), ubound(I) !2,5
write(*,*) "P: ", lbound(P), ubound(P) !2,5
write(*,*) "A: ", lbound(A), ubound(A) !2,5

contains

subroutine Test(I, P, A)
integer, target::      I(:)
integer, pointer::     P(:)
integer, allocatable:: A(:)
write(*,*) "I: ", lbound(I), ubound(I) !1,4
write(*,*) "P: ", lbound(P), ubound(P) !2,5
allocate(A(2:5))
write(*,*) "A: ", lbound(A), ubound(A) !2,5
end subroutine Test
end program 
[/fortran]

View solution in original post

0 Kudos
6 Replies
DavidWhite
Valued Contributor II
1,712 Views
In IVF, for your code, the array has values in elements 1, 2 and 3 as expected. A run-time error is then flagged forWRITE A(0).

David

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,712 Views
CVF had an early implementation of this feature (TR15581) and it was rather buggy. I heartily recommend upgrading to IVF, especially if you plan on using newer language features.
0 Kudos
j_clausen
Beginner
1,712 Views
Thank you both

That's what I like to hear, i.e. that this is not a general Fortran issue. This will make the code in IVF much prettier than that of CVF.

j_clausen
0 Kudos
j_clausen
Beginner
1,712 Views

I have now migrated to Intel Visual Fortran and the problem in my initial post has vanished, as mentioned by David. This leads me to a question: Does the standard say anything about the indexing conventions? I.e. does Compaq Fortran comply with the Fortran 95 standard, even though the code sample shown initiallydon't work?

j_clausen

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,713 Views

Well, the Compaq Fortran had a bug in its implementation, so it does not quite make sense to consider it within the framework on the Standard.

The question "does the standard say anything about the indexing conventions" is too broad to be succinctly answered. The standard says quite a bit about "indexing conventions", because they have to be uniform across platforms, so that you can produce portable programs.

With my mind-reading hat on, I presume that you need the information about what happens when an array is passed to a routine. The short answer is that POINTER and ALLOCATABLE array preserve their bounds across routine boundaries, but assumed-shape dummies get remapped to lower bound of 1:

[fortran]integer, target::      I(2:5)
integer, pointer::     P(:)
integer, allocatable:: A(:)

P=>I

call Test(I, P, A)
write(*,*) "I: ", lbound(I), ubound(I) !2,5
write(*,*) "P: ", lbound(P), ubound(P) !2,5
write(*,*) "A: ", lbound(A), ubound(A) !2,5

contains

subroutine Test(I, P, A)
integer, target::      I(:)
integer, pointer::     P(:)
integer, allocatable:: A(:)
write(*,*) "I: ", lbound(I), ubound(I) !1,4
write(*,*) "P: ", lbound(P), ubound(P) !2,5
allocate(A(2:5))
write(*,*) "A: ", lbound(A), ubound(A) !2,5
end subroutine Test
end program 
[/fortran]

0 Kudos
j_clausen
Beginner
1,712 Views

Thank you very much Jugoslav. Your mind-reading hat works perfectly.

j_clausen

0 Kudos
Reply