C++ Integration
To get started calling any matrix-free function provided by primate, such sl_trace or lanczos, simply pass any type with a .shape() and .matvec() member functions defined like so:
class LinOp {
int nrow, ncol;
LinOp(int nr, int nc) : nrow(nr), ncol(nc) {}
void matvec(const float* input, float* output) const {
... // implementation details
}
void shape() const { return std::make_pair(nrow, ncol); }
}It’s up to you to ensure shape() yields the correct size; primate will supply vectors to input of size .shape().second (number of columns) and guarantees the pointer to the output will be at least shape().first (number of rows), no more.
The LinearOperator concept
primate’s generic API is enabled through C++20 concepts. Thus, the more exact statement is that any type respecting the LinearOperator concept shown below can be passed:
using FP = std::floating_point;
template < typename T, FP float_t = typename T::value_type >
concept LinearOperator = requires(T A, const float_t* v, float_t* o) {
{ A.matvec(v, o) }; // o = A v
{ A.shape() } -> std::convertible_to< std::pair< size_t, size_t > >;
};An instance A of type T is said to support the LinearOperator concept if it has:
- A method Av \mapsto o, with signature
A.matvec(const float_t* v, float_t* o) - A method yielding (\mathrm{card}(o), \mathrm{card}(v)), with signature
A.shape() -> pair< ... >
shape() should yield a pair (n,m) representing the sizes of the output and input vectors, respectively. This corresponds to the number of rows and columns in the matrix setting.
Other Concepts
Depending on the problem at hand, the supplied operator may need to meet other constraints. Here’s a short list additional operator concepts:
| Concept | Supports | Signature | Requires |
|---|---|---|---|
LinearOperator |
A v \mapsto o | A.matvec(v, o) |
NA |
AdjointOperator |
A^T v \mapsto o | A.rmatvec(v, o) |
LinearOperator |
AdditiveOperator |
o \gets o + \alpha Av | A.matvec_add(v, alpha, o) |
LinearOperator |
AffineOperator |
Sets t s.t. A + tB | A.set_parameter(t) |
LinearOperator |
Respecting these constraints is opt-in: if your operator is symmetric and you only need access to the Lanczos method, then any satisfying the LinearOperator concept is sufficient.