Go to the previous, next chapter.

Using FORTRAN Routines with PROFIL

In this section we describe how to use FORTRAN routines with PROFIL. FORTRAN double precision and integer types can be used without any modification. For single precision, a conversion is necessary for vector and matrix types, because PROFIL uses double precision for the REAL type internally. This can be changed in the configuration file. See section Basic Operations and Types, for details.

The conversion between single and double precision types is beyond the scope of this short documentation and because of this left out here. It is assumed that the reader is familiar with building and using own libraries.

The general steps to use FORTRAN library functions with PROFIL are:

  1. Convert all needed FORTRAN routines to C (e.g. using f2c, which is freely available via NetLib).

  2. Compile the converted C files with a modified f2c.h file which is available from the same source as PROFIL/BIAS.

  3. Build a library from the compiled files.

  4. Write the PROFIL interface routines to the compiled C routines.

  5. Use the PROFIL interface routines in your program and link the new library routines with your program.

Throughout this description we use the computation of the eigenvalues of a symmetric real matrix as an example (the FORTRAN routine is RSM from EISPACK). We assume that all FORTRAN routines belonging to RSM are converted to C and a library called libRSM.a has been built from this set of routines.

The parameter description of the FORTRAN RSM subroutine is given below (taken from the EISPACK rsm.f file).

      subroutine rsm(nm,n,a,w,m,z,fwork,iwork,ierr)
      integer n,nm,m,iwork(n),ierr
      integer k1,k2,k3,k4,k5,k6,k7
      double precision a(nm,n),w(n),z(nm,m),fwork(1)
c     this subroutine calls the recommended sequence of
c     subroutines from the eigensystem subroutine package (eispack)
c     to find all of the eigenvalues and some of the eigenvectors
c     of a real symmetric matrix.
c     on input
c        nm  must be set to the row dimension of the two-dimensional
c        array parameters as declared in the calling program
c        dimension statement.
c        n  is the order of the matrix  a.
c        a  contains the real symmetric matrix.
c        m  the eigenvectors corresponding to the first m eigenvalues
c           are to be computed.
c           if m = 0 then no eigenvectors are computed.
c           if m = n then all of the eigenvectors are computed.
c     on output
c        w  contains all n eigenvalues in ascending order.
c        z  contains the orthonormal eigenvectors associated with
c           the first m eigenvalues.
c        ierr  is an integer output variable set equal to an error
c           completion code described in the documentation for tqlrat,
c           imtqlv and tinvit.  the normal completion code is zero.
c        fwork  is a temporary storage array of dimension 8*n.
c        iwork  is an integer temporary storage array of dimension n.

This header is converted by f2c into the following C header, which can be used by PROFIL routines:

extern "C" {
  int rsm_(PINT nm, PINT n, PREAL a, PREAL w,
           PINT m, PREAL z, PREAL fwork,
           PINT iwork, PINT ierr);

The leading P of the types denotes a pointer to the appropriate type, because FORTRAN always uses reference parameters.

Assuming that we want to create a PROFIL subroutine which returns a vector containing the eigenvalues of its matrix argument, the header would be

VECTOR Eigenvalues (MATRIX & A)

To use the PROFIL vectors and matrices as FORTRAN subroutine parameters, the extension theElements must be appended with a separating dot to the vector or matrix name. Additionally, all vector and matrix types must be correctly sized before calling the converted FORTRAN routine. For the small example discussed here, the complete implementation of the subroutine Eigenvalues might look like:

VECTOR Eigenvalues (MATRIX & A)
// Computes and returns all eigenvalues of the symmetric matrix A
  INT nm = RowDimension (A);
  INT n = ColDimension (A);
  VECTOR e(n);
  VECTOR fwork(8 * n);
  INTEGER_VECTOR iwork(n);
  INT ierr, m = 0;

// No symmetry check is performed!! rsm_ (& nm, & n, A.theElements, e.theElements, & m, NULL, fwork.theElements, iwork.theElements, & ierr); if (ierr) Error ("Something is wrong in eigenvalue computation", ierr, ErrorHandler::SevereError); return e; }