Now let us have a look at the file that contains module euler. Figure 2.11 lists the content of file euler.f90, on which I have saved the skeleton of the module.
This is only a skeleton, because functions small_gamma,
big_gamma, and gamma are not fully defined.
They
are not even correctly defined. But this skeleton covers all
mechanics of the program. It can be compiled and linked with
the main program, and the main program can be run - just to
ensure that the mechanics are correct.
Then we can worry about defining functions
,
and
.
The module program looks much like the main program,
but it begins with the word module. In the preamble
you can define any global variables or constants that
need to be accessed either by the module's functions or by
programs calling the module. Here we only define the
constant long.
The statement contains
separates the first part
of a module,
that is allowed to contain specification statements only,
from a part that contains definitions of module subprograms.
This statement can be used in a main program too, in which case
it would separate specification and procedural
parts of the main program from its subprograms.
Following contains we have definitions of four functions
that correspond to Q(a, x),
,
,
and
.
Of these only the first, Q(a, x) is correctly
implemented, whereas the remaining three functions simply return
a.
Observe that the dummy parameters, a, and x, are declared to have their
intent(in)This tells Fortran compiler that they are not meant to be changed by the subprogram. Consequently the compiler may implement some optimisations, and it can also check the subprogram for any inadvertent attempt to change the values of the
intent(in) parameters.
The body of the module ends with the statement
end module euler
Since all mechanics of the module should now be fully functional, I can demonstrate to you how it all works. In order to compile and link the whole program, the module must be compiled first:
gustav@blanc:../src 14:33:08 !546 $ f90 -c euler.f90 gustav@blanc:../src 14:33:14 !547 $ ls -FCs euler* 3 euler.M 1 euler.f90 2 euler.o gustav@blanc:../src 14:33:18 !548 $Under Solaris 2.6 the compilation creates two files:
euler.M and euler.o.
The first file contains specifications of all public objects
defined in the module. This is a data file, but you can get a glimpse
of what it contains if you run strings on it:gustav@blanc:../src 14:35:01 !552 $ strings euler.M EULER SELECTED_REAL_KIND EULER LONG _SELECTED_REAL_KIND_ @STACK @DARGS GOODNESS GOODNESS.in.EULER @STACK @DARGS SMALL_GAMMA SMALL_GAMMA.in.EULER @STACK @DARGS BIG_GAMMA BIG_GAMMA.in.EULER @STACK @DARGS GAMMA GAMMA.in.EULER gustav@blanc:../src 14:35:55 !553 $This is the file that is looked up by the Solaris Fortran compiler when it encounters the statement
use euler in the main program. File euler.o
contains a compiled code that corresponds to the module's subprograms.
That is the file that we will have to link our program with.
In summary, euler.M is used during compilation of chi.f90, and euler.o is used when linking chi.
Under IRIX, the module interface file generated by the compiler
will be called EULER.kmo. This file is human readable,
and this is what it looks like:
gustav@barruc:../src 15:40:47 !501 $ cat EULER.kmo
internalinterface
function GOODNESS ( A, X )
intent ( in ) A, X
doubleprecision A, X
doubleprecision GOODNESS
end function GOODNESS
function SMALL_GAMMA ( A, X )
intent ( in ) A, X
doubleprecision A, X
doubleprecision SMALL_GAMMA
end function SMALL_GAMMA
function BIG_GAMMA ( A, X )
intent ( in ) A, X
doubleprecision A, X
doubleprecision BIG_GAMMA
end function BIG_GAMMA
function GAMMA ( A )
intent ( in ) A
doubleprecision A
doubleprecision GAMMA
end function GAMMA
end interface
integer LONG
parameter (LONG = selected_real_kind (9, 99))
intrinsic SELECTED_REAL_KIND
gustav@barruc:../src 15:40:54 !502 $
Program chi is now compiled, linked, and run as follows:
gustav@blanc:../src 14:39:26 !558 $ f90 -c chi.f90 gustav@blanc:../src 14:39:33 !559 $ f90 -o chi chi.o euler.o gustav@blanc:../src 14:40:21 !560 $ ./chi < chi.dat a = 1.808 +- 0.088 b = 0.515 +- 0.014 chi^2 = 15.310 Q = 1.000 STOP 0 gustav@blanc:../src 14:40:25 !561 $
Now observe what is going to happen if I replace
q = goodness( (n - 2.0_long) / 2.0_long, chi_2 / 2.0_long )with
q = goodness( (n - 2.0_long) / 2.0_long )in chi.f90, i.e., if I call function goodness with one argument instead of two: