Fortran

Execution Control

If construct

The if construct (called a block IF statement in FORTRAN 77) is common across many programming languages. It conditionally executes one block of code when a logical expression is evaluated to true.

[name:] IF (expr) THEN
    block
[ELSE IF (expr) THEN [name]
    block]
[ELSE [name]
   block]
END IF [name]

where,

  • name - the name of the if construct (optional)
  • expr - a scalar logical expression enclosed in parentheses
  • block - a sequence of zero or more statements or constructs

A construct name at the beginning of an if then statement must have the same value as the construct name at the end if statement, and it should be unique for the current scoping unit.

In if statements, (in)equalities and logical expressions evaluating a statement can be used with the following operators:

.LT.  which is <   ! less than
.LE.           <=  ! less than or equal
.GT.           >   ! greater than
.GE.           >=  ! greater than or equal
.EQ.           =   ! equal
.NE.           /=  ! not equal
.AND.              ! logical and
.OR.               ! logical or
.NOT.              ! negation

Examples:

! simplest form of if construct
if (a > b) then
    c =  b / 2
end if
!equivalent example with alternate syntax
if(a.gt.b)then
   c=b/2
endif

! named if construct
circle: if (r >= 0) then
    l = 2 * pi * r
end if circle

! complex example with nested if construct
block: if (a < e) then
    if (abs(c - e) <= d) then
        a = a * c
    else
        a = a * d
    end if
else
    a = a * e
end if block

A historical usage of the if construct is in what is called an “arithmetic if” statement. Since this can be replaced by more modern constructs, however, it is not covered here. More details can be found here.

SELECT CASE construct

A select case construct conditionally executes one block of constructs or statements depending on the value of a scalar expression in a select case statement. This control construct can be considered as a replacement for computed goto.

[name:] SELECT CASE (expr)
[CASE (case-value [, case-value] ...) [name]
   block]...
[CASE DEFAULT [name]
   block]
END SELECT [name]

where,

  • name - the name of the select case construct (optional)
  • expr - a scalar expression of type integer, logical, or character (enclosed in parentheses)
  • case-value - one or more scalar integer, logical, or character initialization expressions enclosed in parentheses
  • block - a sequence of zero or more statements or constructs

Examples:

! simplest form of select case construct
select case(i)
case(:-1)
    s = -1
case(0)
    s = 0
case(1:)
    s = 1
case default
    print "Something strange is happened"
end select

In this example, (:-1) case value is a range of values matches to all values less than zero, (0) matches to zeroes, and (1:) matches to all values above zero, default section involves if other sections did not executed.

Block DO construct

A do construct is a looping construct which has a number of iterations governed by a loop control

integer i
do i=1, 5
  print *, i
end do
print *, i

In the form above, the loop variable i passes through the loop 5 times, taking the values 1 to 5 in turn. After the construct has completed the loop variable has the value 6, that is, the loop variable is incremented once more after the completion of the loop.

More generally, the do loop construct can be understood as follows

integer i, first, last, step
do i=first, last, step
end do

The loop starts with i with the value first, incrementing each iteration by step until i is greater than last (or less than last if the step size is negative).

It is important to note that since Fortran 95, the loop variable and the loop control expressions must be integer.

An iteration may be ended prematurely with the cycle statement

do i=1, 5
  if (i==4) cycle
end do

and the whole construct may cease execution with the exit statement

do i=1, 5
  if (i==4) exit
end do
print *, i

do constructs may be named:

do_name: do i=1, 5
end do do_name

which is particularly useful when there are nested do constructs

do1: do i=1, 5
  do j=1,6
    if (j==3) cycle        ! This cycles the j construct
    if (j==4) cycle        ! This cycles the j construct
    if (i+j==7) cycle do1  ! This cycles the i construct
    if (i*j==15) exit do1  ! This exits the i construct
  end do
end do1

do constructs may also have indeterminate loop control, either “forever” or until a given condition is met

integer :: i=0
do
  i=i+1
  if (i==5) exit
end do

or

integer :: i=0
do while (i<6)
  i=i+1
end do

This also allows for an infinite do loop via a .true. statement

print *,'forever'
do while(.true.)
  print *,'and ever'
end do

A do construct may also leave the order of iterations indeterminate

do concurrent (i=1:5)
end do

noting that the form of loop control is the same as in a forall control.

There are various restrictions on the statements that may be executed within the range of a do concurrent construct which are designed to ensure that there are no data dependencies between iterations of the construct. This explicit indication by the programmer may enable greater optimization (including parallelization) by the compiler which may be difficul to determine otherwise.

“Private” variables within an interation can be realized by use of a block construct within the do concurrent:

do concurrent (i=1:5, j=2:7)
  block
    real tempval  ! This is independent across iterations
  end block
end do

Another form of the block do construct uses a labelled continue statement instead of an end do:

    do 100, i=1, 5
100 continue

It is even possible to nest such constructs with a shared termination statement

    do 100, i=1,5
    do 100, j=1,5
100 continue

Both of these forms, and especially the second (which is obsolescent), are generally to be avoided in the interests of clarity.


Finally, there is also a non-block do construct. This is also deemed to be obsolescent and is described elsewhere, along with methods to restructure as a block do construct.

WHERE construct

The where construct, available in Fortran90 onwards represents a masked do construct. The masking statement follows the same rules of the if statement, but is applied to all the elements of the given array. Using where allows operations to be carried out on an array (or multiple arrays of the same size), the elements of which satisfy a certain rule. This can be used to simplify simultaneous operations on several variables.

Syntax:

[name]: where (mask)
    block
[elsewhere (mask)
    block]
[elsewhere
    block]
end where [name]

Here,

  • name - is the name given to the block (if named)
  • mask - is a logical expression applied to all elements
  • block - series of commands to be executed

Examples:

! Example variables
real:: A(5),B(5),C(5)
A = 0.0
B = 1.0
C = [0.0, 4.0, 5.0, 10.0, 0.0]

! Simple where construct use
where (C/=0)
    A=B/C
elsewhere
    A=0.0
end

! Named where construct
Block: where (C/=0)
    A=B/C
elsewhere
    A=0.0
end where Block

This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow