! File typical.1.f90
! The suffix .f90 permits the use of the new free source form available in
! Fortran 90.
! A module is a new feature in Fortran 90. Modules are primarily used to
! declare data, subroutines, and functions that are accessible in more than
! one program unit. Modules are a safe alternative to common in Fortran 77,
! and provide much more functionality by including more than just data.
! The data, subroutine, and function names in a module are made available
! by using the module in the program unit using the USE statement together
! with the module name.
! Case is not significant in Fortran 90.
module TypicalModule
integer, parameter :: N = 4 ! Declare an integer constant, N.
integer, parameter :: M = 50 ! Declare an integer constant, M.
private M ! Make the integer constant visible only within this module.
! Define a derived type called rational that contains two integer
! components, n and d. Derived types are similar to records in Pascal
! or structures in C. Individual components are accessed via the ``%''
! operator (see the rationalAdd function below).
type rational
integer n, d
end type rational
! Every subroutine or function has an interface which indicates the name,
! the arguments, their types, attributes, and the type and attributes of
! the function (for a function).
! There are two types of interfaces in Fortran 90, implicit interfaces
! and explicit interfaces. Implicit interfaces are used in Fortran 77
! external procedures and assume that a procedure call is correct in the
! type and number of arguments passed. Explicit interfaces, however, have
! the advantage that type-checking of actual and dummy arguments can be
! performed for procedure calls. Incorrect calls or invocations are
! detected by the compiler.
! Interfaces of subroutines and functions within a module are always
! explicit. However, an interface block is needed to define a generic
! procedure name or operator and the set of procedures to which the name
! applies. The following interface block extends the binary ``+''
! operator. Now, the function rationalAdd can be invoked using the
! binary operator ``+'' on two objects of type( rational ).
interface operator (+)
module procedure rationalAdd
end interface
private gcd ! Use the gcd function internal to this module only.
! The contains statement indicates the presence of one or more internal
! subprograms that are included in the module and is necessary to
! separate the specification statements of the module from the
! subprogram definitions.
contains
function rationalAdd( left, right )
! To declare a variable to be of some derived type, use the type
! statement with the derived type's name in parenthesis.
type( rational ) rationalAdd
! As in Fortran 77, parameter passing is by reference.
! It may be necessary for the compiler to generate temporaries in
! some cases. However, changes to these temporaries affect the actual
! argument. Fortran 90 provides the intent attribute to further
! specify and document a variable's use in the program. Possible
! intent specifications are in, out, and inout. Variables violating
! their intent are caught by the compiler.
type( rational ), intent(in) :: left, right
integer k, m1, m2
type( rational ) sum
k = gcd( left%d, right%d )
m1 = left%d / k
m2 = right%d / k
! To assign a value to a variable of a derived type such as sum, use
! a structure constructor as indicated below. A structure constructor
! consists of the derived type name together with the value to be
! assigned to each component of the derived type, in the order
! declared in the specification of the derived type. (A derived type
! may also be assigned by assigning values to its individual
! components.)
sum = rational( left%n * m2 + right%n * m1, left%d * m2 )
k = gcd( sum%n, sum%d )
rationalAdd = rational( sum%n / k, sum%d / k ) ! Reduce the rational.
end function rationalAdd
! Recursion is now permissible in Fortran 90. The function gcd is
! declared recursively below.
! If a function calls itself, either directly or indirectly, the
! keyword recursive must appear in the function statement. Recursive
! functions must also declare a result clause to be used rather than the
! function name. This requirement is to avoid ambiguity with
! array-valued functions that are directly recursive. The result
! variable is used to hold the function result for each function
! invocation; the function name is used to invoke the function itself.
recursive function gcd( a, b ) result( divisor )
! Note that the function itself is not declared when the result
! variable is present. The type of the function is the type of
! the result variable. Thus, only the result variable may be
! declared.
integer divisor
integer, intent(in) :: a, b
integer m, n
! Multiple statements may be written on a single source line
! provided they are delimited with semicolons.
m = abs(a); n = abs(b)
if ( m > n ) call swap( m, n ) ! Insure that m <= n.
! When the function invokes itself recursively, the result variable
! should be used to store the result of the function. The function
! name is used to invoke the function. Thus, the function name should
! not appear on the left-hand side of an assignment statement.
if ( m == 0 ) then
divisor = n
else
divisor = gcd( mod( n, m ), m )
end if
! Unlike internal subprograms, module procedures, such as gcd, may
! have internal subprograms defined within them (to one level only).
! As with module procedures, internal subprograms also have an
! explicit interface. Thus, the swap subroutine is not declared in
! the gcd function above---its interface is explicit.
contains
! The swap subroutine is internal to gcd and is not visible
! elsewhere, not even in this module.
subroutine swap( x, y )
integer, intent(inout) :: x, y
integer tmp
tmp = x; x = y; y = tmp
end subroutine swap
end function gcd
end module TypicalModule
! The above module can be in a different source file than the program and
! be compiled separately. The explicit interfaces of the module procedures
! guarantee that the compiler will check the actual and dummy arguments, in
! both type and number, for each module procedure called in the program.
program Typical
! A module is accessed via the use statement. With the use statement
! below, all public names (names not declared private in the module) are
! available for use in the program. Use statements must immediately
! follow the program statement. A program may use an unlimited
! number of modules.
use TypicalModule
! Note that a variable may be initialized at the time of declaration.
type( rational ) :: a = rational( 1, 2 ), b = rational( 3, 4 ), c
! The derived type rational and its associated function, ``+'', may
! now be used between a and b.
c = a + b ! This statement is equivalent to c = rationalAdd( a, b ).
! Input two rational numbers and output their sum.
print *, 'Enter two rational numbers.'
print *
! Nonadvancing output is possible using the advance specifier in the
! write statement. This permits multiple write statements to output
! a continuing line of output.
write( *, fmt = "(a)", advance = "no" ) 'Numerator of a : '
read *, a%n
write( *, fmt = "(a)", advance = "no" ) 'Denominator of a : '
read *, a%d
write( *, fmt = "(a)", advance = "no" ) 'Numerator of b : '
read *, b%n
write( *, fmt = "(a)", advance = "no" ) 'Denominator of b : '
read *, b%d
c = a + b
print *
print *, a%n, '/', a%d, '+', b%n, '/', b%d, '=', c%n, '/', c%d
end program Typical