General size square matrices are handled in a subtly different way to their fixed-size equivalents. For fixed size symmetric and triangular matrices, there are specific functions dealing with each type of square matrix, currently the two types, symmetric and lower triangular. A fixed size square matrix does not ``know'' what type of matrix it is. The type field in this case is an inessential field of the matrix, and is indeed #ifdef'd out when Gandalf is compiled with NDEBUG set. The only reason for using the same structure for both symmetric and lower triangular matrices is to allow the in-place operations that convert a symmetric matrix to a triangular matrix or vice versa. This arrangement is optimal for speed, because no type checking needs to be done at run time.
In contrast, the general size square matrix structure has a type field that is meaningful as the current matrix type. Many Gandalf functions are written for general square matrices. This simplifies the programming interface, in that one function can be used to implement an operation (e.g. square matrix add) for every type of square matrix, at the expense of some loss of speed, since the general function has to call different subroutines depending on the type of matrix. The overhead in implementing this arrangement is reduced to the minimum by including the routines to implement each operation for a given matrix type in the matrix structure itself. This object-oriented design feature is hidden from the programmer through the use of macros, so the package appears to the programmer as a normal set of functions.
Another difference between fixed and general vectors and matrices is that whereas in general fixed size vectors & matrices should be declared as structures, avoiding the need for dynamic allocation, general size vectors & matrices require dynamic allocation of their internal data. There is still an advantage in declaring structures rather than structure pointers, in that with pointer variables you require a call to malloc() to create the structure they point to. Gandalf lets the programmer decide which style to use. In the following description examples of both styles are presented.
Once again, both double precision and single precision routines are available, and once again a parallel set of header files, structures and functions is provided. We shall concentrate on the double precision package, and the equivalent structure and function name conversions for single precision are given in Section 3.2.3.
Most of the routines return a pointer to the matrix/vector result structure. NULL is returned on failure, and the Gandalf error handler is invoked. This is reiterated in the text below, and exceptions are noted.