namespace Eigen { /** \page TopicNewExpressionType Adding a new expression type \warning Disclaimer: this page is tailored to very advanced users who are not afraid of dealing with some %Eigen's internal aspects. In most cases, a custom expression can be avoided by either using custom \ref MatrixBase::unaryExpr "unary" or \ref MatrixBase::binaryExpr "binary" functors, while extremely complex matrix manipulations can be achieved by nullary functors as described in the \ref TopicCustomizing_NullaryExpr "previous page". This page describes with the help of an example how to implement a new light-weight expression type in %Eigen. This consists of three parts: the expression type itself, a traits class containing compile-time information about the expression, and the evaluator class which is used to evaluate the expression to a matrix. \section TopicNewExpressionChecklist Checklist before adding a new matrix or expression type Adding a new dense expression type is an internal extension point. Before doing so, check whether a smaller extension point is enough: - If you only need coefficient-wise custom work, prefer custom \ref TopicCustomizing_Functors "functors" with unaryExpr(), binaryExpr(), NullaryExpr(), or redux(). - If you need a procedural matrix or a read-only indexed view, prefer \ref TopicCustomizing_NullaryExpr "nullary expressions". - If you only need convenience methods on Matrix or Array, prefer the \ref TopicCustomizing_Plugins "plugin" mechanism. - If you need an owning matrix with conventional dense storage, prefer composing or inheriting from Matrix, as described in \ref TopicCustomizing_InheritingMatrix. When a new expression type is still needed, the implementation usually has to provide: - an expression class deriving from MatrixBase, ArrayBase, or EigenBase, depending on the public API it should expose; - an \c internal::traits specialization describing scalar type, storage kind, compile-time sizes, flags, and related expression properties; - storage for operands or parameters, with careful lifetime handling for nested expressions; - rows(), cols(), and any other dimension accessors required by the chosen base class; - an \c internal::evaluator specialization implementing coefficient access, and packet access only when the expression can really be vectorized; - an entry-point function that constructs the expression and returns it by value; - focused tests for fixed and dynamic sizes, constness, aliasing/evaluation behavior, and any supported storage orders. Owning storage types are much more invasive than lightweight expressions because they interact with PlainObjectBase, resizing, alignment, assignment, and evaluator assumptions. New code should avoid introducing such a type unless the existing Matrix, Array, Map, Ref, view, or expression mechanisms cannot represent the use case. \b TO \b DO: Write a page explaining the design, with details on vectorization etc., and refer to that page here. \eigenAutoToc \section TopicSetting The setting 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 simplicity, we restrict the \c makeCirculant function to dense matrices. It may make sense to also allow arrays, or sparse matrices, but we will not do so here. We also do not want to support vectorization. \section TopicPreamble Getting started We will present the file implementing the \c makeCirculant function part by part. We start by including the appropriate header files and forward declaring the expression class, which we will call \c Circulant. The \c makeCirculant function will return an object of this type. The class \c Circulant is in fact a class template; the template argument \c ArgType refers to the type of the vector passed to the \c makeCirculant function. \include make_circulant.cpp.preamble \section TopicTraits The traits class For every expression class \c X, there should be a traits class \c Traits in the \c Eigen::internal namespace containing information about \c X known as compile time. As explained in \ref TopicSetting, we designed the \c Circulant expression class to refer to dense matrices. The entries of the circulant matrix have the same type as the entries of the vector passed to the \c makeCirculant function. The type used to index the entries is also the same. Again for simplicity, we will only return column-major matrices. Finally, the circulant matrix is a square matrix (number of rows equals number of columns), and the number of rows equals the number of rows of the column vector passed to the \c makeCirculant function. If this is a dynamic-size vector, then the size of the circulant matrix is not known at compile-time. This leads to the following code: \include make_circulant.cpp.traits \section TopicExpression The expression class The next step is to define the expression class itself. In our case, we want to inherit from \c MatrixBase in order to expose the interface for dense matrices. In the constructor, we check that we are passed a column vector (see \ref TopicAssertions) and we store the vector from which we are going to build the circulant matrix in the member variable \c m_arg. Finally, the expression class should compute the size of the corresponding circulant matrix. As explained above, this is a square matrix with as many columns as the vector used to construct the matrix. \b TO \b DO: What about the \c Nested typedef? It seems to be necessary; is this only temporary? \include make_circulant.cpp.expression \section TopicEvaluator The evaluator The last big fragment implements the evaluator for the \c Circulant expression. The evaluator computes the entries of the circulant matrix; this is done in the \c .coeff() member function. The entries are computed by finding the corresponding entry of the vector from which the circulant matrix is constructed. Getting this entry may actually be non-trivial when the circulant matrix is constructed from a vector which is given by a complicated expression, so we use the evaluator which corresponds to the vector. The \c CoeffReadCost constant records the cost of computing an entry of the circulant matrix; we ignore the index computation and say that this is the same as the cost of computing an entry of the vector from which the circulant matrix is constructed. In the constructor, we save the evaluator for the column vector which defined the circulant matrix. We also save the size of that vector; remember that we can query an expression object to find the size but not the evaluator. \include make_circulant.cpp.evaluator \section TopicEntry The entry point After all this, the \c makeCirculant function is very simple. It simply creates an expression object and returns it. \include make_circulant.cpp.entry \section TopicMain A simple main function for testing Finally, a short \c main function that shows how the \c makeCirculant function can be called. \include make_circulant.cpp.main If all the fragments are combined, the following output is produced, showing that the program works as expected: \include make_circulant.out */ }