4 Structure
4.1 Design principles
High level principles
- Lisplab will be a homogeneous platform for mathematics.
- Lisplab is free software.
- User applications should need to stay only in Common Lisp.
(There should be no need
for optimized math in FFIs or special languages like Maxima)
- Lisplab will steal as much code as possible from as many as possible.
General design principles
- Every common mathematical operator and function
is represented by a CLOS generic function.
- Modular structure (Inspired by GSL).
- Trust the Lisp virtual machine (Avoid use of FFIs and destructive functions).
- Avoid mathematical algorithms in macros.
- Error checks is primarily caller's responsibility.
Design principles for the matrix code
- Layered structure where dependencies are
primarily to the layer below – not vertical within the layer.
4.2 Package structure
So far, there is only one main package, called, you might guess it:
lisplab. Except from that there are only a few special packages
for generated code and FFIs: Slatec, Blas, and FFTW. For test
code an applications you have the package lisplab-user.
4.3 The four levels, 0 – 3.
The Lisplab matrix and linear algebra code
has a layered structure with four levels, 0 – 3,
where
- Level 0 is matrix independent and contains
generic functions for mathematics.
In this level only specialization for numbers and non-matrix objects.
- Level 1 defines matrices and implements
mref
, vref
,cols
, rows
, size
and make-matrix-instance
.
- Level 2 Implements level 0 for matrices and
defines core functionality related to matrices such as
matrix constructors
dnew
, dcol
, etc.
and other matrix helper functions, such as
mmax
, mmin
, circ-shift
, etc.
Optimizations are mainly in level 2.
- Level 3 is everything else that uses matrices,
including linear algebra, FFTs, solvers, etc.
The levels are unequal in size: level 0 is potentially large,
level 1 is small, level 2 and 3 are large.
The intention with the structure are the following
- To minimize the work needed to add new matrices implementations.
Actually, you need only to implement level 1,
provided you inherit from matrix base. Otherwise you need also
to implement level 2.
- To encourage code reuse. For example, if you add
a new type to the dotted algebra, such as polynomials, symbolic
expressions, or arbitrary precision floats, you can immediately
perform matrix operations on them without write one single extra line
of code.
- To manage optimizations and special implementations by
overloading for specialized matrix types, mainly at level 2,
but also at level 3.
- To make foreign libraries available in Common Lisp.
- To create a closed, constant and extensible system of operations.
The filenames often also denote the levels. If a filename does not
denote the level, it is most probably level 3, or outside the level system
(non matrix code).
4.4 Matrix class hierarchy
All matrices are subclasses of matrix-base
, and as
far as possible the generic functions specialize
on one or many of its subclasses.
The matrix class hierarchy has three independent
lines of inheritance
- On structure
- On element type
- On implementation
The structure is inspired by the stream example in
Object-Oriented Programming in Common Lisp, by Sonya E. Keene.
4.4.1 The structure
The structure tells what kind of symmetries or other
special properties the matrix has.
Two matrix classes
matrix-structure-general
, where the matrix
has no known symmetries.
matrix-structure-diagonal
, where only
diagonal elements are non-zero.
- Other types to come.
4.4.2 The element type
The element type classes has no other purpose than to be
represents a Common Lisp types.
matrix-element-base
, represents t
matrix-element-double-float
, represents double-float
matrix-element-complex-double-float
, represents complex double-float
4.4.3 The implementation
Since Lisplab has many competing implementation of the same
generic functions, the implementation class structure tells which
one too choose. There are currently four classes in a straight
line of inheritance
matrix-implementation-base
matrix-implementation-lisp
, use native Common Lisp if possible.
matrix-implementation-blas
, use foreign libraries if possible.
This standard method dispatch ensures foreign library methods
are chosen before native lisp. It is the responsibility of the
methods to call next method if the library is not loaded.