 |
» |
|
|
 |
A module is a nonexecutable
program unit that contains—usually related—definitions
and declarations that may be accessed by use association. Typically,
modules are used for: Defining and declaring derived types Defining and declaring global data areas Creating subprogram libraries
The definitions within
a module are made accessible to other program units through use association.
The program unit that requires access to the module must have a USE statement at the head of its specification part,
and the statement must specify the name of the module. The following sections describe the module program unit and
the USE statement. The last section gives an example program
that uses a module.  |  |  |  |  | NOTE: Compiling
programs that contain modules requires care to ensure that each module
is compiled before the program unit that uses it. For detailed information
about compiling programs that contain modules, refer to the HP Fortran Programmer’s
Guide. |  |  |  |  |
Module
program unit |  |
The syntax of a
module program unit is: MODULE module-name [specification-part] [module-procedure-part] END [MODULE [module-name]] |
where: - module-name
is the name of the module. - specification-part
is zero or more
of the statements listed in Table 7-1 “Specification statements” with
the exception of the FORMAT statement. Also, specification-part must not contain statement function definitions or
automatic objects. (Specifying the SAVE attribute within a module is unnecessary in HP Fortran as
entities declared within a module retain their values by default.) Each entity declared
in specification-part and each of the procedure defined in module-procedure-part has either the PUBLIC or PRIVATE attribute. By default, all entities have the PUBLIC attribute and are thereby accessible by use association.
Entities having the PRIVATE attribute are accessible from within the module
only. The PUBLIC and PRIVATE attributes and statements are fully described
in Chapter 10, “HP Fortran Statements.” - module-procedure-part
is: CONTAINS module-procedure[module-procedure...] |
- module-procedure
is either a function
or subroutine. module-procedure has the same structure as an external function or
subroutine except that the END statement of module-procedure must include the SUBROUTINE or FUNCTION keyword, as appropriate; for an external procedure this
is optional. For information about external subroutines, see “External
procedures”. Note the following about module procedures: They have an
explicit interface within the using program unit. It is not necessary
to create an interface block for a module procedure. They can also contain internal procedures. They can be
passed as an actual argument.
The following
may be contained in a module and be made accessible by use association: USE statement |  |
The USE statement provides access to module entities within
the using program unit—that is, the
program unit in which the statement is specified. The USE statement specifies the name of the module that
the program unit wants to access. The information in the specified
module is made accessible to the program unit by use association.
The USE statement must appear at the head of the specification
part of a program unit. The USE statement can take either of two forms: USE module-name[, rename-list] USE module-name, ONLY : access-list
where: - rename-list
is a comma separated list of: local-name => module-entity-name - module-entity-name
is the name of a module entity. - local-name
is the name by which module-entity-name will be accessed within the using program unit. - access-list
is a comma-separated list of: [local-name =>] module-entity-name
As
shown in the syntax description, the USE statement provides a renaming feature that allows
module entities to be renamed within a using program unit. The association
between local-name and module-entity-name is conceptually similar to argument association:
the one name is an alias for the other, and the association between
the two is in effect only within the using program unit. The renaming feature
can be used to resolve name conflicts when more than one module contains
an entity with the same name. Consider a program unit that has access
by use association to two modules: mod_defs1 mod_defs2. The names of the entities in mod_defs1 are a, b, and c; and the names of the entities in mod_defs2 are b, c, and d. The following USE statements will avoid name conflicts within the
using program unit: USE mod_defs1 USE mod_defs2, b => local_b, c => local_c |
The ONLY clause provides an additional level of control
over access to module entities. As described in “Module
program unit”, the PRIVATE and PUBLIC attributes control access to module entities in
all using program units. The ONLY clause controls access within a specific program
unit. For example, consider a module named mod_defs that contains the entities ent_x, ent_y, and ent_z. If a program unit contains the following USE statement: USE mod_defs, ONLY : ent_x, entry += local_y |
it has access to ent_x and ent_y only. Furthermore, it must access ent_y by the name local_y. A program
unit may have more than one USE statement specifying the same module: If one of the USE statements is without the ONLY clause, then all module entities with the PUBLIC attribute are accessible. Furthermore, all local-names from the rename-lists and access-lists are interpreted as a single concatenated rename-list. If all of the USE statements have the ONLY clause, all of the access-lists are interpreted as a single concatenated access-list.
For more information, see “USE”. Program
example |  |
The following example
program consists of three files: The file main.f90 is the driver that has access to entities in two
modules—precision and linear_equation_solver—by use association. The modules are the
other two files. The purpose of precision is to communicate a kind type parameter to the
other program units in the program, for the sake of precision portability.
The second module—linear_equation_solver—contains three module procedures, the
first of which, solve_linear_equations, uses the other two; solve_linear_equations is itself invoked by the main program. Stated algebraically, the equations that main.f90 provides as input for solution are: 2x + 3y + 4z = 20 3x + 4y + 5z = 26 4x + 5y - 6z = -4
|
Example 7-11 main.f90 PROGRAM main ! use the two modules defined in precision.f90 and ! lin_eq_slv.f90 USE precision USE linear_equation_solver IMPLICIT NONE ! the matrix a contains the coefficients to solve; b holds ! the constants on the right-hand side of the equation; ! the solution goes in x REAL (adequate) :: a(3,3), b(3), x(3) INTEGER :: i, j ! set by solve_linear_equations to indicate whether or not ! a solution was possible LOGICAL :: error ! initialize the matrix DO i = 1,3 DO j = 1,3 a(i,j) = i+j END DO END DO a(3,3) = -a(3,3) ! initialize the vector of constants b = (/ 20, 26, -4 /) CALL solve_linear_equations (a, x, b, error) IF (error) THEN PRINT *, 'Cannot solve.' ELSE PRINT *, 'The solution:', x END IF END PROGRAM main |
Example 7-12 precision.f90 MODULE precision ! The named constant adequate is a kind number of a real ! representation with at least 10 digits of precision and 99 ! digits range that normally results in 64-bit arithmetic. ! This constant ensures the same level of precision ! regardless of whether the program ! of whether the program is compiled on a 32-bit or 64-bit ! single-precision machine. INTEGER, PARAMETER :: adequate = SELECTED_REAL_KIND(10,99) END MODULE precision |
Example 7-13 lin_eq_slv.f90  |
MODULE linear_equation_solver USE precision IMPLICIT NONE PRIVATE adequate ! to avoid a "double definition" of adequate ! in program units that also use precision ! forbid outside access to these two module procedures PRIVATE :: factor, back_substitution CONTAINS ! module procedures defined here SUBROUTINE solve_linear_equations (a, x, b, error) ! solve the system of linear equations ax = b; set error to ! true if the extents of a, x, and b are incompatible or ! a zero pivot is found REAL (adequate), DIMENSION (:, :), INTENT (IN) :: a REAL (adequate), DIMENSION (:), INTENT (OUT) :: x REAL (adequate), DIMENSION (:), INTENT (IN) :: b LOGICAL, INTENT (OUT) :: error REAL (adequate), DIMENSION (SIZE (b), SIZE (b) + 1) :: m INTEGER :: n n = SIZE (b) ! check for compatible extents error = SIZE(a, DIM=1) /= n .OR. SIZE(a, DIM=2) /= n & .OR. SIZE(x).LT. n IF (error) THEN x = 0.0 RETURN END IF ! append the right-hand side of the equation to m m (1:n, 1:n) = a m (1:n, n+1) = b ! factor m and perform forward substitution in the last ! column of m CALL factor (m, error) IF (error) THEN x = 0.0 RETURN END IF ! perform back substitution to obtain the solution CALL back_substitution (m, x) END SUBROUTINE solve_linear_equations SUBROUTINE factor (m, error) ! Factor m in place into a lower and upper triangular ! matrix using partial pivoting ! Set error to true if a pivot element is zero; Perform ! forward substitution with the lower triangle on the ! right-hand side m(:,n+1) REAL (adequate), DIMENSION (:, :), INTENT (INOUT) :: m LOGICAL, INTENT (OUT) :: error INTEGER, DIMENSION (1) :: max_loc REAL (adequate), DIMENSION (SIZE (m, DIM=2)) :: temp_row INTEGER :: n, k INTRINSIC MAXLOC, SIZE, SPREAD, ABS n = SIZE (m, DIM=1) triang_loop: DO k = 1, n max_loc = MAXLOC (ABS (m (k:n, k))) temp_row (k:n+1) = m (k, k:n+1) m (k, k:n+1) = m (k-1+max_loc(1), k:n+1) m (k-1+max_loc(1), k:n+1) = temp_row (k:n+1) IF (m (k, k) == 0) THEN error = .TRUE. EXIT triang_loop ELSE m (k, k:n+1) = m (k, k:n+1) / m (k, k) m (k+1:n, k+1:n+1) = m (k+1:n, k+1:n+1) - & SPREAD (m (k, k+1:n+1), 1, n-k) * & SPREAD (m (k+1:n, k), 2, n-k+1) END IF END DO triang_loop END SUBROUTINE factor SUBROUTINE back_substitution (m, x) ! Perform back substitution on the upper triangle to compute ! the solution REAL (adequate), DIMENSION (:, :), INTENT (IN) :: m REAL (adequate), DIMENSION (:), INTENT (OUT) :: x INTEGER :: n, k INTRINSIC SIZE, SUM n = SIZE (m, DIM=1) DO k = n, 1, -1 x (k) = m (k, n+1) - SUM (m (k, k+1:n) * x (k+1:n)) END DO END SUBROUTINE back_substitution END MODULE linear_equation_solver |
 |
Here are the command lines to compile and execute the program,
along with the output from a sample run: $ f90 precision.f90 lin_eq_slv.f90 main.f90 $ a.out The solution: 1.0 2.0 3.0 |
The order in
which the files appear on the f90 command line is significant: files that contain modules
must be compiled before files containing the program units that
use the modules. For more information about compiling programs that
use modules, see the HP Fortran Programmer’s
Guide
|