question about negative indices in fortran 77 
Author Message
 question about negative indices in fortran 77

Dear friends,

I am working with an "inherited" program written in fortran 77. The
program works fine as it is (both on Compaq compilers for windows and
Intel compilers for linux), but now I'm doing some modifications and I
need to debug it. The problem is that some (I guess very old)
subroutines use negative indices in arrays, so whenever I compile
with Intel Fortran 8.1 for linux with -C option, the program stops at
these calls and doesn't arrive at the interesting parts.

I'm checking for violations of array bounds because the program is doing
something really weird: a variable is changing its value inside a
subroutine where it isn't touched (neither read nor written!). The only
thing that I've seen trigger this kind of behavior in other languages
has always been array bounds violations (even just reading forbidden
memory).

Now we arrive at the interesting part. Let's say I have the following
declaration at the beginning of a subroutine:

      implicit real*8 (a-h,o-z)
      real*8 e(m*n),d(m*n),c(m*n),b(m*n),a(m*n),
     &   ef(m*n),df(m*n),cf(m*n),bf(m*n),af(m*n),
     &   x(m*n),y(m*n),r(m*n),up(m*n),aux(m*n)

The way I understand it, an expression like d(-i) is equivalent to
e(m*n-i). Using this I can translate the whole subroutine into something
more sensible that the de{*filter*} will allow. I actually did it with one
subroutine, and the results are identical to what I obtained before the
translation. Now I want to do the same thing to another subroutine that
is very similar, but I have the following problem: there is a reference
to e(-i), but since "e" is the first array in the declaration, where is
the memory allocated for this?

Please forgive me if this is a silly question in this forum. I am mostly
a C/C++ guy and my head tends to explode just a bit when I see code that
depends on the details of memory layout :-)

Thank you very much in advance,

--
Jose Miguel Pasini
To reach me, replace the numbers with actual numbers.



Sun, 17 Jun 2007 23:53:52 GMT  
 question about negative indices in fortran 77

Quote:

> Dear friends,

> I am working with an "inherited" program written in Fortran 77. The
> program works fine as it is (both on Compaq compilers for windows and
> Intel compilers for linux), but now I'm doing some modifications and I
> need to debug it. The problem is that some (I guess very old)
> subroutines use negative indices in arrays, so whenever I compile
> with Intel Fortran 8.1 for linux with -C option, the program stops at
> these calls and doesn't arrive at the interesting parts.

> I'm checking for violations of array bounds because the program is doing
> something really weird: a variable is changing its value inside a
> subroutine where it isn't touched (neither read nor written!). The only
> thing that I've seen trigger this kind of behavior in other languages
> has always been array bounds violations (even just reading forbidden
> memory).

Yes, that's always the most likely reason.  It's possible to
also get subroutine arguments messed up, (maybe out of
order), but that's unlikely for an old working code.

Quote:

> Now we arrive at the interesting part. Let's say I have the following
> declaration at the beginning of a subroutine:

>       implicit real*8 (a-h,o-z)
>       real*8 e(m*n),d(m*n),c(m*n),b(m*n),a(m*n),
>      &   ef(m*n),df(m*n),cf(m*n),bf(m*n),af(m*n),
>      &   x(m*n),y(m*n),r(m*n),up(m*n),aux(m*n)

> The way I understand it, an expression like d(-i) is equivalent to
> e(m*n-i).

No, not really.  Fortran doesn't define what happens when
array subscripts go out of bounds.  Many compilers will lay
out memory in the order arrays are declared.  If they
do, then, in your case above, e is sort of equivalent to
d with negative out-of-bounds subscripts.  BUT, there is
no guarantee or requirement that memory be assigned in
that order.  Many optimizing compilers will lay out memory
in the order arrays are used (and never assign actual memory
for unused arrays), others will overlap arrays that are only
used in discontiguous parts of the program.  And the
behavior usually depends on the optimization level,
compiler release, etc.  There's no guarantee.

Quote:
>Using this I can translate the whole subroutine into something
> more sensible that the de{*filter*} will allow. I actually did it with one
> subroutine, and the results are identical to what I obtained before the
> translation. Now I want to do the same thing to another subroutine that
> is very similar, but I have the following problem: there is a reference
> to e(-i), but since "e" is the first array in the declaration, where is
> the memory allocated for this?

There really isn't any specific memory.  If the arrays
are on the stack, then e(-i) is mucking around with
something from it's callers stack memory (or even further
up the call chain if "i" is large enough).  If the arrays
are statically assigned to memory, then this subroutines
memory probably comes just after the memory of whatever
subroutine was loaded before it, likely a pseudo-random
oeganization from your point of view.  So what
happens will depend on the order subroutines are loaded
or called, and you just can't count on it.

Quote:

> Please forgive me if this is a silly question in this forum. I am mostly
> a C/C++ guy and my head tends to explode just a bit when I see code that
> depends on the details of memory layout :-)

Yeah, it's a real shame when people write code like that.
Fortran doesn't constrain memory layouts to allow optimizers
wide latitude in doing optimizations.  Unfortunately,
people often look at a particular result and assume that
the standard forces that behavior when, in fact, they are
just lucky.

Realistically, your only hope is remove the negative
subscripts.  That's likely to mean you'll have to figure
out why the original person wrote it that way and recode
the bad parts.  This is the only way you can also run
the program with bounds checking turned on.  If the
code fails with bounds checking turned on, there's
always the PRINT statement for debugging.

For a second only hope, try compiling with ever
optimization turned off.  That's likely to give the
same memory layout as the original program did back in
1977 (when optimizers were less aggressive and stacks
were less common).

If they don't work, then your next only hope is to fool
around with EQUIVALENCE to force things to be in the correct
order.  Something like
       real*8  memory(many*m*n)
       equivalence (memory(1), e(1))
       equivalence (memory(m*n+1), d(1))
       equivalence (memory(2*m+n+1, c(1))
...
this is what the original coder probably assumed would
happen.  For your subroutine that fails with a
reference to e(-i), try putting a pad before the
big chunk of memory.  Something like
       real*8  pad(m*n+1)
       equivalence (pad(m*n+1), memory(1))
        equivalence (memory(1), e(1))
that will give you something reasonably well defined
before e.  Bounds checking won;t work here, because you'll
be going out of bounds ;) .

Finally, your really last only hope is to find the orginal
programmer and shoot him.  That won't help you today,
but it will in the long run ;) .

Dick Hendrickson

- Show quoted text -

Quote:

> Thank you very much in advance,



Mon, 18 Jun 2007 00:21:53 GMT  
 question about negative indices in fortran 77
...

Quote:
> Now we arrive at the interesting part. Let's say I have the following
> declaration at the beginning of a subroutine:

>       implicit real*8 (a-h,o-z)
>       real*8 e(m*n),d(m*n),c(m*n),b(m*n),a(m*n),
>      &   ef(m*n),df(m*n),cf(m*n),bf(m*n),af(m*n),
>      &   x(m*n),y(m*n),r(m*n),up(m*n),aux(m*n)

> The way I understand it, an expression like d(-i) is equivalent to
> e(m*n-i).

No guarantee of that although it would be common for memory to allocated
consecutively there is no requirement for it.  It would be possible if
the arrays were actually in common or there were some equivalence'ing,
but would need to see that and there would be restrictions on what
were/are arguments to the subroutine as well.

Bounds checking should catch it...

Quote:
> Using this I can translate the whole subroutine into something
> more sensible that the de{*filter*} will allow. I actually did it with one
> subroutine, and the results are identical to what I obtained before the
> translation. Now I want to do the same thing to another subroutine that
> is very similar, but I have the following problem: there is a reference
> to e(-i), but since "e" is the first array in the declaration, where is
> the memory allocated for this?

May not have been unless one of the above situations holds...this looks
like either a mistake or is relying on a fortuitous operational
characteristic of the previous compilers used...

Quote:
> Please forgive me if this is a silly question in this forum. I am mostly
> a C/C++ guy and my head tends to explode just a bit when I see code that
> depends on the details of memory layout :-)

Me too, excepting where noted above and I don't recommend that as normal
practice, either!

This looks like an abominable piece of code at first blush...



Mon, 18 Jun 2007 00:19:15 GMT  
 question about negative indices in fortran 77



Quote:
> Dear friends,

> I am working with an "inherited" program written in Fortran 77. The
> program works fine as it is (both on Compaq compilers for windows and
> Intel compilers for linux), but now I'm doing some modifications and I
> need to debug it. The problem is that some (I guess very old)
> subroutines use negative indices in arrays, so whenever I compile
> with Intel Fortran 8.1 for linux with -C option, the program stops at
> these calls and doesn't arrive at the interesting parts.

It's not Fortran 77 if it uses negative subscripts without corresponding
declaration of the lower bound.  As others pointed out, all compilers have
options to catch the violation, which may help you determine when you have
patched up the source successfully, should you choose that route.


Mon, 18 Jun 2007 00:58:55 GMT  
 question about negative indices in fortran 77

Quote:

> Dear friends,

> I am working with an "inherited" program written in Fortran 77. The
> program works fine as it is (both on Compaq compilers for windows and
> Intel compilers for linux), but now I'm doing some modifications and I
> need to debug it. The problem is that some (I guess very old)
> subroutines use negative indices in arrays, so whenever I compile
> with Intel Fortran 8.1 for linux with -C option, the program stops at
> these calls and doesn't arrive at the interesting parts.

Negative subscripts are almost certainly a programming error. Errors
have a {*filter*} habit of staying hidden for a very long time.

Now for the exceptions:

You might have declarations of the form  REAL X(-10:10)  which makes
the subscripts from -10 to 10 (all 21 values) the intended values.
This is good style. Hopefully you have not just tossed the
declaration as something that looked too strange.

An extreme form of game playing is to use the "sequence association"
rules to allow reaching "backwards" in common. For a 1:n declared
array in common a subscript of 0 will be the data item before the
array in common. This is a form of behavior which allows you to
take revenge on the original programmer. Good luck in fixing both
such outrageous programming and also in finding and fixing the
original programmer. (Yes I have seen this done. The application
lead to indices of 0 and the programmer had read too much assembly
code so viewed the compiler as awkward shorthand for assembly.
This was a long time ago so I will not name either the company or
the programmer.)

Quote:
> I'm checking for violations of array bounds because the program is doing
> something really weird: a variable is changing its value inside a
> subroutine where it isn't touched (neither read nor written!). The only
> thing that I've seen trigger this kind of behavior in other languages
> has always been array bounds violations (even just reading forbidden
> memory).

> Now we arrive at the interesting part. Let's say I have the following
> declaration at the beginning of a subroutine:

>       implicit real*8 (a-h,o-z)
>       real*8 e(m*n),d(m*n),c(m*n),b(m*n),a(m*n),
>      &   ef(m*n),df(m*n),cf(m*n),bf(m*n),af(m*n),
>      &   x(m*n),y(m*n),r(m*n),up(m*n),aux(m*n)

> The way I understand it, an expression like d(-i) is equivalent to
> e(m*n-i). Using this I can translate the whole subroutine into something
> more sensible that the de{*filter*} will allow. I actually did it with one
> subroutine, and the results are identical to what I obtained before the
> translation. Now I want to do the same thing to another subroutine that
> is very similar, but I have the following problem: there is a reference
> to e(-i), but since "e" is the first array in the declaration, where is
> the memory allocated for this?

I have never heard of any compiler that did modulo subscripts
automatically. They would be really very nice for some applications.

Some hardware does circular buffering for powers of two so that does
not count as an exception.

- Show quoted text -

Quote:
> Please forgive me if this is a silly question in this forum. I am mostly
> a C/C++ guy and my head tends to explode just a bit when I see code that
> depends on the details of memory layout :-)

> Thank you very much in advance,



Mon, 18 Jun 2007 01:19:17 GMT  
 question about negative indices in fortran 77


Quote:
> Now we arrive at the interesting part. Let's say I have the following
> declaration at the beginning of a subroutine:
>       implicit real*8 (a-h,o-z)
>       real*8 e(m*n),d(m*n),c(m*n),b(m*n),a(m*n),
>      &   ef(m*n),df(m*n),cf(m*n),bf(m*n),af(m*n),
>      &   x(m*n),y(m*n),r(m*n),up(m*n),aux(m*n)
> The way I understand it, an expression like d(-i) is equivalent to
> e(m*n-i).

If this code worked, there is something that ties all those
declared arrays together somehow.  Since this is f77, all
those arrays aren't automatic arrays, so they must be dummy
arguments or in common.  You must include the code from the
subroutine statement up to the first executable statement
within the subroutine.  Then we can determine whether the
arrays are dummy arguments or in common.  If they are dummies,
your compiler should have the capacity to give you a
traceback so you can know where the subroutine was fatally
called from.  From there we might conceivably need the
declarations of the calling subprogram and the values of
any actual arguments.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end



Mon, 18 Jun 2007 03:21:34 GMT  
 question about negative indices in fortran 77
On Wed, 29 Dec 2004 12:21:34 -0700

Quote:

> message

> > Now we arrive at the interesting part. Let's say I have the
> > following declaration at the beginning of a subroutine:

> >       implicit real*8 (a-h,o-z)
> >       real*8 e(m*n),d(m*n),c(m*n),b(m*n),a(m*n),
> >      &   ef(m*n),df(m*n),cf(m*n),bf(m*n),af(m*n),
> >      &   x(m*n),y(m*n),r(m*n),up(m*n),aux(m*n)

> > The way I understand it, an expression like d(-i) is equivalent to
> > e(m*n-i).

> If this code worked, there is something that ties all those
> declared arrays together somehow.  Since this is f77, all
> those arrays aren't automatic arrays, so they must be dummy
> arguments or in common.  You must include the code from the
> subroutine statement up to the first executable statement
> within the subroutine.  Then we can determine whether the
> arrays are dummy arguments or in common.  If they are dummies,
> your compiler should have the capacity to give you a
> traceback so you can know where the subroutine was fatally
> called from.  From there we might conceivably need the
> declarations of the calling subprogram and the values of
> any actual arguments.

> --

James,

Thank you very much for the comments. You nailed it on the head!  I'd
like to also thank the other people that have answered so promptly.
Indeed, the arrays are dummy arguments, and the subroutine that calls
this one uses arguments from a common block, where they're declared in a
different order. Actually, in the common block they're declared like
this (the same letters are used)

real*8 d(nxy),e(nxy), etc.

instead of the other way around. Here nxy=(m+2)*(n+2). Therefore, in
order to sanitize the program I should change the declarations in the
subroutine to

real*8 e((m+2)*(n+2)),d((m+2)*(n+2)), etc

and then change the reference to e(-i) into d((m+2)*(n+2) - i).

Thanks again,

--
Jose Miguel Pasini
To reach me, replace the numbers with actual numbers.



Mon, 18 Jun 2007 03:45:08 GMT  
 question about negative indices in fortran 77

Quote:

> On Wed, 29 Dec 2004 12:21:34 -0700


> > message

> > > Now we arrive at the interesting part. Let's say I have the
> > > following declaration at the beginning of a subroutine:

> > >       implicit real*8 (a-h,o-z)
> > >       real*8 e(m*n),d(m*n),c(m*n),b(m*n),a(m*n),
> > >      &   ef(m*n),df(m*n),cf(m*n),bf(m*n),af(m*n),
> > >      &   x(m*n),y(m*n),r(m*n),up(m*n),aux(m*n)

> > > The way I understand it, an expression like d(-i) is equivalent
to
> > > e(m*n-i).

> > If this code worked, there is something that ties all those
> > declared arrays together somehow.  Since this is f77, all
> > those arrays aren't automatic arrays, so they must be dummy
> > arguments or in common.  You must include the code from the
> > subroutine statement up to the first executable statement
> > within the subroutine.  Then we can determine whether the
> > arrays are dummy arguments or in common.  If they are dummies,
> > your compiler should have the capacity to give you a
> > traceback so you can know where the subroutine was fatally
> > called from.  From there we might conceivably need the
> > declarations of the calling subprogram and the values of
> > any actual arguments.

> > --

> James,

> Thank you very much for the comments. You nailed it on the head!  I'd
> like to also thank the other people that have answered so promptly.
> Indeed, the arrays are dummy arguments, and the subroutine that calls
> this one uses arguments from a common block, where they're declared
in a
> different order. Actually, in the common block they're declared like
> this (the same letters are used)

> real*8 d(nxy),e(nxy), etc.

> instead of the other way around. Here nxy=(m+2)*(n+2). Therefore, in
> order to sanitize the program I should change the declarations in the
> subroutine to

> real*8 e((m+2)*(n+2)),d((m+2)*(n+2)), etc

> and then change the reference to e(-i) into d((m+2)*(n+2) - i).

> Thanks again,

> --
> Jose Miguel Pasini
> To reach me, replace the numbers with actual numbers.

Wow, I thought I had seen most of the "clever" programming
techniques, but this is a new one for me.

My biggest regret is that you're coming from a C++ background
and this is going to leave a bad taste in your mouth about
Fortran.  Remember that you can write {*filter*}in any language,
and I'm sorry you don't have a better Fortran example to start
with.

-Scott



Mon, 18 Jun 2007 22:44:29 GMT  
 question about negative indices in fortran 77
On Wed, 29 Dec 2004 17:19:17 GMT, Gordon Sande

[snip]

Quote:
>An extreme form of game playing is to use the "sequence association"
>rules to allow reaching "backwards" in common. For a 1:n declared
>array in common a subscript of 0 will be the data item before the
>array in common. This is a form of behavior which allows you to
>take revenge on the original programmer. Good luck in fixing both

[snip]

I'm not sure I'd call it "extreme" or harbor thoughts of revenge.
Setting it up via COMMON is {*filter*}, since COMMONs can wind up confusing
enough without added tricks.  But if this were set up via EQUIVALENCE,
e.g.,

dimension a(100),adummy(2)
equivalence (a,adummy(2))

then you have the equivalent of a(0:100), and the EQUIVALENCE draws
attention to it.  As well as being the official way to arrange
storage.

I used to do this in FORTRAN IV when I had coordinates starting at 0
so that I could do stuff like

x = dx*float(i)

rather than

x = dx*float(i-1)

and avoid off-by-one errors without having to think too hard.

Obsolete now that we can do (n1:n2), but it did make my programs
easier to follow back then.

Ken Plotkin



Tue, 19 Jun 2007 02:12:38 GMT  
 
 [ 9 post ] 

 Relevant Pages 

1. question about negative indices in fortran 77

2. Fortran 77 simple code question

3. some fortran 77 language question

4. Fortran 77 File I/O Write and Format Question

5. Fortran 77 question

6. Fortran 77 question

7. A few basic questions about FORTRAN 77 program

8. Question on FORtran 77 standard

9. File access question (Fortran 77) - please e-mail answer

10. Question about HP 9000/700 Fortran 77

11. Fortran 77 question

12. Fortran 77 syntax question

 

 
Powered by phpBB® Forum Software