One of the powerful advantages of computer algorithms, compared to simple mathematical formulae, comes in the form program branching whereby the program can decide which instructions to execute next based on a logical condition.
There two main forms of controlling program flow:
Conditional (if): choose program path based on a boolean (true or false) value
Loop: repeat a portion of code multiple times
Before we use a conditional branching operator, we need to be able to form a logical expression.
To form a logical expression the following set of relational operators are available:
||Tests for equality of two operands|
||Test for inequality of two operands|
||Tests if left operand is strictly greater than right operand|
||Tests if left operand is strictly less than right operand|
||Tests if left operand is greater than or equal to right operand|
||Tests if left operand is less than or equal to right operand|
as well as the following logical operators:
||TRUE if both left and right operands are TRUE|
||TRUE if either left or right or both operands are TRUE|
||TRUE if right operand is FALSE|
||TRUE if left operand has same logical value as right operand|
||TRUE if left operand has the opposite logical value as right operand|
In the following examples, a conditional
if construct is used to print out a
message to describe the nature of the
Example: single branch
if (angle < 90.0) then print *, 'Angle is acute' end if
In this first example, the code within the
if construct is only executed if the
test expression (
angle < 90.0) is true.
Tip: It is good practice to indent code within constructs such as
to make code more readable.
We can add alternative branch to the construct using the
if (angle < 90.0) then print *, 'Angle is acute' else print *, 'Angle is obtuse' end if
Now there are two branches in the
if construct, but only one branch is executed depending
on the logical expression following the
We can actually add any number of branches using
else if to specify more conditions:
if (age < 90.0) then print *, 'Angle is acute' else if (angle < 180.0) then print *, 'Angle is obtuse' else print *, 'Angle is reflex' end if
When multiple conditional expressions are used, each conditional expression is tested only if none of the previous expressions have evaluated to true.
In the following example a
do loop construct is used to print out the numbers in
do loop has an integer counter variable which is used to track which iteration of the loop
is currently executing, in this example we use a common name for this counter variable:
When we define the start of the
do loop we use our counter variable name followed by an equals (
to specify the start value and final value of our counting variable.
integer :: i do i=1,10 print *, i end do
do loop with skip
integer :: i do i=1,10,2 print *, i ! Print odd numbers end do
A condition may be added to a
do loop with the
while keyword. The loop will be executed while the condition given
while() evaluates to
do while() loop
integer :: i i = 1 do while (i < 11) print *, i i = i + 1 end do ! Here i = 11
Most often than not, loops need to be stopped if a condition is met. Fortran provides two executable statements to deal with such cases.
exit is used to quit the loop prematurely. It is usually enclosed inside an
Example loop with
integer :: i do i=1, 100 if (i > 10) then exit ! Stop printing numbers end if print *, i end do ! Here i = 11
On the other hand,
cycle skips whatever is left of the loop and goes into the next cycle.
Example loop with
integer :: i do i=1,10 if (mod(i,2) == 0) then cycle ! Don't print even numbers end if print *, i end do
Note: When used within nested loops, the
exit statements operate on the inner-most loop.
A recurring case in any programming language is the use of nested loops. Nested loops refer to loops that exist within another loop. Fortran allows the programmer to tag or name each loop. If loops are tagged, there are two potential benefits:
cyclemay be used with tags, which allows for a very fine-grained control of the loops.
Example tagged nested loops
integer :: i,j outer_loop: do i=1,10 inner_loop: do j=1,10 if ((j+i) > 10) then ! Print only pairs of i and j that add up to 10 cycle outer_loop ! Go to the next iteration of the outer loop end if print *, 'I=', i, ' J=', j, ' Sum=', j+i end do inner_loop end do outer_loop
do concurrent loop is used to explicitly specify that the inside of the loop has no interdependencies; this informs the compiler that it may use parallelization/SIMD to speed-up execution of the loop and conveys programmer intention more clearly. More specifically, this means
that any loop iteration does not depend on the prior execution of other loop iterations. It is also necessary that any state changes that may occur must only happen within each
do concurrent loop.
These requirements place restrictions on what can be placed within the loop body.
do concurrent is not a basic feature of Fortran. The explanation given does not detail
all the requirements that need to be met in order to write a correct
do concurrent loop. Compilers are also free to do as they see fit,
which means they may not optimize the loop.
do concurrent() loop
real, parameter :: pi = 3.14159265 integer, parameter :: n = 10 real :: result_sin(n) integer :: i do concurrent (i=1:n) ! Careful, the syntax is slightly different result_sin(i) = sin(i*pi/4.) end do print *, result_sin