The main purpose of the class CwiseNullaryOp is to define procedural matrices such as constant or random matrices as returned by the Ones(), Zero(), Constant(), Identity() and Random() methods. Nevertheless, with some imagination it is possible to accomplish very sophisticated matrix manipulation with minimal efforts such that implementing new expression is rarely needed.
To explore these possibilities let us start with the circulant example of the implementing new expression topic. Let us recall that a circulant matrix is a matrix where each column is the same as the column to the left, except that it is cyclically shifted downwards. For example, here is a 4-by-4 circulant matrix:
A circulant matrix is uniquely determined by its first column. We wish to write a function makeCirculant
which, given the first column, returns an expression representing the circulant matrix.
For this exercise, the return type of makeCirculant
will be a CwiseNullaryOp that we need to instantiate with: 1 - a proper circulant_functor
storing the input vector and implementing the adequate coefficient accessor operator(i,j)
2 - a template instantiation of class Matrix conveying compile-time information such as the scalar type, sizes, and preferred storage layout.
Calling ArgType
the type of the input vector, we can construct the equivalent squared Matrix type as follows:
This little helper structure will help us to implement our makeCirculant
function as follows:
As usual, our function takes as argument a MatrixBase
(see this page for more details). Then, the CwiseNullaryOp object is constructed through the DenseBase::NullaryExpr static method with the adequate runtime sizes.
Then, we need to implement our circulant_functor
, which is a straightforward exercise:
We are now all set to try our new feature:
If all the fragments are combined, the following output is produced, showing that the program works as expected:
This implementation of makeCirculant
is much simpler than defining a new expression from scratch.
The goal here is to mimic MatLab's ability to index a matrix through two vectors of indices referencing the rows and columns to be picked respectively, like this:
To this end, let us first write a nullary-functor storing references to the input matrix and to the two arrays of indices, and implementing the required operator()(i,j)
:
Then, let's create an indexing(A,rows,cols)
function creating the nullary expression:
Finally, here is an example of how this function can be used:
This straightforward implementation is already quite powerful as the row or column index arrays can also be expressions to perform offsetting, modulo, striding, reverse, etc.
and the output is: