Functions and Subroutines
Optional Arguments
some
dummy arguments of subprograms can be declared to be optional
allows
using default values for arguments
subroutine swap(x, y, condition)
integer, intent(inout) :: x,y
integer, intent(in), optional :: condition
integer :: temp
! condition = 1 performs a swap only if x
< y
! condition = 2 performs a swap only if x
> y
! if condition is not specified always
perform a swap
Optional Arguments
if present(condition) then
if
( (condition == 1) .and. (x < y)) then
temp = x; x = y ; y = temp
elseif ((condition == 2) .and. (x > y)) then
temp = x; x = y ; y = temp
endif
else
temp = x; x = y ; y = temp
endif
end subroutine swap
Using Optional Arguments
compulsory
arguments should come before optional arguments
if
some optional arguments are missing, keyword arguments used in calling
program
keywords
specify the dummy arguments which are to be assigned values
keywords
are names of dummy arguments and allow changing order of arguments
keywords
must be used for optional arguments
Keyword Arguments
arguments
specified by naming the dummy argument and assigning an expression to it
call swap(x,y,1)
call swap(x,y)
call swap(condition = 2, x = x, y = y)
if
a keyword argument is used, all later arguments must be keyword arguments
initial
arguments correspond by position
keywords
override positional correspondence
Array Arguments
whole
array can be an argument for a subprogram
corresponding
dummy argument must be an array of the same rank
shape
of dummy argument is not declared
assumed
to be same as that of corresponding actual argument
may
be different for different calls
intrinsic
functions used to determine shape
Array Arguments
subroutine inverse(a,b)
integer, intent(in), dimension(:,:) :: a
integer, intent(out), dimension(:,:) :: b
! declares a and b to be rank 2 arrays
! actual shape of a and b will depend on
actual argument
integer, dimension(size(a,dim=1), size(a,dim=2))
:: c
! c is a local variable
! shape of local arrays must be declared
! it can depend on the shape of actual
arguments
! c is also called an automatic array
Array Arguments
function sort(a) result(b)
integer, intent(in), dimension(:) :: a
integer, dimension(size(a)) :: b
integer :: i, j
do
i = 1, n
j = count(b(1:i-1) <= a(i))
b(j+2:i) = b(j+1:i-1)
b(j+1) = a(i)
end do
end function sort
Allocatable Arrays
allocatable
arrays must be allocated before being passed to a subprogram
allocatable
arrays used in subprograms must be deallocated in the subprogram
memory
leak can occur
each
execution of subprogram creates a new copy of the array which becomes
inaccessible after it terminates
use
automatic arrays instead
External Subprograms
subprograms
not contained in any program
such
subprograms can be compiled separately
can
be used ( called) by any program
same
structure as internal subprograms, except that they may contain other internal
subprograms
allows
sharing of code between programs
old
style of Fortran programming
not
recommended for Fortran 90
alternatives
available ( modules, see later)
External Subprograms
subroutine swap(x,y)
implicit none
! required here as not contained in any
program
real, intent(inout) :: x, y
real :: temp
temp = x
x = y
y = temp
end subroutine swap
! only variables declared in subprogram and
arguments
! can be used
Using External Subprograms
similar
to internal subprograms
call
statement used for subroutines and function names for functions
arguments
and declarations of external subprograms not known in calling program
an
explicit interface to external subprograms must be provided
all
declarations of arguments in subprogram must be included in calling program
Calling External Subprograms
program test_call
implicit none
real :: x, y
interface
subroutine swap(x,y)
real, intent(inout) :: x, y
end subroutine swap
end interface
read *, x, y
if
(x < y) then call swap(x,y)
print *, x, y
end program test_call
Interface Statement
all
definitions of subprograms used in a (sub)program contained in interface block
comes
after all declarations of variables
contains
first line of each subprogram used and declarations of all dummy arguments
interface
subroutine a(list_of_dummy arguments of a)
! declarations of dummy arguments in
subroutine a
end subroutine a
function b(list_of_dummy arguments of b)
! declarations of arguments of b
end function b
end interface
Using External Subprograms
file
containing several external subprograms may be compiled separately
-c
option should be used when compiling
subprograms
cannot be executed by themselves, must be called by a program
produces
object code ( .o files)
use
this file when compiling a program using any of these subprograms
executable
code is produced (called linking)
Libraries
a
precompiled collection of external subprograms can be built, can be used
whenever required
library
of subprograms
many
commercial libraries available especially for numerical computation
source
code is not available
cannot
make modifications
build
your own library
interface
to subprograms must be known
General Integration Program
trapezoidal
rule can be applied to integrate any function
function
to be integrated is external
main
program can be compiled (with c option) without the function to be integrated
produces
a .o file
compile
the external function with this
program
needs to be compiled only once
General Integration Program
program integrate
implicit none
real :: a, b, h, integral
integer :: n, i
interface
function f(x)
real, intent(in) :: x
real :: f
end function f
end interface
print *, enter endpoints and number of intervals
read *, a, b, n
h = (b-a)/real(n)
integral = (f(a)+f(b))/2.0
! uses external function f
do
i = 1, n-1
integral = integral + f(a+i*h)
end do
integral = integral*h
print *, integral is, integral
end program integrate
Function Arguments
names
of functions can be arguments
general
subprogram for integration
name
of function to be integrated can be passed as a parameter
same
subprogram used for integrating many different functions
name
of function specified when subprogram is called
name
is not a character string
Example
subroutine trapezoid(f,a,b,n,integral)
implicit none
real, intent(in) :: a, b
real, intent(out) :: integral
real, external :: f !
declares f an external real function
integer, intent(in) :: n
real :: h
integer :: i
h = (b-a)/real(n)
integral = (f(a)+f(b))/2.0
do
i = 1, n-1
integral = integral + f(a+i*h)
end do
integral = integral * h
end subroutine trapezoid
program integrate
implicit none
real :: a, b, integral
integer :: n
real, external :: func1, func2, func3, func4
character(len=5) :: name
interface
subroutine trapezoid(f,a,b,n,integral)
real,
intent(in) :: a,b
integer,
intent(in) :: n
real,
intent(out) :: integral
real,
external :: f
end
subroutine trapezoid
end interface
print *, "enter function to be integrated"
read *, name
print *, "give end points of interval"
read *, a, b
print *, "enter number of intervals"
read *, n
select case(name)
case("f1")
call trapezoid(func1,a,b,n,integral)
case("f2")
call trapezoid(func2,a,b,n,integral)
case("f3")
call trapezoid(func3,a,b,n,integral)
case("f4)
call trapezoid(func4,a,b,n,integral)
case default
print *, "unknown function
stop
end select
print *, "integral is", integral
end program integrate
function func1(x)
implicit none
real, intent(in) :: x
real :: func1
func1 = x*sin(x)
end function func1
function func2(x)
! statements in function func2
end function func2
Compilation
all
subprograms maybe in separate files
f90
c integrate.f90 trapezoid.f90
will
produce files integrate.o and trapezoid.o
f90
c func1.f90 func2.f90 func3.f90 func4.f90
link
all files together to form executable code
f90
integrate.o trapezoid.o func1.o func2.o
.
all
required functions must be available before executable code can be generated