1

I've been given old FORTRAN code (parts of it seem to even suggest FORTRAN66, though I'm not sure), an excerpt of which is included below.

  PROGRAM FOO

  ! ------------------------------------------
  ! Code calling subroutine bar multiple times
  ! ------------------------------------------

  END

  subroutine bar(number,x,y,ic,imax)
  implicit real*8(a-h,o-z)
  dimension   x(1000),y(1000),ic(1000)

  rmin = -rmax

  do n = 1,number
    ic(n) = 0
    rmax = dmax1(rmax,sqrt(x(n)**2+y(n)**2))
    rmin = dmin1(rmin,sqrt(x(n)**2+y(n)**2))
  end do
  delta = 1.3*sqrt((rmax**2-rmin**2)/number)

  ! ---------
  ! More code
  ! ---------

  end

The line that caught my interest is the fourth one of the subroutine: rmin = -rmax. I've checked and the only occurrences of both rmin and rmax in the entire program are those shown here. They aren't even declared anywhere (and not present in any common block).

However, the code compiles and the program runs just fine. What's going on there? Is this a valid declaration/initialization for both variables? Are they both initialized to zero this way? I assume they are, because (going off of this post) initialization at the time of declaration would mean their value will be conserved between calls to bar and then the rmin = -rmax statement makes sense to me.

Any clarification on this kind of declaration/initialization would be greatly appreciated.

Community
  • 1
  • 1
Wouter
  • 161
  • 1
  • 6
  • Pure conjecture, but if the same subroutine is called several times and with no other calls going on in between, then the storage for `rmin` would be the same storage on each invocation, right? So it'd get whatever was left there from the previous call? – ClickRick Jun 15 '14 at 23:05
  • @ClickRick Do you mean: if `rmax` and `rmin` have the SAVE attribute, I would suspect after the first call to `bar` one would have `rmax = R` where `R` is the maximum value for all `n` of `r(n)` and `r(n)` is the `sqrt` statement in the second line of the `do`-loop. Then in the next call, `rmin` is set to `-R` and `rmax becomes `max(R,R')` where `R'` now is the maximum value for all `n` of `r(n)` (where the `r(n)` are different than those of the first call!). The line after the `do`-loop then seems to compute some sort of difference between the values of `rmax` in subsequent calls to `bar`. – Wouter Jun 15 '14 at 23:14
  • What I'm suggesting is that those values are occurring even without the SAVE attribute, simply on account of the same storage being allocated each time the subroutine is called, and nothing else having overwritten it in the meantime. – ClickRick Jun 15 '14 at 23:17
  • I don't think that's the case, since `rmin` and `rmax` would go out of scope after each call to `bar` and therefore lose their previous values. And I don't see why the same blocks in memory would be used for those variables in every call. Additionally, calls to other subroutines are made between calls to `bar`. But I am intrigued: if those other subroutines would not get called, are you saying the same blocks in memory would somehow automatically be used? – Wouter Jun 15 '14 at 23:26
  • That's the conjecture, yes. – ClickRick Jun 15 '14 at 23:27
  • Interesting, I'd like to see someone more knowledgeable comment on that. It seems kind of iffy to me, but then again I'm by no means an expert. – Wouter Jun 15 '14 at 23:31

2 Answers2

2

While rmin and rmax are implicitly declared, they seem to be uninitialized. Perhaps on the hardware or compiler on which this program originally ran variables were automatically initialized. This is not guaranteed behavior.

M. S. B.
  • 28,968
  • 2
  • 46
  • 73
  • My suspicion is that they are specifically *not* initialised, hence they keep their value from the previous call. Or from some other result entirely if an intervening call to another subroutine had taken place. – ClickRick Jun 15 '14 at 23:07
  • 1
    On many modern platforms / compilers, the uninitialized values could be anything. Suppose on the first call that rmax is 99E+6 and that sqrt (x**2 + y**2) never exceeds 1000. Then rmax won't change from 99E+9. Surely wrong! I think you should revise the code to initialize rmax so any negative value and rmin to a very large value, e.g., `huge(1.0D0)`. Likely many <= FORTRAN 77 compilers acted as if they had `SAVE`, but that is also not required by the code that you show. – M. S. B. Jun 15 '14 at 23:23
  • I'm looking into the specifics of the rest of the code to determine the idea behind it, but as I explained to Greg, the code (consisting of several hundred lines) is severely under-commented. So it's going to take a while. I'll provide an update when I know more. For now thanks for taking a look and answering! – Wouter Jun 15 '14 at 23:35
1

The key line here is

implicit real*8(a-h,o-z)

This means that any variable that starts with the letter a through h, or o through z, is implicitly declared to be a real*8. In your case, rmin and rmax both start with r, so they are implicitly declared.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • Thank you for your quick response! I understand that the `implicit` statement means they are `real*8`, but are they then also initialized by that statement? If so, is it safe to just assume that they are both initialized to zero? – Wouter Jun 15 '14 at 22:06
  • The Fortran specification does not require that uninitialised variables are initialised to zero. However, the compiler you are using, or the options used with that compiler, may do this for you. But it's a strange initialisation because if they do default to zero, then `rmin` will always end up being zero (even if it should have been another value). The code as given will only happen to work if `rmax` happens to start with a large *negative* value. Which certainly could be the case most of the time on a particular compiler and machine environment. – Greg Hewgill Jun 15 '14 at 22:12
  • I'm using the Intel Visual Fortran compiler (x11), if you're familiar with the behaviour of that particular compiler in this particular case... So default initialization like that would not result in the variables acquiring the SAVE attribute explained in the post I linked? – Wouter Jun 15 '14 at 22:18
  • Sorry, I'm afraid I'm not familiar with that particular compiler. However, it's certain that the use of the SAVE attribute would be exactly the wrong thing to do, because then `rmax` would never return a smaller value than it ever had before in any call to `bar`. – Greg Hewgill Jun 15 '14 at 22:20
  • Is that really so? If `rmax` and `rmin` have the SAVE attribute, I would suspect after the first call to `bar` one would have `rmax = R` where `R` is the maximum value for all `n` of `r(n)` and `r(n)` is the `sqrt` statement in the second line of the `do`-loop. Then in the next call, `rmin` is set to `-R` and `rmax` becomes `max(R,R')` where `R'` now is the maximum value for all `n` of `r(n)` (where the `r(n)` are different than those of the first call!). The line after the `do`-loop then seems to compute some sort of difference between the values of `rmax` in subsequent calls to `bar`. – Wouter Jun 15 '14 at 22:41
  • I'm not sure I follow. The result of the `sqrt` is never assigned to `rmax`, so I'm not sure why it would take on that value. – Greg Hewgill Jun 15 '14 at 22:43
  • The second line of the `do`-loop in `bar` reads `rmax = dmax1(rmax,sqrt(x(n)**2+y(n)**2))`, that's where I assume it would change value. – Wouter Jun 15 '14 at 22:44
  • Oh sorry, I was looking at the wrong `sqrt`. I'm still pretty certain that the SAVE attribute is not the right thing to do here. The subroutine appears to calculate a pretty straightforward value based on maximum and minimum distances, and I doubt that its value should be affected by previous calls to the subroutine. – Greg Hewgill Jun 15 '14 at 22:46
  • No problem, I suspected as much :) I'm going to have another look at the entire code to see if such behaviour is indeed even desirable. I left out most of the code for the subroutine (and the 300 something other lines in the program) but context might be important here. Unfortunately, the program is severely under-commented (there aren't any comments at all in the subroutine), so it's taking quite some time to understand it. Especially since I'm not really familiar with FORTRAN. I'll provide an update when I know more. – Wouter Jun 15 '14 at 22:55
  • Many older compilers would indeed implicitly give local variables the SAVE attribute, and some would even zero-initialize the values. This code evidently depends on such behavior, even though it is not standard. Most newer compilers don't do this by default, though if you're using Intel Visual Fortran and "migrated" a project from Compaq Visual Fortran, you'd get the "implicit SAVE" enabled in the converted project. I'm pretty sure that implicit SAVE is exactly what is going on here. (Has no connection to the IMPLICIT statement.) – Steve Lionel Jun 16 '14 at 15:37