87 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
namespace Eigen {
 | 
						|
 | 
						|
/** \page TopicCustomizing_NullaryExpr Matrix manipulation via nullary-expressions
 | 
						|
 | 
						|
 | 
						|
The main purpose of the class CwiseNullaryOp is to define \em 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 \ref TopicNewExpressionType "implementing new expression" is rarely needed.
 | 
						|
 | 
						|
\section NullaryExpr_Circulant Example 1: circulant matrix
 | 
						|
 | 
						|
To explore these possibilities let us start with the  \em circulant example of the \ref TopicNewExpressionType "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:
 | 
						|
\f[ \begin{bmatrix}
 | 
						|
    1 & 8 & 4 & 2 \\
 | 
						|
    2 & 1 & 8 & 4 \\
 | 
						|
    4 & 2 & 1 & 8 \\
 | 
						|
    8 & 4 & 2 & 1
 | 
						|
\end{bmatrix} \f]
 | 
						|
A circulant matrix is uniquely determined by its first column. We wish
 | 
						|
to write a function \c makeCirculant which, given the first column,
 | 
						|
returns an expression representing the circulant matrix.
 | 
						|
 | 
						|
For this exercise, the return type of \c makeCirculant will be a CwiseNullaryOp that we need to instantiate with:
 | 
						|
1 - a proper \c circulant_functor storing the input vector and implementing the adequate coefficient accessor \c 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 \c ArgType the type of the input vector, we can construct the equivalent squared Matrix type as follows:
 | 
						|
 | 
						|
\snippet make_circulant2.cpp square
 | 
						|
 | 
						|
This little helper structure will help us to implement our \c makeCirculant function as follows:
 | 
						|
 | 
						|
\snippet make_circulant2.cpp makeCirculant
 | 
						|
 | 
						|
As usual, our function takes as argument a \c MatrixBase (see this \ref TopicFunctionTakingEigenTypes "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 \c circulant_functor, which is a straightforward exercise:
 | 
						|
 | 
						|
\snippet make_circulant2.cpp circulant_func
 | 
						|
 | 
						|
We are now all set to try our new feature:
 | 
						|
 | 
						|
\snippet make_circulant2.cpp main
 | 
						|
 | 
						|
 | 
						|
If all the fragments are combined, the following output is produced,
 | 
						|
showing that the program works as expected:
 | 
						|
 | 
						|
\include make_circulant2.out
 | 
						|
 | 
						|
This implementation of \c makeCirculant is much simpler than \ref TopicNewExpressionType "defining a new expression" from scratch.
 | 
						|
 | 
						|
 | 
						|
\section NullaryExpr_Indexing Example 2: indexing rows and columns
 | 
						|
 | 
						|
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:
 | 
						|
 | 
						|
\snippet nullary_indexing.out main1
 | 
						|
 | 
						|
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 \c operator()(i,j):
 | 
						|
 | 
						|
\snippet nullary_indexing.cpp functor
 | 
						|
 | 
						|
Then, let's create an \c indexing(A,rows,cols) function creating the nullary expression:
 | 
						|
 | 
						|
\snippet nullary_indexing.cpp function
 | 
						|
 | 
						|
Finally, here is an example of how this function can be used:
 | 
						|
 | 
						|
\snippet nullary_indexing.cpp main1
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
\snippet nullary_indexing.cpp main2
 | 
						|
 | 
						|
and the output is:
 | 
						|
 | 
						|
\snippet nullary_indexing.out main2
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
}
 | 
						|
 |