Design of the solutions for LinBox v2.0
The design is very close to the existing one. In a nutshell:
- the matrix class is a templated argument. It meets the BlackBox concept.
- the implementations for DenseMatrix and SparseMatrix are done via template specialization
- the implementation for BlackBox matrices is the default (unspecialized) template implementation.
- the Method class is a template argument. Methods provide:
- a means to choose an algorithm at compile time according to the Method class.
- a means to specify matrix properties (eg. symmetry) in the Method object, allowing for algorithmic refinement at run time.
- a means for the solution to return side conditions of the computation (eg. inconsistency) by data stored in the Method object.
Using determinant as an example, the user must be able to call
det (d, A);
det (d, A, hybrid);
det (d, A, elimination);
det (d, A, blackbox);
det (d, A, otherMethod);
for A being of any BlackBox class including SparseMatrix or DenseMatrix, over any compatible domain. The difference between using no method and using method hybrid is that the user can put information in the method and get information back. When information back is essential the no-method call will throw an exception.
When elimination method is used with a generic blackbox, generally the equivalent DenseMatrix will be constructed and the elimination done on that. When blackbox method is used with a DenseMatrix or SparseMatrix an algorithm that is oblivious to the matrix structure beyond the BlackBox concept is used.
A given solution may support any number of other, more specific methods.
Trace is an interesting case. The pure blackbox approach - n matrix vector products for an n by n blackbox - is horribly inefficient. Almost every blackbox class can provide a better way to compute the trace, not just the SparseMatrix and DenseMatrix. In this case matrix traits can be used to get the solution using a trace function provided in the matrix class.
All solutions must at least provide these following functions
/**
* Call with a method
*/
template <class Matrix, class Method >
typename Matrix::Element&
det (typename Matrix::Element& d, const Matrix& A, const Method& M);
/**
* Simplest call, method oblivious
*/
template <class Matrix>
typename Matrix::Element&
det (typename Matrix::Element& d, const Matrix& A);
/**
* General spec. for internal usage only
*/
template <class Matrix, class Method, class DomainCategory>
typename Matrix::Element&
det (typename Matrix::Element& d,
const Matrix& A,
const DomainCategory& DomCat,
const Method& M);
And then the different instantiations, to specialize the method, the domain category, ...
/**
* Now the specific implementations have to appear here
* There should be at least an implementation for the domain categories
* RingDomainCategory::ModularTag and RingDomainCategory::IntegerTag
* and for DenseMatrix, SparseMatrix, BlackBox
*/
/**
* Call with a method
*/
template <class Matrix, class Method >
typename Matrix::Element&
det (typename Matrix::Element& d,
const Matrix& A,
const Method& M){
return det (d,
A,
DomainTraits<typename Matrix::Field>::category (),
typename MethodTraits<Matrix>::Method (M))
/**
* Simplest call, method oblivious
*/
template <class Matrix>
typename Matrix::Element&
det (typename Matrix::Element& d,
const Matrix& A){
return det (d,
A,
DomainTraits<typename Matrix::Field>::category (),
typename MethodTraits<Matrix>::Method ())
}
/**
* Determinant of a DenseMatrix, over a finite ring
*/
template <class Domain>
det (typename Domain::Element& d,
const DenseMatrix<Domain>& A,
const RingDomainCategories::ModularTag& DomCat,
const Method::Wiedemann& M){
// Call to code in the algorithms directory here,
// for det with DenseMatrix over a modular ring
// using Wiedemann's algorithm
...;
}
/**
* Determinant of a SparseMatrix, over matrices can be provided
* by specialization of both the Method and the matrix.
*/
template <class Domain>
det (typename Domain::Element& d,
const SparseMatrix<Domain> A,
const RingCategories::ModularTag& DomCat,
const Method::SparseElimination& M){
...;
}
- JGD: Move solutions "General spec internal usage" to function objects (instead of simple functions) ?
--> Enable to design generic codes e.g. for Chinese remaindering something like:
det( d, A, IntegerTag, M ) { GeneralCRT( det<Modular<> >, prime, ...) ; }
