Fortran array to array C. Stupid macro tricks required

I have this "simplified" fortran code

real B(100, 200) real A(100,200) ... initialize B array code. do I = 1, 100 do J = 1, 200 A(J,I) = B(J,I) end do end do 

One programming guru warned me that fortran processes data in column order efficiently, while c processes data efficiently in row order. He suggested that I carefully study the code and be prepared to switch loops around to maintain the speed of the old program.

Being the lazy programmer that I am, and given the days of effort and the mistakes that I will probably make, I began to wonder if there could be a #define method that would allow me to easily convert this code and easily.

Do you have any suggestions?

+4
source share
3 answers

In C, multidimensional arrays work as follows:

 #define array_length(a) (sizeof(a)/sizeof((a)[0])) float a[100][200]; a[x][y] == ((float *)a)[array_length(a[0])*x + y]; 

In other words, they are really flat arrays, and [][] is just syntactic sugar.

Suppose you did this:

 #define at(a, i, j) ((typeof(**(a)) *)a)[(i) + array_length((a)[0])*(j)] float a[100][200]; float b[100][200]; for (i = 0; i < 100; i++) for (j = 0; j < 200; j++) at(a, j, i) = at(b, j, i); 

You go sequentially from memory and pretend that a and b actually laid out in column order. It's kind of terrible in this a[x][y] != at(a, x, y) != a[y][x] , but as long as you remember that he cheated like this, that's it will be fine.

Edit

Man, I feel stupid. The purpose of this definition is to make at(a, x, y) == at[y][x] , and it is. Therefore, it is much simpler and easier to understand.

 #define at(a, i, j) (a)[j][i] 

It would be better than what I suggested above.

+4
source

Are you sure your FORTRAN guys did everything right?

The code fragment that you originally placed already accesses arrays in lowercase order (which is "inefficient" for FORTRAN, "effective" for C).

As illustrated by a code snippet and as indicated in your question, getting this โ€œcorrectโ€ may be error prone. Worry about the FORTRAN code being ported to C first without worrying about such details. When the port is working, then you can worry about changing access to the column order for row access (if it really matters after the port is up).

+4
source

One of my first college assignments was to fix the long-term C application that was ported from FORTRAN. The arrays were much larger than yours, and it took about 27 hours per turn. After he fixed it, they ran about 2.5 hours ... pretty sweet!

(OK, it really wasnโ€™t assigned, but I was curious, and I found a big problem with their code. Some of the old timers did not like me, despite this fix.)

It would seem that the same problem is found here.

 real B(100, 200) real A(100,200) ... initialize B array code. do I = 1, 100 do J = 1, 200 A(I,J) = B(I,J) end do end do 

Your loop (to be a good FORTRAN) would be as follows:

 real B(100, 200) real A(100,200) ... initialize B array code. do J = 1, 200 do I = 1, 100 A(I,J) = B(I,J) end do end do 

Otherwise, you are navigating through arrays in a row, which can be very inefficient.

At least I believe that it would be in FORTRAN - it has been a long time.


I saw that you updated the code ...

Now you want to change the loop control variables so that you iterate through the rows and then inside, iterate through the columns if you convert to C.

+2
source

All Articles