Integration

primate supports a variety of matrix-types of the box, including numpy ndarray’s, compressed sparse matrices (a lá SciPy), and LinearOperators—the latter enables the use of matrix free operators.

Outside of the natively types above, the basic requirements for any operator A to be used with e.g. the Lanczos method in primate are:

  1. A method A.matvec(input: ndarray) -> ndarray implementing v \mapsto Av
  2. An attribute A.shape -> tuple[int, int] giving the output/input dimensions of A

Here’s an example of a simple operator representing a Diagonal matrix, which inherits a .matvec() method by following the subclassing rules of SciPy’s LinearOperator:

import numpy as np 
from numpy.typing import ArrayLike
from scipy.sparse.linalg import LinearOperator 

class DiagonalOp(LinearOperator):
  diag: np.ndarray = None
  
  def __init__(self, d: ArrayLike, dtype = None):
    self.diag = np.array(d)
    self.shape = (len(d), len(d))
    self.dtype = np.dtype('float32') if dtype is None else dtype

  def _matvec(self, x: ArrayLike) -> np.ndarray:
    out = self.diag * np.ravel(x)
    return out.reshape(x.shape)

C++ usage

Similarly, to get started calling any matrix-free function provided by primate on the C++ side, such hutch or lanczos, simply pass any type with .shape() and .matvec() member functions:

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.

To read more about how semantics extend to the C++ side as well via C++20 concepts—see the C++ integration guide. If you’re using pybind11 and you want to extend primate’s Python API to work natively with linear operator implemented in C++, see the pybind11 integration guide.