[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |

The strategy adopted for converting and wrapping the fortran files is a little involved. Some routines are simple to do, others very tricky. The general procedure is as follows. These steps are elaborated upon in the example below.

[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |

- Use GAMS to find the module name, in SLATEC if possible, although CMLIB and TOMS routines are also public domain and good.
- Convert the fortran to C using f2c
- Add the routine to the Imakefile in the netlib library.
- Encapsulate the routine in a class in vnl, after determining a suitable interface.
- Read the module documentation and determine the calling sequence.
- In the calling method, create all necessary workspace arrays and temporary variables that the call requires, call the external routine, and convert the results into the classes that VXL expects.
- After the call, interpret the error code, and handle accordingly.

[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |

There are a few potential sources of difficulty, mostly in item 5, but in general I find that gritting one's teeth and guessing is a surprisingly good strategy. The main points to remember are:

- All scalar variables are passed by reference. This means that you need to store all constants in variables and pass their addresses or declare the routines as accepting references. I do the latter for input variables, and the former for outputs.
- Fortran arrays start from 1 rather than 0. This is actually a non-problem, as f2c generates code which interfaces zero-based to one-based arrays using the Numerical Recipes trick of decrementing the pointer, but is mentioned here for the benefit of fortran programmers.
- Fortran arrays are stored column-wise rather than row-wise. Class
`vnl_fortran_copy`

provides an easy and efficient way to transpose matrices before calling.

In addition to these fortran specifics, it is important to be aware of the sorts of design patterns seen in numerical code. Many routines are coded for maximum generality and efficiency, which can make reading the descriptions heavy going. Common conventions are:

- An array is passed with three dimensions: number of rows in the physical array, number of rows to use for computation and number of columns. This allows the routines to be used on any submatrix of a larger matrix.
- Output results overwrite the input matrix.
- Output results are stored in some compact form, which must be decoded before use. Note however that in many cases routines are supplied to perform further computations using the encoded representation for time and space efficiency. The new QR class will demonstrate how to take advantage of this.
- The results of pivoting are generally returned in vectors of
integers (say
`ipvt`

), where`ipvt[i]`

is the position to which row/column`i`

has been moved. These permutations which must be applied to the results in order to complete the process.

[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |

Given the need for an algorithm that is not yet included in the vnl package, say a routine to compute the QR decomposition, your first stop is the GAMS decision tree. Class "D" is Linear Algebra, and class "D5" is QR decomposition. The SLATEC implementation is called DQRDC (Double precision QR DeComposition). Download the source, or obtain it from a local SLATEC distribution. Convert it to a C source file and a prototype file using

f2c -P dqrdc.f |

and from the prototype file `dqrdc.P`

we find that the function
prototype is

int dqrdc_(doublereal *x, integer *ldx, integer *n, integer *p, doublereal *qraux, integer *jpvt, doublereal *work, integer *job); |

At this point, the header of the fortran file `dqrdc.f`

is examined in
order to determine the meaning of the parameters. Considering parameter
`X`

, we find

X DOUBLE PRECISION(LDX,P), where LDX .GE. N. X contains the matrix whose decomposition is to be computed. |

This means that X is a LDX row by P column matrix, and that we require a
decomposition of the first N rows. This is a common convention in fortran
programs which allows computation on subblocks of matrices. In general, we
will assume that we wish to work on the full matrix, and therefore that LDX
= N. To create the required transformed copy of the matrix, use class
`vnl_fortran_copy`

:

vnl_fortran_copy Xtranspose(X); |

Now, the function may be called as

int n = X.rows(); int p = X.columns(); vnl_vector<int> jpvt(p); jpvt.fill(0); // Mark all columns as pivotable vnl_vector<double> work(p); int do_pivoting = 1; vnl_vector<double> qraux(p); dqrdc_(Xtranspose, &n, &n, &p, qraux.data_block(), jpvt.data_block(), w.data_block(), &do_pivoting); |

[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |

This document was generated on *May, 1 2013* using *texi2html 1.76*.