Module
and Data Sharing
Programming in the Large
•
Software, in general, is large having
multiple units
•
Multiple units designed and developed
independently
•
But these units executed together to
achieve some common goal
•
Units share data and need to
communicate with one another
•
Large software require mechanisms for
designing and developing multiple units
•
Flexible and powerful mechanism for
Communication or sharing of data essential
Parameters and Global
Variables
•
Fortran provides two means of
communication
•
Parameters: Subroutines and main
programs can share data via parameters
•
Global Variables: Internal routines and
functions can share the variable in the main program
•
Both are restrictive
–
Too many parameters
–
All routines in the same file
•
A more general mechanism desirable for
programming in the large
• Modules
is the Fortran Solution for this
Module definition
•
Here
is an example module definition
module example
implicit none
save
! guarantees saving all data values declared
integer, parameter:: pi = 3.141592
real:: x, y, z
real, dimension(100,100)::
satellite_data
end module example
Module use
Program
using_example
use example ! appears before all other
statement
implicit none
integer:: i, j
do i = 1, 100
do j = 1, 100
satellite_data(i, j) = pi * i + j
end do
end do
call test_routine
end
program
Module use in procedures
subroutine
test_routine
use example ! like in the program
implicit none
..
satellite_data(i, j) = ...
...
end
subroutine
Data Sharing using
modules
•
Data declared in different modules can
be shared among main program and subroutines and functions
•
Variables can be assigned and updated
by all the units
•
Values are retained with SAVE attribute
•
a simple and efficient mechanism for
sharing large amount of data
•
No need for passing large amount of
data via parameters
• Modules
can be separately compiled and linked later
Procedures can be shared
too
Module example1
implicit none
-- shared data ---
contains
subroutine ex1(x, y, z)
implicit none
-- parameter and local
variable declarations
-- body
end subroutine
-- other procedure or function
definition
end module example1
Using the procedures
•
Main program and any procedure that
uses the above module can call ex1 and other routines declared
•
Advantage over conventional method
–
increased safety
•
Modules with procedures create (when
compiled) EXPLICIT INTERFACES
•
compile with -c option creates .vo file
containing the interface
•
Explicit interface for a procedure
contains
no. , type, intent of each argument
•
When the calling program compiled, the
compiler checks whether the calls match the interfaces and flag errors, if any
•
When procedures not in a module
compiled only an implicit interface is created
– No
details about the procedures
–
compiler can then miss errors leading
to strange errors at run-time
High Level Data Types
•
Another use of including procedures in
modules is extensibility
•
New data types can be created by the
users
•
Suppose we want to create a new data
type Polynomails
–
Data Values: all possible ploynomials
of, say degree 4
–
Operations: Addition, Subtraction, multiplication by a constant, creation,
coefficient extraction
• Modules
useful for defining such a data type
Polynomial data type
Module
polynomial
implicit none
type:: poly
real:: x
real:: y
real:: z
real:: w
end type
contains
subroutine create(poly_result, x1, y1,
z1, w1)
implicit none
type (poly), intent(out)::
poly_result
real:: x1, y1, z1, w1
poly_result%x = x1
poly_result%y = y1
poly_result%z = z1
poly_result%w = w1
end subroutine
Polynomial Module
continued
subroutine
add(poly_result, poly1, poly2)
implicit none
type (poly), intent(out)::
poly_result
type (poly), intent(in):: poly1,
poly2
poly_result%x = poly1%x + poly2%x
poly_result%y = poly1%y + poly2%y
poly_result%z = poly1%z + poly2%z
poly_result%w = poly1%w + poly2%w
end
subroutine
subroutine multiply(poly_result, poly1, a)
implicit none
type (poly), intent(out)::
poly_result
type (poly), intent(in):: poly1
real, intent(in):: a
poly_result%x = a* poly1%x
poly_result%y = a* poly1%y
poly_result%z = a* poly1%z
poly_result%w = a* poly1%w
end
subroutine
The
main program
Program
poly_main
use
polynomial
implicit none
type(poly):: a, b, c, d, e
real:: a1, a2, a3, a4
real:: b1, b2, b3, b4
print *, "type the coefficients of a"
read *, a1, a2, a3, a4
print *, "type the coefficients of b"
read *, b1, b2, b3, b4
call create(a, a1, a2, a3, a4)
call create(b, b1, b2, b3, b4)
call add(c, a, b)
call multiply(d, a, a1)
call multiply(e, b, b1)
print *, c%x, c%y, c%z, c%w
print *, d%x, d%y, d%z, d%w
end
program
A Problem
•
Units using a module can access any
entities declared in the module
•
For example, the main program above
accesses the x,y,z,w components to print the polynomial coefficients
•
But this is undesirable
•
Loss of Abstraction:
– Polynomial
module provides an abstract data type of polynomails
– The
operation like c%x is meaningless at the level of polynomials
– It
is like accessing 5th bit of an integer variable
•
Not robust under change of
representation
– Structures
are internal data structures to represent polynomials
– Suppose
tomorrow we choose to use arrays for representing polynomials
–
then the main program would not work
The solution
• There
is a need for an abstract routine that returns any coefficient of a polynomial
• But
that is not enough - main program can even then access the internal
representation
• There
is a need for a mechanism to restrict the access of module components
• Components
can be declared to be public or private
• For
example, the above problem disappears if we declare
type:: poly
private
real:: x
real:: y
real:: z
real:: w
end type
• Then
any reference to the components like c%x, d%z is illegal
•
Separate routines needed for printing
coefficients
Public and Private Components
•
In general, any component, data or
routines can be declared public or private
•
The declarations are:
private::
list of private items
public::
list of public items
•
A declaration private inside a module (after implicit none)
–
declares all items to be private
•
Default: all items are public
•
Alternate declarations is:
integer,
public:: x, y, z
real, private:: a, b, c
Assumed Shape arrays
•
Array
parameters in procedures
–
usually
the shape of array is explicitly given
–
Example: real, dimension(n,m):: arr1
where
n,m are also arguments
•
If
procedures are declared in a module then no need for specifying n, m
•
They
can be automatically found using intrinsic functions
–
LBOUND(arr1,i):
lower bound in ith dimesion
(this will be 1)
–
UBOUND(arr1,j):
upper bound in the jth dimension
•
Shape
and size can be inferred using these functions in called program
•
Actual
bounds can not however be inferred
– use explicit shape
array if required