# Flow control

February 2020

Back to index.html.

# Flow control

As previously noted, a Fortran program sequentially executes the code from the beginning through the end. By default, the program does not skip any single statement and does not go back to the previous statements. We are going to see some control statements which change the flow or repeat the same statements many times.

## Conditional

### The if statement

#### Simple example

You often want to change the flow by the condition. A typical example is to test the input value; you can print an error message if the values are invalid. To make branches by condition, Fortran provides the if statement, as seen in the following example.

program cond
implicit none
real :: x
if(x<0.0) then
print *,'The value should be 0 or positive.'
stop
else
print *,'square root=',sqrt(x)
end if
end program cond

Note that I put an indent to the if statement to make the structure clearer (and it is a good practice). The stop keyword stops the program immediately. You can see how to use the if statement with this example.

• The if statement starts with if (condition) then and ends with end if. The condition is a logical expression which returns .true. or .false..
• The if statement has 2 blocks: the first one between if and else, and the second one between else and end if. Each block is exclusively executed by the condition in the if statement.
• If the condition is true, the program proceeds the first block and exits the statement (jumps to the next line of end if).
• If the condition is false, the program jumps to the second block and exit the statement.

The above if statement has the following structure.

if(condition 1) then
{block}
else
{the other block}
end if

The if statement has some flexible structure. The following code runs in the same way as above (only the kernel of the program is shown).

! Alternative 1
if(x>=0.0) then
print *,'square root=',sqrt(x)
else
print *,'The value should be 0 or positive.'
stop
end if

! ----------------------------------------------
! Alternative 2
if(x<0.0) then
print *,'The value should be 0 or positive.'
stop
end if
print *,'square root=',sqrt(x)

The first alternative has the opposite condition as the original one. The second alternative has no else block; the program stops if the conditional meets, so it does not need the else block.

#### General form of if

The if statement has the following general form.

if(condition 1) then
{block 1}
else if(condition 2) then
{block 2}
else if(condition 3) then
{block 3}
...
else
{the other block}
end if

In the above case, the program can be interpreted as follows.

• The program first tests Condition 1, and if true, it executes Block 1 only and exits the statement.
• If Condition 1 is not true, then it tests condition 2, and if true, it executes Block 2 and exits the statement.
• If Condition 2 is not true, then it tests condition 3, and if true, it executes Block 3 and exits the statement.
• You can put more else if statements between the first if and else.
• You can optionally put else at the bottom of the statement. The Else block will be executed if all the conditions do not meet.

When there is no else block, if all conditions do not meet, the program does nothing and exits the statement.

By the way, Fortran accepts endif instead of end if (and elseif vs. else if). Also, spaces are allowed to be between if and ( i.e. if (condition) then. This tutorial uses end if and else if, but it is my preference. You can use your favorite style.

#### One-line if

When you have only 1 block, i.e. if(...) then ... end if and the block has only 1 statement, you can write the code in 1 line.

program cond
implicit none
real :: val
if(val==0.0) stop
print *,val
end program cond

#### Logical expressions

You can combine several conditions with .and. and .or.. Recall the rule to make logical expressions. The following program precisely finds the error of input values and gives the user messages about what is wrong. It accepts two positive numbers from the keyboard and calculates a value.

program cond
implicit none
real :: x,y
if(x<0 .and. y<=0) then
print *,'error: x<0 and y<=0'
else if(x<0) then
print *,'error: x<0'
else if(y<=0) then
print *,'error: y<=0'
else
print *,'sqrt(x)*log(y)=',sqrt(x)*log(y)
end if
print *,'done.'
end program cond

#### Nested if statements

The if statements can be nested, which means you can put it in another if statement. You can cascade a conditional test to another. The following example is an alternative version of the previous program.

program cond
implicit none
real :: x,y
if(x<0) then
print *,'error: x<0'
else
if(y<=0) then
print *,'error: y<=0'
else
print *,'sqrt(x)*log(y)=',sqrt(x)*log(y)
end if
end if
print *,'done.'
end program cond

In this case, the program does not detect the case where both x and y are invalid at the same time. The original code looks flat and checks all possible cases on the same line. The above code shows a clear intent that checks x first and y second.

I have to admit that the above example is artificial to show the nested-if. The code is equivalent to the following program with a single if-elseif-else block.

   if(x<0) then
print *,'error: x<0'
else if(y<=0) then
print *,'error: y<=0'
else
print *,'sqrt(x)*log(y)=',sqrt(x)*log(y)
end if

#### Summary

• The if statement starts with if(condition) then and ends with end if.
• The condition has a logical expression resulting in a single .true. or .false..
• You can optionally insert else if(condition) as many as possible and one else into the statement.
• If the condition meets, the program executes the immediately beneath block and exits the current if statement (moves to the next line of end if).
• If the condition does not meet, the program jumps to the next else if and evaluates the condition and decide whether the program takes the block or not.
• If all the conditions are false and there is the else block, the program executes it.
• The if statement can be nested.

#### Exercises

• Read 1 integer (code) and 1 real numbers (v) from the keyboard. If the code is 1, compute the square root of v. If the code is 2, compute the sine of v. If the code is the other values, print an error message and stop the program.
• Read an integer and show if it is an even or odd number.

### The select statement

#### Simple example

There is a convenient statement (select) to make branches conditioned by a single value. The select statement is useful to compare between a scalar with a literal (or, a range of literals). Here is a piece of code that shows a typical case where select works well.

   integer :: x
if(x==1) then
print *,'case 1'
else if(x==2 .or. x==3) then
print *,'case 2 or 3'
else
print *,'failed'
end if

With the select statement, the code becomes readable and straightforward as follows.

   integer :: x
select case(x)
case(1)
print *,'case 1'
case(2,3)
print *,'case 2 or 3'
case default
print *,'failed'
end select

The select statement has the following structure.

• The statement starts with select case(x) and end select where x is a single variable or a literal (i.e., scalar).
• The statement has 1 or more case(y) where y is a literal, a range, or a list of them. y should not be a variable. For example, case(1), case(1,2,5), case(2:3), case(2:3,5) are all valid.
• The program starts comparing x with y from the first case block to the last. If x equals to y, the program performs this block, and exit the entire select statement without moving toward the next block.
• If x does not match any y, the program executes the optional case default block. If you omit this block, the program does not do anything.

Here is a general form of the select statement.

select case(scalar)
case(literal list 1)
{block 1}
case(literal list 2)
{block 2}
...
case default
{the other block}
end select

#### Exercises

1. Confirm that the select statement can accept characters. Declare a character variable (say, character(len=10)::s), and make the branches by the variable (select case(s) or select case(s(1:2))).

## Iteration

### The do statement

#### Small example

There is a case where you have to repeat the same operation many times. Or, you need to repeat slightly different but almost the same operation by round. The simplest way is to write all the repeated operations as a flat program, but it should be in trouble in its readability and redundancy. Fortran provides a systematic way to repeat the same (or similar) operation with the do statement.

For example, consider printing Hello, world! 3 times. It can be written in Fortran as follows.

program loop
implicit none
integer :: i
do i=1,3
print *,"Hello, world!"
end do
end program loop
 Hello, world!
Hello, world!
Hello, world!

You may need some explanation.

• The operations (block) that you want to repeat are placed between do and end do.
• The do keyword accompanies with an integer variable, here, i.
• The variable i is automatically initialized to 1 (as specified in the do statement) before the loop starts.
• In the 1st iteration, i is compared with the last value 3 as i<=3. It is true, and the program executes the block.
• When the program reaches end do, it jumps back to do, and increment i by 1. In this case, i becomes 2.
• In the 2nd iteration, i is compared with the last value 3 as i<=3. It is true, and the program executes the block.
• When the program reaches end do, it jumps back to do, and increment i by 1. In this case, i becomes 3.
• In the 3rd iteration, i is compared with the last value 3 as i<=3. It is true, and the program executes the block.
• When the program reaches end do, it jumps back to do, and increment i by 1. In this case, i becomes 4.
• In the 4th iteration, i is compared with the last value 3 as i<=3. It is false, and the program jumps out of end do.

The key to understanding the do loop is as follows.

1. The do statement needs an integer variable (any name; i in this case) as a counter.
2. The do statement has the following form: do variable = starting value, final value.
3. Before the loop, the variable is initialized to the staring value.
4. Whenever the program reaches do, the variable is compared to the final value. If the variable is smaller than or equals to the final value, the focus moves to the next line; Otherwise, the program exits the current loop.
5. Whenever the program reaches end do, the focus goes back to the corresponding do, then the variable is incremented by 1 (and going back to Step 5).

Here is a general form of do.

do counter_variable = initial_value, last_value
{block}
end do

In this usage, do needs a counter variable. This behavior is like to count up numbers by hand. The counter variable is checked only at the beginning of loops, and it is incremented when going back from end do to do.

By the way, this program also works when i=1,3 is replaced with i=0,2 or even i=-5,-3 (please consider why). Non-1 starting value looks unusual but can be useful in future use.

#### Use of the counter variable

The counter is an integer variable, so the program refers to the value of this variable in each iteration (but can not rewrite the variable because the statement protects it). In the above case (i=1:3), the counter i is 1 in the 1st iteration, 2 in the 2nd, and 3 in the last iteration. After the loop, i becomes 4.

The previous example can be slightly changed to show the current iteration number.

program loop
implicit none
integer :: i
do i=1,3
print *,"iteration",i,": Hello, world!"
end do
end program loop
 iteration         1: Hello, world!
iteration         2: Hello, world!
iteration         3: Hello, world!

This variable can also be used in a numerical formula. The following example computes the multiple of 3.

program loop
implicit none
integer :: i
do i=1,9
print *,i," x 3 = ",i*3
end do
end program loop
           1  x 3 =            3
2  x 3 =            6
3  x 3 =            9
4  x 3 =           12
5  x 3 =           15
6  x 3 =           18
7  x 3 =           21
8  x 3 =           24
9  x 3 =           27

Any other variables can be used inside the loop. The following program calculates the factorial of an arbitrary integer read from the keyboard.

program loop
implicit none
integer :: i,n,fact
fact = 1
do i=1,n
fact = fact*i
end do
print *,n,"! = ",fact
end program loop
 # when putting 5:
5 ! =          120

Note that the variable fact for storing the result must be initialized by 1 before the loop. This program does not work if you put a large number (it overflows). The variable is changed to double precision to fix this issue (see exercises).

The counter variable should be an integer. If you need a real number that incrementally changes, you have to calculate the value from the counter. The following program calculates the square root of a real number ranged from 0 to 1 by 0.1.

program loop
implicit none
integer :: i
real :: v
do i=0,10
v = real(i)/10
print *,sqrt(v)
end do
end program loop

#### Break and skip the loop

You may break (exit) a loop when a condition is true. The keyword exit immediately exits the do statement by jumping to the next line of end do. It may happen when you repeatedly read a value from the keyboard and stop reading when the input is invalid.

program loop
implicit none
integer :: i
real :: val

! read value 10 times but exit the loop if the input is negative.
do i=1,10
if(val < 0) exit
print *,sqrt(val)
end do
end program loop

If you want to skip the rest of the statements in the loop and start the next iteration, you can use the cycle keyword, which immediately moves the focus to the beginning of do. In the above code, if you replace exit by cycle, it jumps back to the do statement and starts the next round. You should see if this program reads the value precisely 10 times.

program loop
implicit none
integer :: i
real :: val

! read value 10 times but skip the round if the input is negative.
do i=1,10
if(val < 0) cycle
print *,sqrt(val)
end do
end program loop

#### Infinite loops

If you don’t know how many iterations are needed, do continues the loop forever. Such a structure is called infinite loops, and it never ends unless the program meets exit in the loop. Making infinite loops, you just drop the iterator and use do alone.

program loop
implicit none
real :: val

! read a value but exit the loop if the input is negative.
do
if(val < 0) exit
print *,sqrt(val)
end do
end program loop

Here is a general from of the infinite loops. The code block should have the exit statement.

do
{block with exit}
end do

Again, this unconditional do statement creates the infinite loops, and the program may never stop unless the program reaches exit. The compiler can not detect the infinite loops as a failure. If you run into this issue, hit the Control key (Ctrl) and the C key simultaneously (hit C while pushing Ctrl).

#### Writing a loop

The loop in a programming language has a unique syntax that is not necessarily clear to the beginners. If you know that you have to write a loop but do not know how to write it, please consider the following method.

First, you can think of the result of the loops. For example, you want to get the following output on the screen.

number =          3
number =          4
number =          5

Then, you look for a common thing across iterations.

• Each output should be from the print statement, and you can find the common message in the output, number =.
• The common statement over the loops is print *,"number =".
• You can put a variable to stuff that changes by iteration: print *,"number = ",x.

Finally, you enclose the common code by the do statement.

do
print *,"number = ",x
end do

If the variable systematically changes by iteration, it can be a counter variable. In this case, x ranges from 3 to 5, and here is the code.

do x=3,5
print *,"number = ",x
end do

Or, you may think of the following code.

x = 3
do
print *,"number = ",x
x = x + 1
if(x>=6) exit
end do

The first loop is more transparent for any people than the latter, while the latter code is very straightforward (but it may look more complicated for some people). Although the first code is preferred, we would need a loop like the other code.

There are many cases to generate a sequence in Fortran. The do statement is a typical mechanism to generate the sequence, and it is a solution for the purpose.

#### Practical use of loops

The loop has 2 different viewpoints in practice.

1. Iteration: repeating the same (or similar) operations a finite number of times.
2. Sequence of numbers: generating a series of numbers.

The latter is useful when you manipulate the subscript (index) of an array (e.g., matrix and vector that we are going to see later). When you have to change the index or any numbers systematically, you will use the loops.

#### Summary

• The do statement defines a loop. The statements between do and the corresponding end do are repeated.
• The loop can have an integer variable indicating how many times the loop is repeated. The user can refer to the counter as a variable.
• When the program reaches end do, the focus goes back to the corresponding do, then the counter is incremented by 1.
• The evaluation of the counter occurs at do, the top of the loop. If the counter is greater than the final value, the program exits the loop, i.e., going to the next line of end do.
• The exit statement jumps out of the loop. The cycle statement immediately goes back to do, ignoring the remaining statements.
• Without the counter, do makes an infinite loop. The exit statement is the only way to exit the loop.
• The loop is useful to repeat a task many times or to generate a sequence of numbers.

#### Exercises

1. Rewrite the code to compute a factorial with a larger n using a double-precision variable.
2. Read 10 numbers from the keyboard, then show how many positive numbers were given.
3. Write a fizz buzz program. It prints integer numbers from 1 to n on screen, but when the number is divisible by 3 is replaced by the word fizz, any number divisible by 5 by the word buzz, and the numbers divisible by 15 by the word fizz buzz only (without showing any of fizz and buzz).

### Variation in loop

In this subsection, we are going to see a variation of the loop, particularly useful to generate a sequence of numbers.

#### Non-executable loop

You can use variables as the staring and the last values. In such a case, the loop may not be executed. It is a valid program, and it often appears in some algorithms.

program loop
implicit none
integer :: i,a,b

! not executed when a>b
do i=a,b
print *,i
end do
end program loop

#### Non-1 increment

By default, the counter variable is incremented by 1. The user can change the increment to any non-zero integer as the 3rd parameter in the do statement. For example, the following code shows odd numbers up to 10 (actually 9).

program loop
implicit none
integer :: i

! counter incremented by 2
do i=1,10,2
print *,i
end do
end program loop
           1
3
5
7
9 

It is equivalent to write the following code. You can use whatever you prefer.

   do i=1,5
print *,2*i-1
end do

Using this technique, the user can define a loop where the counter decrements.

program loop
implicit none
integer :: i

! from 5 to 1 by -1
do i=5,1,-1
print *,i
end do
end program loop
           5
4
3
2
1

#### Summary

• If the staring value is already larger than the final value in a loop, such a loop will not be executed.
• The increment is defined in the 3rd parameter in do. It should be non zero integers.

#### Exercises

1. Print the following sequence of integer numbers on the screen (first 12 numbers of the sequence).
1. $2, 4, 6, 8, 10, 12, 14, \cdots$
2. $0, 1, 3, 6, 10, 15, 21, \cdots$
3. $1, -1, 1, -1, 1, -1, \cdots$
4. $1, 2, 0, 4, 5, 0, 7, 8, 0, \cdots$
5. $1, 2, 4, 5, 7, 8, \cdots$
2. Compute $4x$ where $x=1-\frac{1}{3}+\frac{1}{5}-\frac{1}{7}+\frac{1}{9}+\cdots$ for the first 1 million terms.
3. Factor $2099829353$ into two primes (i.e. find primes $x$ and $y$ so that $xy=2099829353$).

### Nested loops

You can define nested loops with multiple dos. Here, for simplicity, we just consider double loops with two do statements.

#### Double loops

As the if statement, do can also be nested. You can see how the nested loops work in the following example.

program loop
implicit none
integer :: i,j

do i=1,3
do j=7,9
print *,i," x ",j,"=",i*j
end do
end do
end program loop
           1  x            7 =           7
1  x            8 =           8
1  x            9 =           9
2  x            7 =          14
2  x            8 =          16
2  x            9 =          18
3  x            7 =          21
3  x            8 =          24
3  x            9 =          27

This program prints some products. When the program enters the first loop do i=1,3, the initial i is set. Then the program enters the second loop do j=7,8. In the second loop, i is preserved, and j is updated in this loop. When the second loop ends, the focus returns to the top of the first loop, then i is incremented, and the second loop is executed again. When The outmost loop ends, the entire loop block is done.

#### exit and cycle

With multiple loops, exit and cycle are valid only for the current loop. For example, the following code tries to exit the loop when $i\times j = 16$.

program loop
implicit none
integer :: i,j

do i=1,3
do j=7,9
if(i*j==16) exit
print *,i," x ",j,"=",i*j
end do
end do
end program loop

The exit statement is active when i=2 and j=8, and it just exits the current (the innermost) loop. So, the output looks like this.

           1  x            7 =           7
1  x            8 =           8
1  x            9 =           9
2  x            7 =          14
3  x            7 =          21
3  x            8 =          24
3  x            9 =          27

It surely skips i=2 and j=8. But what if you want to exit the entire loop (the outer loop)? The simplest option is stop, but it stops everything. In Fortran, you can specify do, which you particularly exit by using a label. A label is an arbitrary name stuck to do, and the corresponding end do statements. In the following example, the outer do has a label outer with a colon (:), the corresponding end do has the same label, and exit specifies the label.

program loop
implicit none
integer :: i,j

outer: do i=1,3
do j=7,9
if(i*j==16) exit outer
print *,i," x ",j,"=",i*j
end do
end do outer
end program loop
           1  x            7 =           7
1  x            8 =           8
1  x            9 =           9
2  x            7 =          14

The same principle applies to cycle.

#### Summary

• Nested loops can be defined.
• The do (and end do) statement can have a label, which is a sequence of arbitrary characters.
• The label is used by exit and cycle` to specify the loop.

#### Exercises

1. Show all pairs of integers ($a$ and $b$; $0<a,b<20$) to satisfy that $a/b$ is an integer number.
2. Write a program to find triplets of integer numbers ($a$, $b$, and $c$) to satisfy $a^2+b^2=c^2$ where $0<a,b,c<1000$. Just show the first 10 sets of numbers.

Back to index.html.