HWM14 code uses uninitialized arrays

I always have used (the equivalent of)

    real(8), parameter         :: one = 1
    real(8), parameter         :: pi = 4*atan(one)
    real(8), parameter         :: twopi = 2*pi

Actually used the following reliably, which has worked with all Fortran compilers I have ever used.

    real*8, parameter         :: one = 1
    real*8, parameter         :: pi = 4*atan(one)
    real*8, parameter         :: twopi = 2*pi

Using " real(8), parameter :: pi=3.1415926535897932" has been a terrible mistake for 50 years !
along with real(8), parameter :: dt = 0.001
I don’t know how many codes I have seen this type of error since F77, but it has been too many and should have been removed from the Fortran standard since 1978. It is an obvious bug and with the exception of Tom Lahey, no one else cared.

What if there was an additional option with the implicit statement that tells the compiler the default kind for hard coded constants? Like

implicit constant real(kind=real64)

This feature is already under consideration for F2028: https://j3-fortran.org/doc/year/25/25-191r2.txt

On of the proposed syntaxes is,

    PROGRAM example
        DEFAULT KIND (REAL = SELECTED_REAL_KIND(30))
        REAL :: x = 1.23456789012345678901234567890
        PRINT '(F0.29)',x
    END PROGRAM
1 Like

You can also use acos (-1.0) or acos (-1.0d0).

1 Like

Many, many years ago I worked on a (for then) large program that used 4*ATAN2(1.0,1.0) to get PI. This was on UNIVAC 1100 systems. I never understood why the original authors of the code decided that was better than 4.*ATAN(1.0) but the ATAN2 function was used throughout the code base. I presume there was a legitimate reason for the UNIVAC compiler at the time (late 1970s).

Other contenders:
2*acos(0d0), 2*asin(1d0), (gamma(1d0/2))**2, aimag(log((-1d0,0d0)))

The reason ATAN2 was used was that ATAN was not available for some FORTRAN compilers pre Fortran 77. Similarly with ACOS not being used also.
Similarly, I think that use of ATAN at compile time in “real(8), parameter :: pi = 4*atan(one)” was from F90.

1 Like

The F66 standard Table 4 on p25 has all 4 of ATAN, DATAN, ATAN2 and DATAN2 and no other inverse trig function. My only earlier source is Daniel D. McCracken’s “A Guide to FORTRAN Programming” (Wiley, 1961) where Table 2.3 on p13 lists only ATANF as an arctangent function, but warns above the Table that the names vary with the different versions of FORTRAN, and on p54 that the exact list of what we now call intrinsic functions “depends not only on the computer and the version of FORTRAN used but on the particular installation.”

My “go-to” reference for Fortran archeology , Fredric Stuart’s “Fortran Programming” 1970 edition shows at that time (1969-1970) that ATAN was supported by 86 compilers versions on 152 different computer models. TAN and ATAN2 were not supported at that time on all the compilers Stuart lists in his books tables. The Univac systems I referenced above supported both ATAN and ATAN2. One interesting thing is that IBM (you know the folks that created Fortran) only supported TAN and ATAN2 on some of their 7000 series systems at the time. Univac 1106 and 1108s were the computers I used in college and my first engineering job.

Parameters were introduced in f77, so prior to that any compile time initializations would have been with data statements, which only allowed literal constants, no expressions or function evaluations.

F77 introduced parameter statements, and it also allowed expressions. I’m unsure about which intrinsic functions were allowed in parameter statements in f77. I personally avoided using floating point functions like sqrt, tan, atan, and so on during most of the 1980s, but I don’t remember why. It might have been because not all compilers supported them (e.g. Cray compilers were slow to implement full f77), or it might have been because the compile-time evaluation of some functions differed from the run-time evaluation, which sometimes caused problems (and which was allowed to occur by the standard).

Then f90 and later divided the intrinsic functions into different categories, some of which were allowed in parameter statements and some that weren’t. The trend since f90 has been to allow more functions in parameter statements.

I cannot think of any reason why atan2() would have been preferred to atan() in a parameter statement. Of course, atan2() allows the result to range over all four quadrants, but if you want a value in the middle of the first quadrant, then I can’t think of a reason why atan2() would be preferred over atan().

Here is something strange, found in Subroutine hwm14.f90 in your archive: Line 729 has
real(4), parameter :: talt=125.0 !, twidth=5.0
Note the ‘!’, which is unexpected in an apparent declaration and initialization of a parameter.
Furthermore, earlier in the same subroutine we have “use dwm”, and module dwm contains a declaration of ‘twidth’ as a real(4) variable. The value of twidth is read from an unformatted file elsewhere. The value read is 4.0, compared to the 5.0 in the faulty parameter declaration.
This error is present in the file hwm14.f90 from the original NRL site, as well, although the line number that I gave does not apply to that file.

You aren’t kidding about that book being a reference for archaic Fortran dialects. I just skimmed through it at archive.org. He wrote the book mostly in Fortran II (arithmetic IFs everywhere), with the Fortran IV enhancements described only in the later chapters. Almost no reference to the Fortran 66 Standard - which was a subset of IBM’s Fortran IV. (No ENTRY, IMPLICIT, NAMELIST, direct access I/O, etc.) The tables outlining the differences in compiler support indicate the sad state of affairs for anyone trying to write a reasonably portable program at that point in time.

My copy is the text I used in the spring of 1972 for the then required Fortran programming class that all engineering, physics and I think math majors took at my university. How its stayed with me for almost 54 years is beyond me. In addition to the numerous tables that document the capabilities of various compilers of time, it includes some interesting short programs that are still of use (with a little refactoring to modern syntax). My edition is the 1970 edition. I’m not sure which one is on archive. You are correct about the Fortran II/Fortran IV emphasis. I really should get rid of it (along with about 100 other text books that are just taking up space) but its like an old friend you don’t see much of anymore. It brings back a lot of memories of a younger (and much less wise) me.

Edit.

It looks like the version on archive.com is the 1968 version. The 1970 version does cover NAMELIST, IMPLICIT and ENTRY

3 Likes

I do this when I’m developing code and I want to temporarily disable the parameter attribute or change its value. Everything after the ! is treated as a comment, so ignored as far as variable scope. Of course, the goal is to eventually put the parameter back, or remove the comment entirely, but maybe that last step slipped by the programmer.

1 Like

Removing the ‘!’ and attempting to compile reveals that ‘twidth’ is already in module ‘dwm’, which is 'use’d in the subprogram where the mangled declaration is located. The module variable is read elsewhere from an unformatted file, so one wonders why the programmer wanted to replace that by a parameter.