NewExpressionType.dox 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. namespace Eigen {
  2. /** \page TopicNewExpressionType Adding a new expression type
  3. <!--<span style="font-size:130%; color:red; font-weight: 900;"></span>-->
  4. \warning
  5. Disclaimer: this page is tailored to very advanced users who are not afraid of dealing with some %Eigen's internal aspects.
  6. In most cases, a custom expression can be avoided by either using custom \ref MatrixBase::unaryExpr "unary" or \ref MatrixBase::binaryExpr "binary" functors,
  7. while extremely complex matrix manipulations can be achieved by a nullary functors as described in the \ref TopicCustomizing_NullaryExpr "previous page".
  8. This page describes with the help of an example how to implement a new
  9. light-weight expression type in %Eigen. This consists of three parts:
  10. the expression type itself, a traits class containing compile-time
  11. information about the expression, and the evaluator class which is
  12. used to evaluate the expression to a matrix.
  13. \b TO \b DO: Write a page explaining the design, with details on
  14. vectorization etc., and refer to that page here.
  15. \eigenAutoToc
  16. \section TopicSetting The setting
  17. A circulant matrix is a matrix where each column is the same as the
  18. column to the left, except that it is cyclically shifted downwards.
  19. For example, here is a 4-by-4 circulant matrix:
  20. \f[ \begin{bmatrix}
  21. 1 & 8 & 4 & 2 \\
  22. 2 & 1 & 8 & 4 \\
  23. 4 & 2 & 1 & 8 \\
  24. 8 & 4 & 2 & 1
  25. \end{bmatrix} \f]
  26. A circulant matrix is uniquely determined by its first column. We wish
  27. to write a function \c makeCirculant which, given the first column,
  28. returns an expression representing the circulant matrix.
  29. For simplicity, we restrict the \c makeCirculant function to dense
  30. matrices. It may make sense to also allow arrays, or sparse matrices,
  31. but we will not do so here. We also do not want to support
  32. vectorization.
  33. \section TopicPreamble Getting started
  34. We will present the file implementing the \c makeCirculant function
  35. part by part. We start by including the appropriate header files and
  36. forward declaring the expression class, which we will call
  37. \c Circulant. The \c makeCirculant function will return an object of
  38. this type. The class \c Circulant is in fact a class template; the
  39. template argument \c ArgType refers to the type of the vector passed
  40. to the \c makeCirculant function.
  41. \include make_circulant.cpp.preamble
  42. \section TopicTraits The traits class
  43. For every expression class \c X, there should be a traits class
  44. \c Traits<X> in the \c Eigen::internal namespace containing
  45. information about \c X known as compile time.
  46. As explained in \ref TopicSetting, we designed the \c Circulant
  47. expression class to refer to dense matrices. The entries of the
  48. circulant matrix have the same type as the entries of the vector
  49. passed to the \c makeCirculant function. The type used to index the
  50. entries is also the same. Again for simplicity, we will only return
  51. column-major matrices. Finally, the circulant matrix is a square
  52. matrix (number of rows equals number of columns), and the number of
  53. rows equals the number of rows of the column vector passed to the
  54. \c makeCirculant function. If this is a dynamic-size vector, then the
  55. size of the circulant matrix is not known at compile-time.
  56. This leads to the following code:
  57. \include make_circulant.cpp.traits
  58. \section TopicExpression The expression class
  59. The next step is to define the expression class itself. In our case,
  60. we want to inherit from \c MatrixBase in order to expose the interface
  61. for dense matrices. In the constructor, we check that we are passed a
  62. column vector (see \ref TopicAssertions) and we store the vector from
  63. which we are going to build the circulant matrix in the member
  64. variable \c m_arg. Finally, the expression class should compute the
  65. size of the corresponding circulant matrix. As explained above, this
  66. is a square matrix with as many columns as the vector used to
  67. construct the matrix.
  68. \b TO \b DO: What about the \c Nested typedef? It seems to be
  69. necessary; is this only temporary?
  70. \include make_circulant.cpp.expression
  71. \section TopicEvaluator The evaluator
  72. The last big fragment implements the evaluator for the \c Circulant
  73. expression. The evaluator computes the entries of the circulant
  74. matrix; this is done in the \c .coeff() member function. The entries
  75. are computed by finding the corresponding entry of the vector from
  76. which the circulant matrix is constructed. Getting this entry may
  77. actually be non-trivial when the circulant matrix is constructed from
  78. a vector which is given by a complicated expression, so we use the
  79. evaluator which corresponds to the vector.
  80. The \c CoeffReadCost constant records the cost of computing an entry
  81. of the circulant matrix; we ignore the index computation and say that
  82. this is the same as the cost of computing an entry of the vector from
  83. which the circulant matrix is constructed.
  84. In the constructor, we save the evaluator for the column vector which
  85. defined the circulant matrix. We also save the size of that vector;
  86. remember that we can query an expression object to find the size but
  87. not the evaluator.
  88. \include make_circulant.cpp.evaluator
  89. \section TopicEntry The entry point
  90. After all this, the \c makeCirculant function is very simple. It
  91. simply creates an expression object and returns it.
  92. \include make_circulant.cpp.entry
  93. \section TopicMain A simple main function for testing
  94. Finally, a short \c main function that shows how the \c makeCirculant
  95. function can be called.
  96. \include make_circulant.cpp.main
  97. If all the fragments are combined, the following output is produced,
  98. showing that the program works as expected:
  99. \include make_circulant.out
  100. */
  101. }