Jump to content United States-English
HP.com Home Products and Services Support and Drivers Solutions How to Buy
» Contact HP
More options
HP.com home
HP Fortran Compiler for HP-UX: HP Fortran Programmer's Reference > Chapter 7 Program units and procedures

Modules

» 

Technical documentation

Complete book in PDF
» Feedback
Content starts here

 » Table of Contents

 » Glossary

 » Index

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

  • Defining operators

  • 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:

  • Declared variables

  • Named constants

  • Derived-type definitions

  • Procedure interfaces

  • Module procedures

  • Generic names

  • Namelist groups

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:

  • main.f90

  • precision.f90

  • lin_eq_slv.f90

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

Printable version
Privacy statement Using this site means you accept its terms Feedback to webmaster
© Hewlett-Packard Development Company, L.P.