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

Two-dimensional matrices indexing

Kusiek__Adam
Beginner
485 Views

Hello, 

I am working on the old F77 code which I have to combine with the newer version of software. I have the question about multidimensional matrix indexing i.e 

Let's declare 2D matrix: 

integer, dimension(5,4) :: M 

Can I write instead of: M(1,2)  = 3 the following line M(7,1) = 3 ? 

The two-dimensional matrices in old F77 code (I am working on) were indexed in both ways presented above - this does not work for Intel Parallel Studio XE 2017 with 32bit project and works with 64bit project - is it a problem of compiler settings? 

Thank you for any help/suggestions

Adam 

0 Kudos
6 Replies
andrew_4619
Honored Contributor II
485 Views

That is a bug in your old compiler and also your old code.

0 Kudos
GVautier
New Contributor II
485 Views

Hi

In some old codes, this behaviour was sometimes used intensively.

In modern compiler, you should use equivalence or pointers instead.

dimension m(5,4)

dimension m20(20,1)

equivalence (m,m20)

so m(1,2) and m20(7,1) have the same address.

The second dimension of m20 is optional if you want to minimize changes in your code.

0 Kudos
Kusiek__Adam
Beginner
485 Views

Hello 

Thank you for all responses.

@ Vautier: I think this is what I was looking for - should help

Beside equivalnce is Intel Fortran Compiler offering something like in C/C++ where you have pointer on the matrix and you can use both 

tab = 3

or

*(tab + i*ncol + j) = 3

to jump to proper address in memory. 

Best 

Adam 

 

 

 

0 Kudos
mecej4
Honored Contributor III
485 Views

Adam: Are you determined to be a martyr?

I ask this because your original question starkly displays the kind of error that will be next to impossible to seek and fix, if your requested slackening of the language rules is tolerated by the compiler.

I understand what you want; most current compilers, with no subscript checking requested, will compile and run such code. Here is a complete program that is based on your post.

program laxFort
integer, dimension(5,4) :: M
!
M(1,2) = 3
print *,M(7,1)
end program

The program is not standard-conforming, and the result is "undefined". Ifort may give the output as 0, and Gfortran may give -2146722365 (these are the results that I saw, but you may see other results). 

Why? You made a slip in assuming that M(1,2) and M(7,1) refer to the same address in memory. Rather, you should have written M(6,1) or declared the leading dimension as 6 instead of 5. This kind of error is easy to detect and fix in a short program, but where would you be if this was in a large program in which M had been passed around through a chain of subroutine calls? Such errors cannot be located by using subscript checking options in the compiler invocations, because this style of coding relies on disobeying the rules that govern subscripts!

0 Kudos
FortranFan
Honored Contributor II
485 Views

Kusiek, Adam wrote:

.. Beside equivalnce is Intel Fortran Compiler offering something like in C/C++ where you have pointer on the matrix and you can use both ..

@Adam,

Think not about Intel Fortran compiler offering something, but what the IEC ISO standard for Fortran does.

By the way, note there are storage order differences between C, C++ and Fortran in terms of row-major versus column-major.  Also, Fortran is only default 1-based indexing; a coder can do 0-based or any other starting index.  I'm stating this because your M(1,2) is not equivalent to (7,1) of an (effectively 1-D) storage-associated array, it will be (6,1).

And yes, with standard Fortran there are several options for storage association including with objects that have TARGET and POINTER attributes.  Look into the standard or consult references such as those in https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world.  So you can do:

   implicit none

   character(len=*), parameter :: fmtg = "(g0,t5,g0,t10,g0)"
   integer, target :: M(5,4)
   integer, pointer :: N(:,:)
   integer :: i
   integer :: j

   M = reshape( [(42+i,i=1,size(M))], shape=[size(M,dim=1),size(M,dim=2)] )
   M(1,2) = 3
   print fmtg, "j", "i", "M(j,i)"
   do i = 1, size(M,dim=2)
      do j = 1, size(M,dim=1)
         print fmtg, j, i, M(j,i)
      end do
   end do

   N(1:size(M),1:1) => M
   print fmtg, "j", "i", "N(j,i)"
   do i = 1, size(N,dim=2)
      do j = 1, size(N,dim=1)
         print fmtg, j, i, N(j,i)
      end do
   end do

   stop

end

Upon execution, you should get:

j   i    M(j,i)
1   1    43
2   1    44
3   1    45
4   1    46
5   1    47
1   2    3
2   2    49
3   2    50
4   2    51
5   2    52
1   3    53
2   3    54
3   3    55
4   3    56
5   3    57
1   4    58
2   4    59
3   4    60
4   4    61
5   4    62
j   i    N(j,i)
1   1    43
2   1    44
3   1    45
4   1    46
5   1    47
6   1    3
7   1    49
8   1    50
9   1    51
10  1    52
11  1    53
12  1    54
13  1    55
14  1    56
15  1    57
16  1    58
17  1    59
18  1    60
19  1    61
20  1    62

 

0 Kudos
Kusiek__Adam
Beginner
485 Views

Thank you for all these responses - the question was really simple and actually I did not expect such discussion. 

First - to clarify: 

I have to integrate with new software the subroutine (written by someone in the past) which uses the mentioned two ways of indexing. Since I am not familar so much with F77 I expected that this was allowed - but I see my assumption was wrong. 

The most simple way to solve this problem was to introduce some code lines for indices recalculating to use proper way of indexing. But on the other hand I do not wanted to put to much additional code lines which can degrade its performance. So my another idea was to check if there is sth. like in C/C++ (with pointer stuff) or Matlab (where you can use both indexing ways). 

The 'equivalance' is some solution but it does not work with automatic or dynamic arrays. 

Since I also want to avoid matrix reshaping (this must be done few times in code) so the only way will be to add some additional lines  for indices recalculating to use M(i,j) way of indexing. 

I think we can close the discussion at this point. 

Once again thank you for all your suggestions/comments

Best, 

Adam 

 

 

 

 

 

0 Kudos
Reply