Working with Fortran in 2020: Do’s and Don’ts
An etiquette guide for Fortran developers
by DI Dr. Christoph Hofer
Fortran is one of the oldest programming languages. The name is composed of „FORmel TRANslator“. For many software developers Fortran is the archetype for an old, ponderous, limited and difficult to understand programming language, with which one would best have nothing to do. For the old versions of Fortran, this prejudice may indeed be true. However, Fortran has changed a lot in its long history, so in its „modern“ variant (such as Fortran 2003) the language has a much worse reputation than it deserves. The typical use case for Fortran as a programming language is computationally intensive, numerical simulations such as weather forecasts, flow simulations or stability calculations.
Table of contents
- From old to new
- Do’s & Don’ts in Fortran
- Don’t use common block and equivalent statement
- Avoid using GOTO
- Avoid SAVE attributes
- Use implicit none
- Make use of derived data types and classes
- Use the module system
- Don’t rely on short-circuit evaluation
- Source
- Author
From old to new
Fortran is considered as the first ever realized higher programming language and was developed in the years 1954 – 1957 by IBM (FORTRAN I). The scope of the language was still very limited, for example, there were only integers (integers) and reals (floating point numbers) as data types and no functions yet. In the following years new improved and more extensive Fortran versions were developed (FORTRAN II, FORTRAN III, FORTAN 66). The next big update Fortran got in 1977 (FORTRAN 77). Due to new features in the language, this version became very popular and thus quickly became „the“ Fortran. Even today, when talking about Fortran code, mainly FORTRAN 77 code is meant, what also explains the many prejudices against the language. Since then, there have been several more updates to the language, bringing it up to modern programming concepts and standards. Major milestones in the development were the updates to Fortran 90 and Fortran 2003, which, in addition to the change of name (FORTRAN → Fortran) added common concepts such as free source file formats, modules, operator overloading, derived data types, pointers and object-oriented programming to the programming language. In addition to this, Fortran 95 and Fortran 2008 were each minor updates to the language. The latest version of the Fortran standard is Fortran 2018, although no compiler vendor yet supports all features.
Info
Higher Programming Language
Microprocessors are programmed in a so-called machine language, i.e. a binary code that is interpreted by the microprocessor as a sequence of instructions. Since these languages are very dependent on the hardware used and direct programming in a machine language is very time-consuming, the development of higher programming languages and compilers was a great step forward. Higher programming languages use mathematical expressions or expressions based on a natural language (usually English) that are translated into machine language by a compiler (and linker). Higher programming languages are independent of the hardware, the adaptation to the concrete hardware is done by the compiler.
Operator Overloading
is a programming technique with which the meaning of operators (such as +, -, *, …) depends on the respective types used. For example, 1 + 2 returns the number 3, but “Helllo ” + “World” returns the string “Hello World”.
Derived Data Type
allow the user to define data types from existing types. This offers the possibility of defining logically related data in one type and reusing it in different parts of the programme.
Pointer
is a data type that stores the memory address of a variable instead of the variable itself. Pointers refer to a memory address, so to speak, and the extraction of the value behind it is called dereferencing. In contrast to pointers in C/C++, Fortran pointers have even more information and also allow to refer to unrelated memory areas (in the case of arrays).
Object-oriented Programming
is a programming style in which data is not only collected in Derived Data Types but encapsulated together with logic and functionality in so-called objects. Each object has defined interfaces through which it can interact with other objects, e.g. often not all data and functions of an object are visible to other objects. The aim is to avoid code duplications in order to reduce the potential for errors and the maintenance effort.
Do’s & Don’ts in Fortran
Due to the long development history of Fortran and in order to maintain compatibility with legacy code, there are numerous obsolete and sometimes obscure language features in current Fortran compilers. A comprehensive collection of good and bad coding practices is beyond the scope of this article. Nevertheless, we would like to present some common legacy features that can be found in legacy code, as well as selected opportunities offered by new Fortran standards. For a comprehensive list of dos and don‘ts, please refer to [1].
Don’t use common block and equivalent statement
In Fortran 77 and earlier, it was common for different variables to refer to the same memory address using common block and equivalent statement. These expressions were used to share information between subroutines or to reuse (expensive) memory for temporary variables. In the meantime, these expressions have been declared deprecated and should no longer be used. To share data between program parts, modules should be used and memory should be allocated and deallocated dynamically as needed.
Avoid using GOTO
No other expression is as rooted in Fortran as the GOTO. In old programs you can often find an excessive use of GOTOs, partly due to the lack of alternative constructs. Over the time different variants of the GOTO developed, like the computed GOTO statement or the assigned GOTO statement. Also there were variants for the handling of loops or IF-statements, which worked with jumps to corresponding labels. In modern Fortran code, all these variants of GOTOs should be avoided if possible, and replaced by IF and SELECT case (= switch). A notable exception to the need for GOTOs in Fortran code is error management, since exceptions do not exist in Fortran.
Avoid SAVE attributes
The SAVE attribute allows variables to retain their value in repeated function calls. Especially in conjunction with parallelization, this can lead to hard-to-find bugs and dataraces. The SAVE attribute can be safely used with variables that always have the same value on each function call to gain some performance. In all other cases it should be avoided. A particularly sneaky „feature“ of Fortran is that all variables that are initialized the same when they are declared are automatically given an implicit SAVE attribute.
Use implicit none
A concept from old Fortran standards was that undeclared variables are automatically declared as REAL – except those starting with the letter i, j, k, l, m or n, which are declared as INTEGER. This concept is very error-prone, mainly because the compiler does not give an error message if undeclared variables are used, e.g. by a typo. Because of this concept the following joke about Fortran has become common: Fortran is the only language where „God is Real“ applies. This automatic variable declaration can be disabled using IMPLICIT NONE for the current scope and it is „good practice“ to implement it throughout the program code.
Make use of derived data types and classes
With Fortran 90, the language began to develop further in the direction of object-oriented programming. With this standard User-Defined Datatypes were introduced, which allowed for the first time to use reusable structures of logically related data. Also, the concept of generics was added, so that the same function name can be used with different types (but still the function must be programmed for each type). With the Fortran 2003 standard the object-oriented programming was again forced. At the latest since this time it should be tried to encapsulate data and logic in meaningful classes and to let program parts interact over well-defined interfaces.
Use the module system
Fortran 90 also introduced a new form of program organization, namely the module system. A module consists of a set of declarations of data, functions and function interfaces, which can then be used and made visible in other program parts. In addition, modules offer the possibility to restrict the access of the contained functions/data by means of PRIVATE/PUBLIC. Since the Fortran 2008 standard, there are submodules, which now allow the programmer to outsource the program code into a separate submodule. The necessity for this is on the one hand to avoid very large and unclear modules, to have the interface of the module clearly visible, on the other hand also to reduce the recompilation times.
Don’t rely on short-circuit evaluation
Very many programming languages evaluate only the first expression in a logical combination of two expressions, if the result is already determined by this expression. This procedure is called short-circuit evaluation. In Fortran, however, it is up to the compiler whether short-circuit evaluation is used, i.e. in the Fortran standard this is not forbidden, but also not prescribed. A typical use case for the necessity of short-circuit evaluation would be:
IF (PRESENT(x) .AND. x >0) THEN dosomething with x END IF |
In Fortran there is the possibility of optional arguments, i.e. parameters of a function which do not have to be passed. With the help of the function PRESENT(x) it can be checked whether the parameter x was passed. In the example on the right, a query is made after the check whether x is greater than 0. If x is not passed, then by short-circuit evaluation the query x>0 would not be made any more, since already the first condition is not fulfilled. However, the program would crash at this point due to the possible failure of short-circuit evaluation. The correct notation is the splitting on two single conditions as shown in the example:
IF (PRESENT(x)) THEN IF(x >0) THEN dosomething with x END IF END IF |
Other typical cases are queries whether a pointer is assigned to a memory address or whether a mathematical operation is allowed with the input values (division, root…).
Sources
(1) S. Chapman, Fortran for scientists & engineers, McGraw-Hill Education, 4. Edition, 2017
Contact
Author
DI Dr. Christoph Hofer
Professional Software Engineer Unit Industrial Software Applications