next up previous index
Next: The Euler Gamma Function: Up: The Goodness of Fit Previous: More about Fortran

Defining a Module and its Subprograms

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.


  
Figure 2.11: The skeleton of module euler
\begin{figure}
\begin{footnotesize}
\begin{tex2html_preform}\begin{verbatim}modu...
...d module euler\end{verbatim}\end{tex2html_preform}\end{footnotesize}\end{figure}

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 $\gamma (a, x)$, $\Gamma (a,x)$ and $\Gamma (a)$.

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), $\gamma (a, x)$, $\Gamma (a,x)$, and $\Gamma (a)$. 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:
\begin{figure}
\begin{footnotesize}
\begin{tex2html_preform}\begin{verbatim}gust...
...4:42:25 !563 $\end{verbatim}\end{tex2html_preform}\end{footnotesize}\end{figure}

The compiler, having found about the definition of function goodness from euler.M, immediately recognises that the function has been called with an incorrect number of arguments and flags an error.


next up previous index
Next: The Euler Gamma Function: Up: The Goodness of Fit Previous: More about Fortran
Zdzislaw Meglicki
2001-02-26