Functions and
Subprograms
Monolithic Structure
•
Programs seen so for are just of made
of a
–
single unit programs: one single block
of declarations and statements
•
Single block monolithic programs fine
for small programs (50 or less LOC)
•
Not good for larger programs that you
will write; definitely not for your projects
•
Very difficult to understand, debug and
develop
• Some
way of structuring the code required
Programming with Subroutines
• All modern PLs have features to
structure the code into multiple units
• This feature enables composing a large
program from a number of smaller subprograms
• A typical program consists of
– a number of subprograms
– and a main program
• The main program is invoked by the user
• The main program, in turn, invoke the
other subprograms
Design Decomposition
This structuring mechanism has lot of
advantages:
• Readability and understandability of code improves
– Main program and subprograms can be
individually read and understood
• Supports structured
development process
– Break a complex problem into simple
ones,
– arrive at subprograms for smaller ones
– Problem definition, algorithm design,
verification, coding and testing all are decomposed
Advantages of Subprograms
• Concurrent and independent design of subprograms (Teams of
programmers)
• Reuse of existing code
–
If someone had already solved one of the subtasks, use them
by taking the solution as a subprogram (avoids reinvention)
– Library of reusable components or units
Subroutine Definition
A subroutine is an independent program
unit:
SUBROUTINE name ( argument_list)
...
Declaration Section
...
Executable section
RETURN
END SUBROUTINE [name]
Programs and Subroutines
• A subroutine almost resembles normal programs
• It has its own name, a declaration part and an executable
part
• It is compiled separately
• One difference is:
– It can not be directly executed,
– executed via the (main) program
• Another difference is:
– a list of arguments, variable names
– arguments are dummy, placeholders
Calling subroutines
• A subroutine is executed by the main program
• This happens when main program executes a statement
CALL
subroutine_name (argument_list)
• We say that the main program `calls' the subroutine
• When the main program calls the subroutine,
– its execution is suspended
– Control jumps to the beginning of
execution part of the subroutine
• When the subroutine completes its execution (by executing
the RETURN statement or reaching the end of subroutine)
– Control returns to the main program
– Execution proceeds from the next
statement
Call Control Flow
Call Data Flow
• The arguments given in a call statement are called actual
arguments
• The number, order and type of actual arguments must match
that of dummy arguments
• Subroutine declaration includes dummy argument declarations
• When the subroutine is invoked (called) by the main program,
the values of actual and dummy arguments are exchanged.
• Values of some actual arguments are passed to the
corresponding dummy ones at the beginning
• Values of some dummy arguments are passed to the actual ones
at the end of the call
INTENT Declaration
• Dummy arguments are of three kinds:
REAL,
INTENT(IN):: dummy1
INTEGER,
INTENT(OUT):: dummy2
REAL,
INTENT(IN OUT):: dummy3
• dummy1 input argument: receives value at the beginning from
corresponding actual argument
• dummy2 output argument: It passes a value at the end of the
call to the corresponding actual argument
• dummy3 input-output argument: It receives a value at the
beginning and passes a value at the end from/to the actual argument
Local Variables
• Besides dummy arguments, other
variables may be declared in a subroutine
• They are called local since they are
accessible only locally
• Main program can not access them
• The names of these variables (or dummy
arguments) may be same as some other variables in the main program
• The name spaces are distinct
• Same variables names, labels can appear
in a subroutine
Example
Subroutine swap (var1,var2)
! swaps the contents of var1 and var2
implicit none
integer, intent(inout):: var1,var2
!local variable
integer :: temp
temp = var1
var1 = var2
var2 = temp
return
end Subroutine
Explanation
• This subprogram takes two input
arguments, swaps their contents and returns
• The two parameters are of intent INOUT
so that values can be passed to and returned from them
• temp is a local variable
• This subroutine can be separately
compiled
• It can be invoked from a main program
Main program
program sort3
implicit none
integer *, x1,x2,x3
read *, x1,x2,x3
if (x1 > x2) then
call swap (x1,x2) ! call to the subroutine
if (x2 > x3) then
call swap (x2,x3)
if (x1 > x2) then
call swap(x1,x2)
endif
endif
elseif (x2 > x3) then
call swap(x2,x3)
if (x1 > x2) then
call swap(x1,x2)
endif
endif
write *, x1, x2, x3
end program
Observation
• Any number of calls to the subroutines
• Each call supplies a list of actual arguments
• values of actual arguments will be changed after the
call if they are INOUT or OUT arguments
• Local variable temp is used in all the invocations
• Its value is different in different invocations
•
It does not retain its
value across invocations
CALL statement
• CALL is an executable statement
• This can appear in the main program and
even in the subroutine
• When the call statement in a subroutine
is executed, control transfers to subroutine named in the call
• So, starting from a main program, a
series of calls can be made to same or different subroutines
• Calls to the same subroutine possible -
Recursive Call
Call - Return Sequence
Internal Procedures
• Subroutines appearing within the main program definitions
are called internal procedures
– Their definition appear before the end
statement of the program
– all subroutines given one after another
– no nesting of definition
– before the first subroutine, write CONTAINS
– exactly one CONTAINS in a program
– variables declared in the main program
can be used in the routine
– Global variables
Example
Program example
!declaration
. . .
!executable statement
. . .
Contains
Subroutine proc1
...
end subroutine
...
end Program
External Subroutines
• Subroutines can appear in separate files
– All the files compiled for generating
a.out file
– They can be separately compiled to create
.o file
– all the .o files and .for files can be
finally compiled to create the final a.out file
• Libraries
– Many useful routines developed,
compiled and collected together
– These can be used in your programs
– When compiling your programs the object
codes of library routines are linked to get an executable
– Process of Linking
– intrinsic functions
General Picture of Compilation
Functions
• Functions are like subroutines
• Called from main program to do some
independent computations
• The result of computations not passed
via parameters
• Instead the function itself returns a
value
• Functions are called inside an
expression
• No separate call statement
Example
Real Function x_mul(x)
!to evaluate the value of x(1-x*x)/5
implicit none
integer, intent(IN):: x
x_mul = x*(1 - x**2)/5
end function
Observation
• The above is a function that computes
x(1-x2), when given x
• The function definition looks similar
to subroutines
• The value returned by the function is
given in the header (Real)
• Note the intent declaration
• There is an assignment that assigns a
variable with the same name as the function
Using a function
Program sum
real *, x, Sum
integer *, I
Sum = 0.0
do I = 1, 10
Sum = Sum + x_mul(I)
end
print *, Sum
end program
Side Effects
• Invocation of the function takes place
inside expression
• It is like evaluation, returns a value
which is used in the expression
• Always use parameters to be of INPUT
intent
• Otherwise, function invocation may
change the contents of actual parameters
• Then after an expression evaluation,
variables would change values
• This is called side effect
Functions and Subroutines
• Only one result would be returned by a
function
• Type of the result given in the
definition
• For multiple results, use subroutines
• Like subroutines, functions can call
other functions
• Functions can be internal or external
• Many useful functions in libraries
PGPLOT Library
• This is a standard library for drawing
graphs
• This library consists of various
subroutines and functions
• For drawing various kinds of graphs
with colours
• on a variety of medium like screen,
plotters, etc.
• you can use the functions and routines
of this library
• while compiling the name of the library
need to be mentioned
• A separate tutorial on use of PGPLOT
library
Save Attribute
•
Local
variables lose their values across different invocations
•
Sometimes
one would like to retain the values
•
Recording
of history
•
Save
attribute is used for this
•
Declare
in the procedure
–
type_name,
SAVE :: var_name
•
Or
initialize the local variable
An Example
Subroutine save_var(mark)
implicit none
integer :: passed = 0 ! This makes it
retain the value
!alternately use, integer,save:: passed = 0
if (mark > 35) then
passed = passed + 1
endif
if (mark < 0) then
print *, passed
endif
end subroutine