• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace Eigen {
2
3/** \page TopicCustomizing_NullaryExpr Matrix manipulation via nullary-expressions
4
5
6The 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.
7Nevertheless, 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.
8
9\section NullaryExpr_Circulant Example 1: circulant matrix
10
11To explore these possibilities let us start with the  \em circulant example of the \ref TopicNewExpressionType "implementing new expression" topic.
12Let us recall that a circulant matrix is a matrix where each column is the same as the
13column to the left, except that it is cyclically shifted downwards.
14For example, here is a 4-by-4 circulant matrix:
15\f[ \begin{bmatrix}
16    1 & 8 & 4 & 2 \\
17    2 & 1 & 8 & 4 \\
18    4 & 2 & 1 & 8 \\
19    8 & 4 & 2 & 1
20\end{bmatrix} \f]
21A circulant matrix is uniquely determined by its first column. We wish
22to write a function \c makeCirculant which, given the first column,
23returns an expression representing the circulant matrix.
24
25For this exercise, the return type of \c makeCirculant will be a CwiseNullaryOp that we need to instantiate with:
261 - a proper \c circulant_functor storing the input vector and implementing the adequate coefficient accessor \c operator(i,j)
272 - a template instantiation of class Matrix conveying compile-time information such as the scalar type, sizes, and preferred storage layout.
28
29Calling \c ArgType the type of the input vector, we can construct the equivalent squared Matrix type as follows:
30
31\snippet make_circulant2.cpp square
32
33This little helper structure will help us to implement our \c makeCirculant function as follows:
34
35\snippet make_circulant2.cpp makeCirculant
36
37As usual, our function takes as argument a \c MatrixBase (see this \ref TopicFunctionTakingEigenTypes "page" for more details).
38Then, the CwiseNullaryOp object is constructed through the DenseBase::NullaryExpr static method with the adequate runtime sizes.
39
40Then, we need to implement our \c circulant_functor, which is a straightforward exercise:
41
42\snippet make_circulant2.cpp circulant_func
43
44We are now all set to try our new feature:
45
46\snippet make_circulant2.cpp main
47
48
49If all the fragments are combined, the following output is produced,
50showing that the program works as expected:
51
52\include make_circulant2.out
53
54This implementation of \c makeCirculant is much simpler than \ref TopicNewExpressionType "defining a new expression" from scratch.
55
56
57\section NullaryExpr_Indexing Example 2: indexing rows and columns
58
59The 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:
60
61\snippet nullary_indexing.out main1
62
63To 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):
64
65\snippet nullary_indexing.cpp functor
66
67Then, let's create an \c indexing(A,rows,cols) function creating the nullary expression:
68
69\snippet nullary_indexing.cpp function
70
71Finally, here is an example of how this function can be used:
72
73\snippet nullary_indexing.cpp main1
74
75This straightforward implementation is already quite powerful as the row or column index arrays can also be expressions to perform offsetting, modulo, striding, reverse, etc.
76
77\snippet nullary_indexing.cpp main2
78
79and the output is:
80
81\snippet nullary_indexing.out main2
82
83*/
84
85}
86
87