An IBM 704 machine that used FORTRAN punch cards

in FORTRAN, Programming

The Basic Structure of a FORTRAN Programme

.ב״ה

FORTRAN is often viewed as an outdated and archaic language, but it is just as capable of doing any job that other compiled languages can. It’s thoroughly up to date, with the previous stable standard being released in 2018 (5779), and the previous in 2010 (5771). Modern FORTRAN – which is now just spelt Fortran, although I prefer the former – supports generics and modularisation, object-oriented programming, concurrent programming, and is even interoperable with C. This post will walk you through the basic structure of a FORTRAN programme. It’s designed for people who already know a little about programming, but haven’t worked with FORTRAN in the past.

There’s no reason not to use FORTRAN, provided you enjoy working with the language and you can use it within your environment. At the end of the day, the tools used are unimportant; only the ability of the final product to meet requirements matters. That being said, I wouldn’t recommend using FORTRAN if the rest of your company only understands Objective-C. That probably won’t go down well with your boss.

This post and any future posts regarding FORTRAN will not deal with language elements that are specific to fixed-form FORTRAN. If you’re working with legacy code or compilers, a lot of this may not apply to you. I will be following the convention of writing all keywords in capitals, though this is completely optional.

The initial programme template

All FORTRAN programs start with the following basic template:

PROGRAM programme_name
IMPLICIT none
! code goes here
END PROGRAM programme_name

Every FORTRAN programme starts with the keyword PROGRAM followed by the name of the programme and ends with END PROGRAM followed by the name of the programme. PROGRAM is optional, but it is almost always included as it informs the compiler where the main routine of the programme begins.

Most modern FORTRAN programs follow this with IMPLICIT none. This tells the compiler that no implicit types are used by this programme. This is because, if this is not set, FORTRAN will attempt to define any variables with the names i, j, k, l, m and n as integers, and all other variables as real. It is included in almost all code to prevent issues with mistaken type declarations. This statement comes straight after PROGRAM. Only the USE keyword may be placed before it, but we will come to that later.

The ! character indicates a comment. Everything after the ! on that line is ignored by the compiler, except when it is used in a character string.

The rest of the code for the programme follows these statements. FORTRAN programs do have a specific order, though. You can’t write anything in any order and expect it to work – just as main() must be at the end of a C file.

Specification, Execution and Subprogram

The specification, or declaration, section is placed immediately after the implicit statement. This part of the programme specifies the data types of variables that will be used by the main programme. For instance, if our programme were to use an integer referenced as the_integer and a character string referenced as the_character, our programme would now look like this.

PROGRAM programme_name
IMPLICIT none
    ! Start of the specification part
    ! The integer variable
    INTEGER :: the_integer

    ! The character variable
    CHARACTER :: the_character
    ! End of the specification part
    ! The rest of the code goes here
END PROGRAM programme_name

As you can see in the code above, we now have two variables initialised. You should note that FORTRAN does not have a separate data type for strings. The character type covers both single characters and strings of characters. You do need to define how long the string will be, however, or the compiler will truncate it to a single character. Alternatively, you can include a wildcard, but this comes with its own drawbacks that I won’t be covering here.

INTEGER :: the_integer
CHARACTER (LEN=6) :: the_character

After the specification section of the programme, we have the execution section. This section handles the main programme logic that will be executed when the programme is run. Using what we have thus far, we can quickly demonstrate how this part of the programme might look.

PROGRAM programme_name
IMPLICIT none
    ! Start of the specification part
    ! The integer variable
    INTEGER :: the_integer

    ! The character variable
    CHARACTER (LEN=6) :: the_character
    ! End of the specification part

    ! Start of the execution part
    ! Putting the variables to use
    the_character = "World!"
    the_integer = 1
    the_integer = 1 + the_integer

    ! Printing to the command line
    PRINT *, "Hello ", the_character
    PRINT *, the_integer
    ! End of the execution part
END PROGRAM programme_name

Now we have a functioning, albeit short, FORTRAN programme. But what about subprograms? To begin to understand subprograms, we have to separate subprograms into two different subtypes: functions and subroutines.

Functions

Functions are designed to emulate mathematical functions. They work just like functions in C languages, although functions are typically used if there is a single value that must be returned. Functions cannot return more than one value. The following is an example function that prompts for two integers, then adds two integers together.

INTEGER FUNCTION Addition(a, b)
    IMPLICIT none
    INTEGER :: a, b
    Addition = a + b
END FUNCTION Addition

This function can then be called from the main programme code. It will execute, then return the value of Addition. Note that the name of the function is used as the return statement, rather than using a keyword such as return as is the case in C.

Subroutines

Unlike functions, subroutines are designed to be used when a return value is not required, or when more than one return value is required. Functions can serve the former purpose, but this is generally not how they are used. They are visually similar to functions, as you will see below.

SUBROUTINE Subtraction(a, b, c)
    IMPLICIT none
    INTEGER, INTENT(IN) :: a, b
    INTEGER, INTENT(OUT) :: c
    c = a - b
END SUBROUTINE Subtraction

There are a few key differences, however. Firstly, there is no type assigned to the subroutine. This is because subroutines do not have to return a value, nor do they have to return only a single value. Secondly, the variables that are going to be returned by the subroutine are included in the formal argument.

Finally, we have to declare what the purpose of our variables is, as you can see with INTENT(IN) and INTENT(OUT). When the intent of a variable is IN, that means the value of this variable is determined by the input of the subroutine’s formal argument. When the intent is OUT, then the value will be determined within the subroutine, then returned to the part of the programme that called the subroutine. Both of these can be combined with the intent INOUT.

Using functions and subroutines

Now that we know how functions and subroutines are written, we can see how they are implemented in programs.

PROGRAM programme_name
IMPLICIT none
    ! Start of the specification part
    ! The integer variable
    INTEGER :: the_integer, the_output

    ! The character variable
    CHARACTER (LEN=6) :: the_character
    ! End of the specification part

    ! Start of the execution part
    ! Putting the variables to use
    the_character = "World!"
    the_integer = 1
    the_integer = 1 + the_integer

    PRINT *, "Hello ", the_character
    PRINT *, the_integer

    ! Calling the function Addition(a, b)
    PRINT *, Addition(the_integer, the_integer)

    ! Calling the subroutine Subtraction(a, b, c)
    CALL Subtraction(the_integer, the_integer, the_output)
    PRINT *, the_output
    ! End of the execution part

! Start of the subprogram part
CONTAINS

    INTEGER FUNCTION Addition(a, b)
        IMPLICIT none
        INTEGER :: a, b
        Addition = a + b
    END FUNCTION Addition

    SUBROUTINE Subtraction(a, b, c)
        IMPLICIT none
        INTEGER, INTENT(IN) :: a, b
        INTEGER, INTENT(OUT) :: c
        c = a - b
    END SUBROUTINE Subtraction
! End of the subprogram part

END PROGRAM programme_name

To separate out functions and subroutines from the main programme, we use the keyword CONTAINS. This lets the compiler know that the code included after this is not a part of the main programme, and thus should be executed when called, rather than procedurally.Now that the subprograms are included in the entirety of our code thus far, we can see some differences between the two. Right off the bat, we can see that a new integer has been declared in the main programme. This integer, the_output, is defined by the output of the subroutine. Unlike functions, subroutines must have their output assigned to variables declared by the main programme.

We can also see that functions and subroutines are called in a different manner. Functions can be called from within code as they can in C, but subroutines must be called with the CALL keyword. This is because the compiler cannot predetermine how the output of a subroutine will be used if an output is provided. Functions will return a single output that it can interpret, however.

There’s just one more element of FORTRAN programs that we haven’t covered, and that is modules. As these separate out programme code into multiple files and introduce a whole new array of issues that encroach upon object-oriented development, I will cover these in a different post.

Concluding The Basic Structure of a FORTRAN Program

If you’ve gotten this far, congratulations. You’ve successfully learned more about FORTRAN than the majority of today’s programmers will ever know.

This post will, hopefully, give you everything you need to know to begin reading FORTRAN programs. You might not understand what the code does, but you’ll be able to pick out the structure of the programme and translate that into the concepts of a language that you are more familiar with.

As always, drop a comment below or join my Discord server if you have any comments or questions. If you enjoyed this article, check out some of my other development articles here.

Write a Comment

Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

    • I’m not 100% sure on their original reasoning, but FORTRAN’s implicit typing allows you to name variables without including their type and have the compiler understand what you’re trying to do. It saved writing out integer for every integer and real for every real, because you could just start your variable name with the appropriate letter. You can write less code, and people can instantly tell what the type is based on the first letter.