Note: Structured programming was invented to eliminate the spagetty code syndrom that can be encontered in linear programming. Fortran use to have GO TO statement to jump back and forward in the program using numeric labels. In modern Fortran we no longer use goto statement.
Fotran has a special keyword to define the main program. This is translated to function main() in C, and is the entry point of any fortran application. The main program has a name and two regions: executable region and content region.
First region after program name is the the executable region. You can use this to declare arguments, parameters and local variables but also the main thread of the application. Second is the content region for local functions and subroutines.
!this is fortran
program main
! declare arguments
! declare parameters
! declare variables
...
! program statements
...
contains
! declare subprograms
...
end program
Program parameters are declared using statements. The input parameters must be parsed. There are specific variable names and functions available to capture the program parameters.
The program terminates when there is an error. If the program do not have errors, the exit status is 0, and can be verified by an external script or in the command line by using command: echo $?
. Exit status can be set using 2 methods:
A subroutine is a subprogram that have a name, input/oturput parameters and side-effects. Subroutine has it's own local scope where you can declare variables. The subroutine can be created in "contains" region of program.
The arguments are declared without type in the subroutine signature. These are called formal dummy arguments. At the beginning of the soubroutine, after signature, you can declare every argument intention and set arguments optional by using declarative statements similar to local variables.
A subroutine can have only one end but many exit points. A subprogram can use return statement many times to create early exit points. Usually return is used for preconditions and is very convenient to intrerupt the subprogram when the job is done.
A subroutine can have one or more results. The results are usually declared similar to arguments, except these are output arguments. You can set the result value as any other variable during subroutine execution. You must prepare the result before return.
A subroutine is not executed when is declared but later. It can be called once or many times from main thread or from another subroutine. You can use special statement call to execute a subroutine.
!declare subroutine
program main
! call subroutine
call test(<arguments>)
contains
! test is the subroutine name
subroutine test(<dumy_arguments>)
! declarations statements
...
! computation statements
return
end subroutine
end program
Fortran has enhanced support for functions. A function can return a single result. You can define the dummy result name in the function signature using keyword result. You need to define the result type using declarative statement in the function body like any other variable.
Function Components
The arguments are declared without type in the function signature. These are called dummy arguments. At the beginning of the function, after the signature, you can declare every argument type using declarative statements similar to local variables.
Functions can be called in main program or subroutines using function name follow by round brackets () that contain list of actual arguments. Functions can be used in expressions.
!declare functions
program main
! main thread
type_name:: x, y
y=fn(x) ! call function
contains
! fn is the function name
function fn(p) result(r)
! declaration
type_name:: p
type_name:: r
...
! prepare result
r = <expression>
end function
end program
Fortran is a modular language. Modules, are usually stored in external files but can be created in the same file as the main program. You must import a module before you can use it's members. You can import a module using the keyword: "use".
!declare module
module test
! declare module variables
...
contains
! fn is the function name
function fn() result(r)
! prepare result
r = <expression>
end function
end module
!using module
program main
use test
y=fn() ! call function
end program
Notes: Modules can be contained in the same file as the main program but also can be in separate files. When using separate files, the compiler can compile multiple modules. You can pass module names as a list of names to the compiler.
In Fortran we define dummy arguments and actual arguments. They are not one and the same. Dummy arguments must be defined inside subprograms while actual arguments are values that are transfered to the dumy arguments as copy or references.
Currently, Fortran doesn't allow setting a default value for optional dummy arguments. If declaring a dummy argument as optional, the user must implement special code:
! arguments by name
program main
integer:: r1,r2,r3
r1 = suma(2)
r2 = suma(2,4)
r3 = suma(2,4,6)
print *, "r1 = ", r1
print *, "r2 = ", r2
print *, "r3 = ", r3
contains
function suma(a,b,c) result(re)
integer:: a, b, c, re
optional:: b, c
! default values
integer:: b1, c1
if (present(b)) b1=b
if (present(c)) c1=c
! prepare result
re = a + b1 + c1
end function
end program
>./argname
r1 = 2
r2 = 6
r3 = 12
Note: A call must transfer arguments to a subprogram using one of two association techniques: by position or by name. You can specify the name of the arguments in the call. This is an important feature, useful especially when the posible arguents are many and some are optional. Built-in and standard Fortran functions and subroutines can have optional arguments that you can pass by name.
Function and subroutine can modify values of arguments. The new value can propagate back to the actual argument. The literals and the expression results are allways pass by value. Receiver arguments can be pass by reference.
! argument intent (demo)
program main
integer:: op = 0
call test(a=2, b=4, re = op)
print *, "a + b = ", op
contains
subroutine test(a,b,re)
integer, intent(in):: a, b
integer, intent(out):: re
! prepare result
re = a + b
end subroutine
end program
>./out
a = 2, b = 4
a + b = 6
In Fortran parameters are not arguments. Parameters are actually local constants. That may be confusing! Parameters are local variables with initial value, protected against change.
! local parameter
program main
integer:: r1,r2,r3
r2 = avg(2,4)
print *, "avg = ", r2
contains
function avg(a,b) result(re)
integer:: a, b, re
integer, parameter:: c = 2
re = (a + b) / 2
end function
end program
>./parameter
r2 = 3
Recursive functions are special functions that can call themselves several times with different arguments. Fortran has suport for unlimited recursion. The only limitation is that you can run out of memory.
The following code is doing a well known test called "ackermann function". To understand this function better you can check this article: Wikipedia: Ackerman Function
! ackermann test
program recursion
integer :: ack
real::t1,t2
call cpu_time(t1)
write(*,*) ack(3, 12)
call cpu_time(t2)
write(*,'("time=",f6.4)') (t2-t1)
end program
recursive function ack(m, n) result(a)
integer, intent(in) :: m,n
integer :: a
if (m == 0) then
a=n+1
else if (n == 0) then
a=ack(m-1,1)
else
a=ack(m-1, ack(m, n-1))
end if
end function
./recursion
32765
time=3.4615
Read next: Control Flow