Formula Translating System Standard
Some Programming Guidelines
- Use free source formIndent two spaces after the line continuation character
&. You can put
&anywhere, but I like to put them in column 132—I just think it makes the code look nicer.
- Replace DO WHILE statements
DO ... IF() EXIT ... END DOfor better control; need opposite relational operators, e.g.,
>. Be careful about over-counting.
- Use generic intrinsic functionsAlways use generic intrinsic functions—e.g.,
SQRT, etc.—for mathematical operations. This rightly gives the compiler the task of how to handle their arguments (real, complex, etc.).
- Use white space between mathematical operatorsPut spaces between the mathematical operators
- Use lowercase edit descriptorsEdit descriptors for
WRITEstatements should be lowercase; see Rule 29.
- Manage variables using MODULECollect variables into
MODULE Sharedwith modern declaration syntax; if possible, include
PARAMETERconstants to 15 decimal places (double precision) and employ derived-type objects using
- USE only what you needImport as many module entities as is practical into functions and subroutines with
USE Shared, ONLY :. The statement
IMPLICIT NONEalways follows a
USEstatement. Aside: functions and subroutines are collectively referred to as procedures, which can be thought of as subprograms.
- Double precision everywhere
USE, INTRINSIC :: ISO_Fortran_env, dp=>REAL64. Also, use the suffix
_dpas a way of casting a single precision literal using a
1.234_dp. It can be nicer to look at in some cases (see more here).
- Text labels on DO loopsGive your
DOloop a name:
my_loop: DO ... END DO my_loop.
- Use ALLOCATABLE arrays
ALLOCATABLEarrays offer significant advantages in memory management and execution speed when the functionality of pointers is not needed.
- Use uppercase exponent notation
E−. Of course, one could go a step further and replace all
Ds—see Rule 8. Make sure to pad single-digit exponents, e.g.,
- Release files from their associated UNIT numbersAlways pair a
CLOSEstatement with an
.datextension on file names.
- Don't have bare END statements'Tis better for all
ENDstatements to specify what they are ending, e.g.,
END MODULE Shared.
- PROGRAM name and file name should be the same
- Use a consistent set of rules for case
- Use optional white space in statements and keywordsTake advantage of separating blanks in (and around) statements and keywords. Things like
- Place a space after all commasAlso: use single quotes,
', for internal strings and double quotes,
", for external strings.
- Use symbolic relational operatorsMake your code more closely resemble the mathematics by adopting the symbolic relational operators
- Use square bracket notation for array constructorsFor rank 1 arrays, Fortran 2003 introduces the use of square brackets
to delimit an array constructor. For arrays of rank 2 or greater, the
DATAstatement needs to be used … usually declared in a module.
- Indicate the intent of all dummy argumentsIn subroutines, aid the compiler in discovering errors in your program by providing an
- Reduce long argument listsPass derived-type objects between procedures. (These don't need to be passed as dummy arguments.) Especially handy if a group of parameters has an identifiable theme.
- Use assumed-shape arrays as dummy array arguments in subprogramsThese can be tricky. For example,
REAL, INTENT(IN OUT) :: dummy_array(:); see Rule 25. The compiler may request that you write an explicit interface for your subprogram:
Explicit interface required for ... assumed-shape argument. In doing so, you will be assisting the compiler in looking for potential problems. Please see the Notes for more details. If assumed-shape arrays are not working (I don't blame you), then just pass the size of the array as an argument to your procedure—it's not graceful, but it works.
- Allow strings of varying lengthDeclare an assumed-length string:
CHARACTER(LEN=*), INTENT(IN) :: string; use a deferred-length parameter specification:
CHARACTER(LEN=:), INTENT(IN OUT), ALLOCATABLE :: dummy_string. Rule 29. has more info on usage.
- Write all loops that index arrays of rank 2 or greater (nested loops) such that the innermost rank varies firstTo avoid large jumps in memory references, arrange loops to vary indices in "reverse" order.
- Assign the CONTIGUOUS attribute to assumed-shape arraysAssist the complier in generating optimized code by avoiding unnecessary copying of data when invoking subprograms.
- Manage UNIT numbers as a resourceGive your file a name:
INTEGER, PARAMETER :: my_file = 10; avoid using single-digit unit numbers. Remember that Fortran reserves two unit numbers for user I/O with respect to the
5for input (read) from the keyboard and
6for output (write) to the screen. Also, consider replacing
PRINT *statements with formatted
WRITE(6, '(...)', advance='no')output statements if you happen to be reading input from the user.
- Use recommended specifiers in OPEN statementsEspecially recommended are the specifiers
action. See Rule 28.
- Use ASYNCHRONOUS I/O in OPEN statementsDeclare:
REAL, DIMENSION(:), ALLOCATABLE, ASYNCHRONOUS :: my_array; implement:
- Use named character constants for format specificationsGive your format a name:
CHARACTER(*), PARAMETER :: my_format = '(a, i0, a, g14.7, a)'.
- Make dummy arguments predictable and informativeAppend the characters
sto dummy arguments to specify a
SUBROUTINE, respectively. This has the benefit of informing the programmer how many "levels deep" these parameters are within the overall context of your program. For example,
my_variablefsfis buried function-subroutine-function "below" the main program.
Please help yourself to this sick Fortran template.
- Metcalf, Michael. Modern Fortran Explained. Oxford: Oxford University Press, 2011.
- Clerman, Norman. Modern Fortran: Style and Usage. New York: Cambridge University Press, 2012.
- "What does "Error: Explicit interface required for '*' at (1): assumed-shape argument" mean?" Computer Groups.