Control Structures

This section gives a brief introduction to the constructs of the Fortran programming language:

if Conditionals

Fortran features three different types of conditionals: arithmetic if (deprecated), logical if, and block if.

Arithmetic if

The first FORTRAN version from 1956 introduced the arithmetic if conditional that evaluates a numeric expression and then jumps to one of three labeled statements, depending on whether the expression is either negative, zero, or positive:

if (x * y) 100, 200, 300

If negative, the statement does a goto to the first label (100), if zero to the second (200), and if positive to the third (300). This is equivalent to:

if (e < 0) goto 100
if (e == 0) goto 200
goto 300

Arithmetic if is now outdated and has been removed from Fortran 2018. Like the goto statement, it should not be used anymore.

Logical if

The logical if conditional was added to FORTRAN IV and allows the execution of a statement depending on a logical or arithmetic expression, using operators. Only a single statement may be declared:

if (x * y < 0) y = 1

A line-break following the expression is legitimate, but must be indicated by an ampersand:

if (x * y < 0) &
    y = 1

Block if

The block if allows the conditional execution of a group of statements, for example:

if (a == 0) then
else if (a < 0) then
    sum = 0
    sum = sum + a
    print *, sum
end if

This conditional was introduced in FORTRAN 77.

select Switches

The select switch can often be used instead of block if:

select case (grade)
    case ('A')
        print *, 'Excellent!'

    case ('B')
    case ('C')
        print *, 'Well done'

    case ('D')
        print *, 'You passed'

    case ('F')
        print *, 'Better try again'

    case default
        print *, 'Invalid grade'
end select

You may want to use ranges inside select switches with case (begin:end):

select case (marks)
    case (91:100)
        print *, 'Excellent!'

    case (81:90)
        print *, 'Very good!'

    case (71:80)
        print *, 'Well done!'

    case (61:70)
        print *, 'Not bad!'

    case (41:60)
        print *, 'You passed!'

    case (:40)
        print *, 'Better try again!'

    case default
        print *, 'Invalid marks'
end select

do Loop

The do construct loops over statements until an exit occurs:

    a = a + 1
    if (a > 10) &
    print *, a
end do

It can also be used like a for loop in other programming languages. Set begin, end, and step size in the head of the loop:

do i = 1, 10, 2
    print *, i
end do

The loop variable i has to be declared a priori. The step size is optional, default is 1. It is possible to name loops:

loop: do
    a = a + 1
    if (a > 10) &
        exit loop
    print *, a
end do loop

The cycle statement skips to the next iteration:

do i = 1, 10
    if (i == 2) &
    print *, i
end do

Implicit do

Implicit do loops can be used for input and output:

integer :: i

print *, ('Hi there. ', i = 1, 3)

Arrays can be initialised implicitly as well:

integer, parameter :: n = 10
integer            :: i
integer            :: values(n) = [ (i * 2, i = 1, n) ]

The array values will be filled with 2, 4, …, 20.

Concurrent do

The Fortran 2008 standard added the do concurrent construct that allows easy loop parallelisation and is equivalent to forall:

integer :: i
real    :: a(100)

do concurrent (i = 1:size(a))
    a(i) = sqrt(i**i)
end do

Inside a do concurrent loop, only calls to pure functions are allowed.

do while Loops

The do while loop cycles through statements as long as a given condition is true:

do while (i < 5)
    i = i + 1
    print *, i
end do

forall Loops

The forall loop has been introduced with Fortran 95 and declared obsolete with Fortran 2018, in favour of do concurrent. It selects elements in an array by index or index range, with an optional step size. In the following example, the loop statement changes the values of the first three elements of the array to 0:

integer :: a(5) = [ 1, 2, 3, 4, 5 ]
integer :: i

forall (i = 1:3) a(i) = 0

! with explicit step size of 1:
forall (i = 1:3:1) a(i) = 0

Furthermore, a mask can be added to the condition of the statement in order to select only specific value, for instance:

forall (i = 1:3, a(i) == 0) &
    a(i) = 1

The mask can be any pure function. To allow more than one statement, use the forall block statement:

forall (i = 3:5)
    a(i) = 1
    print *, a(i)
end forall

Inside the loop, you can assign pure functions to the elements:

forall (i = 1:3) &
    a(i) = my_func(a(i))

where Statements

The where statement is used for masked array assignments. Elements of an array will be modified directly upon given conditions:

integer :: a(5) = [ 1, 2, 3, 4, 5 ]

where (a >= 3) &
    a = 0

You can add else where statements to the block form of where:

where (a > 0 .and. a < 2)
    a = 0
else where (a >= 4)
    a = 1
end where