Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Fortran's rules for passing arrays to a Sub?

Status
Not open for further replies.

kubota100

Technical User
Feb 14, 2012
8
AU
It's unclear to me exactly what the Fortran language passes from a calling routine to a called routine when the calling variables are arrays, and the calling and called variable types do not match!

My confusion relates to exactly what is being received by the called routine - array elements (element values), memory references to the element values, entire arrays, etc... I haven't been able to identify the rules used. Perhaps there are subtle rules at play here.

Four specific examples demonstrate my areas of confusion, and I'm hoping someone can clarify the rules for me please (the examples are drawn from a working Fortran program, where the calling and called variables are exactly in the forms shown below):

1. calling: A(1:,1) 2-dimensional array passed to
1. called: B 1-dimensional array

2. calling: C(1) 1-dimensional array passed to
2. called: D integer

3. calling: E(1:,var1) 2-dimensional array passed to
3. called: F 1-dimensional array

4. calling: G(var2) 1-dimensional array passed to
4. called: H integer

Any clarification of the data received by the called routines in the four examples will be greatly appreciated.


 
If you do nothing special, Fortran behaves as in "pass-by-reference" ...to achieve "pass-by-value" you really need to go out of your way, I think I had to do that once for compatibility when calling C-language subroutines.

Fortran programmers seemed to have been a tricky bunch, for a while; I would like to think that they are much better behave now, that they actually teach programming in school...Fortran is so old, that I wonder if many of the ones that used it before ever took a programming class...I now I inherited 30+ year old programs in my previous job.

Old programs take advantage of various memory tricks...they could even store characters into integer or real variables, etc. Certainly, they take advantage of how arrays are allocated in memory to use 1-D arrays to refer to what otherwise was a 2-D one.

o.k., I already wrote all that, and now that I look at your examples, I don't think I see anything wrong with them...

1.- They are passing an entire column of the 2-D matrix and it is being placed into a single array...I mean, it is not like they are passing A(1,1) (address to the very first item), they are actually passing A(1:,1)...that's an entire column.

2.- C(1) refers to the very first item in the arrays, but by itself, it IS a scalar...so, you could very well put into a variable declared as scalar, nothing wrong with that.

3.- Same as (1)

4.- Same as (2)

Does this help?

By the way, don't be shy to test stuff in a trivial 10-line program and test this stuff and see what you get and can achieve.
 
Thank you for the excellent clarifying detail.

On a slightly different tangent, if I was translating the Fortran code for running as VBA code, where calling type must equal called type, then, as an extension to my example 1 above, would you recommend firstly copying the first column of the 2-dim array A to a single dimension array, say X(), and then pass the single dimension array X() to the called routine? Would this be considered as a possible "normal" coding practice for such purposes, so as to save modifying the called routine?

Would you recommend another way to deal with it? (I'm only referring to the principles here of course).

Thanks for any advice.
 
A(1:,n) refers to all the elemnts in column n. This is standard FORTRAN 90/95, nothing of the 'tricky' type.

If you introduce X(1:) = A(1:,n) and using X instead of A in your call to your routine, the only thing you get is that modifying B() in your routine does not have any effect on A(). But you could achieve this goal by proper coding of the routine as well. And to make sure of it, you can give the attribute INTENT (IN) to B() in the called routine.

Ah, and yes, when you studied engineering in the old days you could attend a two weeks course of FORTRAN programming (FORTRAN IV !) as I did in 1972. You had to punch your code on cards, deliver them to the operators and next day you received a paper printout, usually of compiler error-messages. To code and debug a 50 statement prog could be a matter of more than a week or two.
[/nostalgia]

Norbert


The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
Thank you for your advice.

1. Say, further to the example discussed, if the X array passed to the sub was modified by the sub, for returning back to the calling routine, then in the calling routine, can I copy the X array back to the same column of A using the reverse statement:

A(1:,n)=X(1:)

Would this work?

2. Also, as an example of the syntax, could I copy the 1-dim array Y to a 2-dim array AA as follows, so the Y array is copied in as a row in AA:

AA(m,1:) =Y(1:)

Will this do the job?

Thanks again for any assistance.
 
kubota, I am not trying to be mean, here, or nothing, please forgive how all this writing comes across...I am simply being devil's advocate...

Like I suggested before....instead of asking the question on whether you can do this or that...why don't you write a 20-line trivial Fortran program where you initialize your matrix, pass it to a subroutine, modify something and see what effect it has on your calling context or whether you need to explicitly pass it back, etc?

If you do NOT have the ability to compile Fortran and your objective is to port this over to VB...what's the point of your last two question? Knowing what is being done in Fortran, do whatever you have to do in VB to achieve what's needed.

Or, keep the Fortran program altogether...sure, Fortran is over 50 years old, but there is absolutely nothing wrong with it...I would program in Fortran before I do anything on C, C++, let alone VB...but I understand why so many people do...



 
Thank you for your response.

Unfortunately, I don't have the ability to compile Fortran code, and my knowledge of Fortran is quite basic, as you can tell!

However, I may attempt to translate some Fortran code (Quadpack integration package) over to VBA for running in Excel, and this is the driver behind my questions, to hopefully gain some insight into some of the "tricker" (to me!) array operations of Fortran, to help complete my picture of these issues.

My last questions were to expand further on the previous information, expanding on Fortran's syntax and understanding via the added examples for completeness. I now feel a lot more confident in my Fortran syntax and array understanding as a result of the helpful answers provided, and the Quadpack translation should now be possible. These array issues were definite obstacles to me.

Thanks to you and gummibaer for such great help. I am most grateful.

(BTW, no harm done!).
 
As an extension to the principles discussed above, in trying to understand another part of an old Fortran program (I don't have a Fortran compiler):

Say a main program calls a sub:

=============================

Function ...

MainArray(100)

MainArray(10) = 25

CALL MYSUB(MainArray(10))
'
'
'
SUBROUTINE MYSUB (X)
'
'
AA = X(3)
BB = X(1)
CC = X

'=============================

1. What is the relationship between the contents of AA and the MainArray contents? Is there an offsetting rule used?

2. Will BB contents equal MainArray(10) contents which equals 25?

3. Is: CC = X a valid statement, and if so, what will be the contents of CC?

Perhaps I'm well off the mark here... These principles can be challenging!

Thanks for any assistance.
 
Hhhmmm...it's tough to answer those questions when I don't have the entire program and I don't have the practice of doing such things.

First of all, I presume that X was declared as an array inside the subroutine, was it not? It'd better.

Without writing a program and testing it, this is what I think will happen:

AA = X(3) = MainArray(12)
BB = X(1) = MainArray(10)
CC = X = MainArray(10:10+N-1)

In other words, the last statement is an entire array assignment a-la-matlab, BUT, from the point of view of X; so, if X was declared to be of length N, only N elements out of MainArray will be passed to CC.

By the way, kubota, here are a few more mean questions for you that I am curious about:

do you have an idea of what the Fortran program is supposed to do?

do you know how? no? a little? so so? exactly?

I guess if you knew exactly, you could be implementing the algorithm without having to refer to the Fortran program?

do you have an executable from the Fortran program that you can run?

when you are done with the VB program...how are you going to know if what you have implemented is correct? Do you have anything to compare it to?

 
Thank you for your fast response and helpful advice.

Hopefully the following will answer some of the questions.

The program I'm translating to VB is the Clenshaw-Curtis numerical integration program originally published in 1972 as TOMS Algorithm 424. The link to the Fortran listing on John Burkardt's site is:


My questions refer to the call to sub R3PASS just after label 150 in the main program. My key issue is trying to understand the nature of the three parameters in the array CSXFRM passed from the main program to the sub, and the parameters then being used by the sub in the arrays X0, X1 and X2, in regards to the relationship between the calling and called arrays.

Mmmm, hope this assists.

I'd be most grateful for any clarity here.
 
Wow...that's some confusing algorithm.

First, as indicated by the link, the program is supposed to be Fortran77...so, there is no a-la-matlab entire-array-at-a-time assignment at this point; that became available in Fortran90. Thankfully, I don't see any instance of it in such subroutine...so, your posting and question about "CC = X" does not happen here...every time the dynamically allocated arrays X0, X1, X2 are used on the left hand side of the equation, they are being addressed as scalars, i.e., one entry at a time.

What was said in my previous posting still stands. I think you are good to go.

...but you still did not answer my question regarding how in the world you are going to know if what you implement is correct. I guess for as long as this algorithm is this famous, there must be some input/output examples out there that you can use to test?


 
Ah, it's good to know how those arrays are connected. I believe I'm on track now.

Re the testing of the program, all I need to do is run some integral calculations - simple ones such as INT (0,1) 1/SQRT(x) dx = 2 (exactly), and INT (0,1) LN(x) dx = -1 (exactly). I look forward to getting those results!

Thank you very much for your advice and for your generosity with your knowledge and time. You help to make this forum such a wonderful resource.
 
Woops - thenks for the Fortran DLL links and ideas. I'll look further into that approach.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top