How to solve the same numerical Problem in 7 different Programming Languages

To state the obvious, the problem is perceived issues with backward compatibility, that there are codes out there still that do not have implicit none and which then rely on Fortran’s current default which is that variable names starting with letters I thru N are default integer types and all others are default real unless declared otherwise and that these will “break” as a result if and when they start using Fortran 20XY compilers where, say, 20XY is the standard revision where this change is introduced.

Say Fortran 202Y introduces this change, the earliest this can happen. This revision is likely to be published around year 2028 or later. It will be another X years later when compiler start supporting certain features of this revision. On top of this, the compiler are under no pressure to change their default behavior, again take the case with Intel oneAPI Fortran compilers which do not treat Fortran procedures as recursive by default even though Fortran 2018 introduced this change.

Thus one is looking at a long period of time - 10 years plus - for these supposed codebases to move toward explicitly introducing their desired implicit mapping. All they have to do is add one line statement to their program units:

   implicit integer(i-n), real(a-h,o-z)

and they get back the behavior they have been used to.

However they apparently would refuse to do so in spite of the simplicity of the change and the long time duration available to adopt this.

Instead all the other practitioners, especially the posterity for Fortran, have to be forced to add implicit none to all their program units.

This is patently unfair and ridiculous. It might have made sense during 1978, or perhaps 1991 for Fortran 90, or 1997 for Fortran 95, or even 2004 for Fortran 2003. But not now.

It is a separate matter but entirely likely that
a. there are NO such codebases or
b. these codebases will never be processed using Fortran 202Y or later compilers. Either because the production codes will either have migrated to other languages by the time the compilers come around, or the codes will continue to execute on processors that never see anything besides a FORTRAN 77 plus extensions compiler or a Fortran 90/95 compiler.

Bottom-line; the threat of a breaking code due to a change that will come into effect 10+ years now is theoretical, in reality it is likely statistically insignificant.

Please see this:

Thanks.
So, in conclusion.

  1. If do as you said, make implicit none default, then all the old code need to add implicit integer(i-n), real(a-h,o-z) to ensure compatibility.
    Question:
    If we accept 1. can someone write a script to automatically add implicit integer(i-n), real(a-h,o-z) in the old code? If so, I have no problem with 1.

  2. If we do not do anything, just as is. Then we need to add implicit none at the beginning of the problem/module. If the function/subroutines are not contained in a module/problem, then all these function/subroutines needs to add implicit none.
    Question:
    If we accept 2. can someone write a script to automatically add implicit none in the proper place in the code? If so, I have no problem with 2, either :rofl:

Bottom line, if anyone can write a perfect script to automatically add whatever implicit none or implicit integer(i-n), real(a-h,o-z) in the proper place in the code, then at least for me, the problem is solved :rofl:

Does the paper below useful?

My solution is to always use -fimplicit-none (or equivalent) as a compiler option, which is basically what IMPLICIT NONE actually is. It then applies to all routines or gives an error where “IMPLICIT REAL (a-h)…” is used.
( I also always use !$OMP PARALLEL default(none), which can help eliminate unnecessary errors )

The best way to think of IMPLICIT NONE is that all declarations set up a dictionary of variables at the start of the routine and if a variable that is referenced is not in the dictionary, then an error should be reported. This also covers spelling errors such as IO vs I0 (zero) or lO (lower case L); which are very poor variable name choices.

Strangely, I know of Fortran users (perhaps FORTRAN in this case) who refuse to adopt IMPLICIT NONE. We are a diverse group !!

2 Likes

I agree.
My shallow opinion is, anyone who wrote modern fortran code, should have a program which has implicit none at the beginning. Then all the subroutine/function/whatever should be in corresponding modules, in the beginning of each module, have implicit none. That is all.
In such way, the whole code is safe. It will just tell user, ‘Hey man, you need to define the type of the variable first’. This is good.

With regard to @FortranFan , again his Fortran expertise is way above me like most the experts here. Uhm, my shallow opinion is, if the team he is working with, have mountains of code which have to have some old beef with implicit none. Then, at the current moment, perhaps the most efficient way is to write a script to automatically add implicit none in the proper places in the code.

Then why not make implicit none the default?

Do external procedures count as program units in standard terms or they should be mentioned here explicitly?

My recommendations for changes to Fortran have been ignored for years.
As someone who has used Fortran continuously for nearly 50 years, this is disappointing.

The changes I would like to see are:

  1. changes to make INTERFACE nearly obsolete, by introducing the concept of a project, where the compiler should create an “module_interface” for all routines in a project, then refer to the single definition of the interface when required. The only place where an INTERFACE is needed could be for when a routine is an argument. A compiler should refer to this “module_interface” to check all routine uses when compiling. This should be done during compiling and during linking, so that library routines are also checked, hence a Fortran linker !
    The use of multiple definitions of INTERFACE for the same routine should be eliminated.
  2. IEEE 754 should be better recognised and the concept of a byte should be an alternative for kind definition. REAL*8 is a clear local definition of precision, without the need to refer to obscure modules, which are often not in the same file.
    I always use byte syntax and if ever there is a Fortran compiler that does not support this syntax, I expect it will have few real fortran users.

What you are proposing to them is NOT what they want, or will even tolerate.

They want an unstated (i.e., implicit) IMPLICIT INTEGER(I-N), REAL(A-H,O-Z), as FORTRAN and Fortran have granted them for decades without requiring them to write one more line. Their stance is that they are disciplined in writing as few type declarations as necessary, i.e., when they need variables of other types (including DOUBLE PRECISION, LOGICAL, CHARACTER, etc.), then they will write type declarations.

Whether we agree with their viewpoint or not, let us understand why they adopt that position. Making IMPLICIT NONE the default is, to them, a disruptive, draconian, high-handed imposition, an infringement on freedom.

They tend to use small groups of variables localized to a score of lines, say. In effect, their code is organized into BLOCKS with no explicit demarcation. Adding lots of declarations in a far away place may actually make such code harder to understand.

I do not espouse their viewpoint, but I am happy to live under the same tent with them.

3 Likes

I have seen many Fortran modules where implicit none appears before the contains and also in each contained procedure, which is redundant but unnecessary. It appears that many people do not understand what a module-level implicit none does. I support making implicit none the default but also allowing users to include it, as @jacobwilliams proposed. I would continue to include it, since it would be years before all compilers aligned with the language change. In fact I would appreciate a compiler option that warned about the lack of implicit none in a main program, at the module level, and in interfaces (where I often forget implicit none).

4 Likes

Great question @msz59 , the short answer is yes. The program units refer to “main program, external subprogram, module, submodule, or block data program unit” and that is what I will suggest be intended for the edit I proposed upthread.

Like what @FortranFan says, the requirement to write implicit none combined with the lack of a default implicit none flag in some compilers can create hard-to-detect bugs in isolated situations, particularly when the procedure interfaces in modules are separated from the implementations in submodules. Luckily gfortran provides a flag to make implicit none default behavior (which enabled the removal of all such cases from the codebase), but others like Intel ifort do not. What if gfortran did not exist? If all compilers provided a default implicit none flag, the issues with implicit none would be less severe. That is when code portability and testing with multiple compilers become crucial for scaling the codebase.

2 Likes

The question is who are “they”?

Chances are high “they” no longer exist, hence anonymous.

Thanks for the explanation. What fraction of Fortran programmers satisfy (1) below and most of the other conditions:

(1) they currently use implicit typing
(2) they care about compliance with the latest Fortran standard
(3) they will upgrade to the latest version of gfortran and other compilers
(4) they refuse to use options such as gfortran std=legacy (which I assume would allow implicit typing)
(5) they would rather rewrite their code in another language than add
IMPLICIT INTEGER(I-N), REAL(A-H,O-Z)

I don’t think the fraction is large, and with attrition the fraction gradually decreases.

3 Likes

The other interpretation is that this “fraction”/faction will continue to use an older version of Fortran.
There is claimed to be a significant fraction of HPC users that still use F77, although perhaps they are a hybrid group, as I find some of the F95 memory features are very useful.
See @CRquantum’s recomendation Making legacy Fortran code type safe through automated program transformation | The Journal of Supercomputing

Do you think the F08/F18 fraction is large and what might be their attrition rate ?

Why do not define some kind of “legacy block” in which you can just embed some old fortran code in modern fortran?

This would work in a similar way as the modern block instruction do: you can define a block and make some variable definitions there. This way the compiler would automatically know what to do, no flags on the legacy quality would be needed. The compiler should restrict itself to the old standard inside the block.

I would suggest that you can embed a whole f77 program in such a block.

Hello all and thanks for keeping the Fortran community alive! I want to give my two cents on the implicit none thing and its implications on other feats of the language.

Each line of code matters when handling large codebases: it has to be maintained, debugged, etc., so, I’m in full favor of actions that lead to more concise Fortran code (staying on the error-proof side).

I really loved how the 90/95/2003 standards brought Fortran into the array realm: one can have extremely compact code do complex things (think merge, forall, pack combined with elemental functions). If extended to classes and polymorphism, that could have evolved into a Matlab/Python/Julia-like language, with the advantage of being statically typed and fast. I think people love those languages cause they’re compact and easy, rather than cause variables can change type all the time.

However, that direction has been completely unwinded by the more recent iterations that are going back to do loops and greater verbosity. In other words, Fortran is getting closer to C+±like behavior, in which case though, it feels much easier/cheaper (and what most teams seem to be doing) to just re-write Fortran code in C++, that also enables a far larger pool of excellent libraries and tools to be used.

1 Like

In a sense, we already have such a “legacy block”. A call using an implicit interface to an external subprogram is a one-line legacy block. In fact, the implementation of the legacy block can not only be in Fortran 77, but it can be in any language such as C, assembler, etc., provided it can be called using one of the existing ABIs.

I acknowledge that a significant fraction of Fortran work is still done in Fortran 77. A recent paper from arXiv looks like an interesting application of automatic differentiation. Since F77 is smaller than F2018, building a tool that does AD for F77 code is simpler.

[Submitted on 31 May 2022]

Smart: A program to automatically compute accelerations and variational equations

Daniel D. Carpintero, Nicolás P. Maffione, Facundo A. Gómez

Modern astronomical potentials modeling galaxies or stellar systems can be rather involved, and deriving their first derivatives (accelerations) and second derivatives (variational equations) in order to compute orbits and their chaoticity may be a formidable task. We present here a fully automated routine, dubbed Smart, with which the accelerations and the variational equations of an arbitrary potential that has been written in the Fortran 77 language can be computed. Almost any Fortran 77 statement is admitted in the potential, and the output are standard Fortran 77 routines ready to use. We validate our algorithm with a set of potentials including time-dependent, velocity-dependent and very complex potentials that even involve auxiliary routines. We also describe with some detail a realistic seven-component Galactic potential, MilkyWayHydra, which yields very involved derivatives, thus being a good test bed for Smart.

I don’t understand the last paragraph above. With the impure elemental procedures of Fortran 2008 the need for explicit loops was further reduced. Are you referring to forall being made obsolescent and do concurrent being the suggested replacement?