Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

Fortran Programming Language

Double precision arrays and subroutines


Hello all,

I am currently in the process of porting some Fortran code to Java. I
picked up the basics of Fortran pretty quickly (love the array
indexing from 1, I wish C did that...), but have encountered a
strangeness related to Double precision arrays being passed to
subroutines and would appreciate clarifications on what is happening
from gurus.

The code I am porting defines some integer and double precision arrays

    integer          maxn, nx
    parameter        (maxn=256, nx=10)
    Double precision workd(3*maxn)
    integer          ipntr(11)

After some processing, it then calls a subroutine

    call av (nx, workd(ipntr(1)), workd(ipntr(2)))

I looked at the definition for av, expecting it to require an integer
and two doubles. However, the first few lines of av are

    subroutine av (nx, v, w)
      integer           nx
      Double precision  v(nx*nx), w(nx*nx)

which I believe means that it is expecting an integer and two double
arrays.

My only explanation would be that workd(ipntr(1)) is sending a pointer
to this element in the array, and then av is considering that pointer
to be the start of an nx * nx array.

Clarifications would be greatly appreciated.

Thanks and kind regards,
Shug

"Shug Boabby" <Shug.Boa@gmail.com> wrote in message

news:1176392603.434913.8170@y5g2000hsa.googlegroups.com...

> My only explanation would be that workd(ipntr(1)) is sending a pointer
> to this element in the array, and then av is considering that pointer
> to be the start of an nx * nx array.

> Clarifications would be greatly appreciated.

Your conclusion is correct, although the use of the term 'pointer' (which
has a stricter meaning in Fortran) would be better replaced by 'index'.

Regards,

Mike Metcalf

On Apr 12, 11:43 am, "Shug Boabby" <Shug.Boa@gmail.com> wrote:

You are correct. Others may explain what is going on in more detail.
Also remember that in Fortran, arrays are stored in column-major
order, which will affect how the elements of 1-D array workd are used
to fill v and w.

To add to what other people have said: Yes, that's essentially what's
happening, but it's not legal Fortran code.

What happens is that, in Fortran, these two program units are
independent.  The subroutine and the program that calls it are compiled
separately, and normally the compiler doesn't know about one when it's
compiling the other.  Although they're usually in the same source file,
it's useful to imagine that they're in separate files being compiled at
separate times and then linked together.

Thus, the compiler doesn't know about the mismatch between the fact that
the subroutine call is being given an integer and two scalar doubles,
and the subroutine declaration is expecting an integer and two double
arrays.  It compiles the subroutine call to pass along scalar doubles,
and it compiles the subroutine to expect double arrays.

This sort of thing is, in most cases, called a "bug".

In this case, however, it seems that the way that this Fortran compiler
works is that on the machine-code level it doesn't actually pass the
values; it passes their location in memory -- that is, a "pointer" in
the C-language sense of the word.  And so, for that particular compiler,
this piece of code happens to work right.

Other compilers do things like passing the size of an array along with
its location in memory, and thus on those compilers this code will fail
in ugly and difficult-to-debug ways.  But apparently this program was
never (we hope!) run on such a compiler....

- Brooks

P.S. Note that, in more recent versions of Fortran, there are much
better ways to write this code -- both to allow the compiler to check
and make sure the subroutine does match the subroutine call, and to pass
sections of arrays to subroutines.  Please don't judge modern Fortran by
this historical ugliness!  :)

--
The "bmoses-nospam" address is valid; no unmunging needed.

Shug Boabby wrote:
> The code I am porting defines some integer and double precision arrays

>     integer          maxn, nx
>     parameter        (maxn=256, nx=10)
>     Double precision workd(3*maxn)
>     integer          ipntr(11)

> After some processing, it then calls a subroutine

>     call av (nx, workd(ipntr(1)), workd(ipntr(2)))

Something else I should mention, which I didn't think to mention in my
previous reply: This code appears to have been written before Fortran
had a standard way for dynamically allocating memory.  This particular
idiom looks like a fairly common way of working around that --
essentially, what's probably happening is that the ipntr values are
acting to dynamically "allocate" bits of the workd array for various
uses, and then it's using a compiler trick to treat the pieces as
individual arrays.

In a language such as Java or modern Fortran, you're probably much
better off eliminating the workd array and dynamically allocating the
arrays that you need instead.

- Brooks

--
The "bmoses-nospam" address is valid; no unmunging needed.

On 2007-04-12 16:40:20 -0300, Brooks Moses
<bmoses-nos@cits1.stanford.edu> said:

It is only a "bug" when there is a type mismatch. Passing an array element to
provide an offset into an array is legal and common in much older code. It
is called an array slice in modern terminology if one is willing to overlook
some tecnical issues.

Separate compilation is used to cheat on type mismatchs for a common form
of "dynamic" allocation from the bad old days before dynamic allocation
came to Fortran.

This is the feature of Fortran that leads many to make the claim that
Fortran uses pass by reference semantics. It has too many problems to
be a useful summary even if it captures some of the spirit of passing
an array element to an array.

Since the original question was about some legacy code it is quite likely
that the old style do it yourself storeage allocation was in use. Complete
with deliberate type mismatch.

> In this case, however, it seems that the way that this Fortran compiler
> works is that on the machine-code level it doesn't actually pass the
> values; it passes their location in memory -- that is, a "pointer" in
> the C-language sense of the word.  And so, for that particular
> compiler, this piece of code happens to work right.

> Other compilers do things like passing the size of an array along with
> its location in memory, and thus on those compilers this code will fail
> in ugly and difficult-to-debug ways.  But apparently this program was
> never (we hope!) run on such a compiler....

More likely when using assumed shape which is a Fortran 90 notion.

On Apr 12, 12:40 pm, Brooks Moses <bmoses-nos@cits1.stanford.edu>
wrote:

This code might be ugly, by modern standards, but it isn't illegal.
It's they way things were commonly done in Fortran77.  As long as the
user keeps track of things then this code will work fine.

Fortran has always passed what would be called pointers in C.

Googleer wrote:
> On Apr 12, 12:40 pm, Brooks Moses <bmoses-nos@cits1.stanford.edu>
> wrote:
>>Shug Boabby wrote:
>>>After some processing, it then calls a subroutine

(with the previously snipped)
     Double precision workd(3*maxn)

>>>    call av (nx, workd(ipntr(1)), workd(ipntr(2)))
>>>I looked at the definition for av, expecting it to require an integer
>>>and two doubles. However, the first few lines of av are
>>>    subroutine av (nx, v, w)
>>>      integer           nx
>>>      Double precision  v(nx*nx), w(nx*nx)
>>>which I believe means that it is expecting an integer and two double
>>>arrays.

(snip)

>>To add to what other people have said: Yes, that's essentially what's
>>happening, but it's not legal Fortran code.

Passing an array element to a subprogram expecting an
assumed size array is legal.  Dimensioning with an expression
was not legal Fortran 66.  I thought it wasn't Fortran 77,
but I am not sure about that one.

>>What happens is that, in Fortran, these two program units are
>>independent.  The subroutine and the program that calls it are compiled
>>separately, and normally the compiler doesn't know about one when it's
>>compiling the other.  Although they're usually in the same source file,
>>it's useful to imagine that they're in separate files being compiled at
>>separate times and then linked together.

Passing a scalar variable or constant would not be legal, though
would likely work for the reason you say.  Passing an array
element is very different, according to the standard, and works
according to the standard.  That is, assuming that the types
agree.

(snip)

>>Other compilers do things like passing the size of an array along with
>>its location in memory, and thus on those compilers this code will fail
>>in ugly and difficult-to-debug ways.  But apparently this program was
>>never (we hope!) run on such a compiler....

Yes, it doesn't work for assumed shape, which has different
ways to accomplish the same effect.

(snip)

> This code might be ugly, by modern standards, but it isn't illegal.
> It's they way things were commonly done in Fortran77.  As long as the
> user keeps track of things then this code will work fine.

Does Fortran 77 allow expressions in the size for such arrays?

-- glen

It's legal sequence association, isn't it?  Providing that there
actually are enough values remaining in workd to satisfy the usage in
subroutine av?

(I'm not even sure exactly which illegality you're confusing this with,
perhaps the old method of sequence associating with a dummy argument of
length 1 and then accessing beyond that bound?)

glen herrmannsfeldt wrote:
>> On Apr 12, 12:40 pm, Brooks Moses <bmoses-nos@cits1.stanford.edu>
>> wrote:
>>> To add to what other people have said: Yes, that's essentially what's
>>> happening, but it's not legal Fortran code.

> Passing an array element to a subprogram expecting an
> assumed size array is legal.

Fortran 77, 15.9.3.3: "If the actual argument is a noncharacter array
element name, the size of the dummy argument array must not exceed the
size of the actual argument array plus one minus the subscript value of
the array element. When an actual argument is a noncharacter array
element name with a subscript value of as, the dummy argument array
element with a subscript value of ds becomes associated with the actual
argument array element that has a subscript value of as + ds - 1 (Table
1,5.4.3)."

Thus, I stand corrected.

I still don't see how this can possibly work in a reasonable fashion
with copy-in, copy-out implementations, though, and up until now I
thought that anything that wouldn't work right under a reasonable
copy-in, copy-out implementation wasn't legal....  :(

> Dimensioning with an expression
> was not legal Fortran 66.  I thought it wasn't Fortran 77,
> but I am not sure about that one.

Fortran 77, 5.1.1.1: "The lower and upper dimension bounds are
arithmetic expressions, called dimension bound expressions, in which all
constants, symbolic names of constants, and variables are of type
integer."  So, yes, it is allowed.

- Brooks

--
The "bmoses-nospam" address is valid; no unmunging needed.

Brooks Moses wrote:

(snip)

>> Dimensioning with an expression
>> was not legal Fortran 66.  I thought it wasn't Fortran 77,
>> but I am not sure about that one.
> Fortran 77, 5.1.1.1: "The lower and upper dimension bounds are
> arithmetic expressions, called dimension bound expressions, in which all
> constants, symbolic names of constants, and variables are of type
> integer."  So, yes, it is allowed.

I was remembering trying one exactly like that in WATFIV some
years ago, which has many Fortran 77 features, but apparently
not that one.  Calling some matrix routine, like matrix inversion,
which uses a one dimensional array and calculates its own
subscript given N.  The array dimension then is N*N, but that
wasn't allowed.  I had to add an additional argument and pass
N*N to it.   WATFIV does bounds checking, and it is not
optional.

I thought it wasn't until Fortran 90 that variable expressions
were allowed.

thanks,

-- glen

Brooks Moses wrote:

(snip)

> I still don't see how this can possibly work in a reasonable fashion
> with copy-in, copy-out implementations, though, and up until now I
> thought that anything that wouldn't work right under a reasonable
> copy-in, copy-out implementation wasn't legal....  :(

The Fortran 66 compilers I know of that do copy-in/copy-out only
do it for scalar variables.  Note, though, that the (*) dimension
didn't exist in Fortran 66, so the called routine could use the
supplied dimension information for copy-in/out.  However most
programs I know of used the (1) dimension to get around that,
and there may be enough code that depends on it working that
there is no other way to do it.

The copy done by more recent compilers implementing assumed
shape arrays is different.  The calling routine does the copy,
and knows the size.

I was just looking into what Fortran I did.  I didn't realize that
it doesn't even have CALL/SUBROUTINE!  It does have functions, but
there is no description on how to write one in Fortran.  Also,
I hadn't noticed before, arrays are stored in memory in decreasing
subscript order.  (Convenient for decrementing index registers.)

-- glen

In article <hKqdnRuJQ4xHPoPbnZ2dnUVZ_tyin@comcast.com>,
glen herrmannsfeldt  <g@ugcs.caltech.edu> wrote:

>Googleer wrote:
>> On Apr 12, 12:40 pm, Brooks Moses <bmoses-nos@cits1.stanford.edu>
>> wrote:
>>>Shug Boabby wrote:
>>>>    subroutine av (nx, v, w)
>>>>      integer           nx
>>>>      Double precision  v(nx*nx), w(nx*nx)

>Does Fortran 77 allow expressions in the size for such arrays?

Yes: f77 5.1.1.1 says so, and 5.1.2.2 says they may involve variables
(such as nx) when the array name is a dummy argument, as v and w are.

-- John Harper, School of Mathematics, Statistics and Computer Science,
Victoria University, PO Box 600, Wellington 6140, New Zealand
e-mail john.har@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045

Shug Boabby wrote:

> I am currently in the process of porting some Fortran code to Java. I
> picked up the basics of Fortran pretty quickly (love the array
> indexing from 1, I wish C did that...)

It gets even better, Fortran can index arbitrary ranges. e.g.  

        real series(-n:n)

including a (C style) start at zero.

Googleer wrote:

> > sections of arrays to subroutines.  Please don't judge modern Fortran by
> > this historical ugliness!

> This code might be ugly, by modern standards, but it isn't illegal.
> It's they way things were commonly done in Fortran77.  As long as the
> user keeps track of things then this code will work fine.

And most of them still do regardless of the code's vintage. An
ignoramus, from Stanford no less, is clearly unaware how the quest
for speed was pursued before the modernity began to scar the language
beyond recognition.
On Apr 12, 3:42 pm, Brooks Moses <bmoses-nos@cits1.stanford.edu>
wrote:

> I still don't see how this can possibly work in a reasonable fashion
> with copy-in, copy-out implementations, though, and up until now I
> thought that anything that wouldn't work right under a reasonable
> copy-in, copy-out implementation wasn't legal....  :(

What you've missed is that the FORTRAN (<= 77) implementations
that did copy-in/copy-out did the copying in the callee, not
the caller.

Bob Corbett

robert.corb@sun.com wrote:

(snip on passing an array element actual argument to an
array dummy argument)

> What you've missed is that the FORTRAN (<= 77) implementations
> that did copy-in/copy-out did the copying in the callee, not
> the caller.

So if you follow the standard and use variables for the
dimensions it can do the copy.  But it was more usual to
use (1), or later (*), in which case the callee doesn't know
the actual length, either.

-- glen

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc