Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 1 | namespace Eigen { |
| 2 | |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 3 | /** \page TutorialMatrixArithmetic Tutorial page 2 - %Matrix and vector arithmetic |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 4 | \ingroup Tutorial |
| 5 | |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 6 | \li \b Previous: \ref TutorialMatrixClass |
| 7 | \li \b Next: \ref TutorialArrayClass |
| 8 | |
| 9 | This tutorial aims to provide an overview and some details on how to perform arithmetic |
| 10 | between matrices, vectors and scalars with Eigen. |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 11 | |
| 12 | \b Table \b of \b contents |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 13 | - \ref TutorialArithmeticIntroduction |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 14 | - \ref TutorialArithmeticAddSub |
| 15 | - \ref TutorialArithmeticScalarMulDiv |
| 16 | - \ref TutorialArithmeticMentionXprTemplates |
Gael Guennebaud | de1220a | 2010-06-28 00:05:11 +0200 | [diff] [blame] | 17 | - \ref TutorialArithmeticTranspose |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 18 | - \ref TutorialArithmeticMatrixMul |
| 19 | - \ref TutorialArithmeticDotAndCross |
| 20 | - \ref TutorialArithmeticRedux |
| 21 | - \ref TutorialArithmeticValidity |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 22 | |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 23 | \section TutorialArithmeticIntroduction Introduction |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 24 | |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 25 | Eigen offers matrix/vector arithmetic operations either through overloads of common C++ arithmetic operators such as +, -, *, |
| 26 | or through special methods such as dot(), cross(), etc. |
| 27 | For the Matrix class (matrices and vectors), operators are only overloaded to support |
| 28 | linear-algebraic operations. For example, \c matrix1 \c * \c matrix2 means matrix-matrix product, |
| 29 | and \c vector \c + \c scalar is just not allowed. If you want to perform all kinds of array operations, |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 30 | not linear algebra, see the \ref TutorialArrayClass "next page". |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 31 | |
Jitse Niesen | 3070164 | 2010-06-29 11:42:51 +0100 | [diff] [blame] | 32 | \section TutorialArithmeticAddSub Addition and subtraction |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 33 | |
| 34 | The left hand side and right hand side must, of course, have the same numbers of rows and of columns. They must |
| 35 | also have the same \c Scalar type, as Eigen doesn't do automatic type promotion. The operators at hand here are: |
| 36 | \li binary operator + as in \c a+b |
| 37 | \li binary operator - as in \c a-b |
| 38 | \li unary operator - as in \c -a |
| 39 | \li compound operator += as in \c a+=b |
| 40 | \li compound operator -= as in \c a-=b |
| 41 | |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 42 | <table class="example"> |
| 43 | <tr><th>Example:</th><th>Output:</th></tr> |
| 44 | <tr><td> |
| 45 | \include tut_arithmetic_add_sub.cpp |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 46 | </td> |
| 47 | <td> |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 48 | \verbinclude tut_arithmetic_add_sub.out |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 49 | </td></tr></table> |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 50 | |
| 51 | \section TutorialArithmeticScalarMulDiv Scalar multiplication and division |
| 52 | |
| 53 | Multiplication and division by a scalar is very simple too. The operators at hand here are: |
| 54 | \li binary operator * as in \c matrix*scalar |
| 55 | \li binary operator * as in \c scalar*matrix |
| 56 | \li binary operator / as in \c matrix/scalar |
| 57 | \li compound operator *= as in \c matrix*=scalar |
| 58 | \li compound operator /= as in \c matrix/=scalar |
| 59 | |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 60 | <table class="example"> |
| 61 | <tr><th>Example:</th><th>Output:</th></tr> |
| 62 | <tr><td> |
| 63 | \include tut_arithmetic_scalar_mul_div.cpp |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 64 | </td> |
| 65 | <td> |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 66 | \verbinclude tut_arithmetic_scalar_mul_div.out |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 67 | </td></tr></table> |
| 68 | |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 69 | |
| 70 | \section TutorialArithmeticMentionXprTemplates A note about expression templates |
| 71 | |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 72 | This is an advanced topic that we explain on \ref TopicEigenExpressionTemplates "this page", |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 73 | but it is useful to just mention it now. In Eigen, arithmetic operators such as \c operator+ don't |
| 74 | perform any computation by themselves, they just return an "expression object" describing the computation to be |
| 75 | performed. The actual computation happens later, when the whole expression is evaluated, typically in \c operator=. |
| 76 | While this might sound heavy, any modern optimizing compiler is able to optimize away that abstraction and |
| 77 | the result is perfectly optimized code. For example, when you do: |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 78 | \code |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 79 | VectorXf a(50), b(50), c(50), d(50); |
| 80 | ... |
| 81 | a = 3*b + 4*c + 5*d; |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 82 | \endcode |
Jitse Niesen | 3070164 | 2010-06-29 11:42:51 +0100 | [diff] [blame] | 83 | Eigen compiles it to just one for loop, so that the arrays are traversed only once. Simplifying (e.g. ignoring |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 84 | SIMD optimizations), this loop looks like this: |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 85 | \code |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 86 | for(int i = 0; i < 50; ++i) |
| 87 | a[i] = 3*b[i] + 4*c[i] + 5*d[i]; |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 88 | \endcode |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 89 | Thus, you should not be afraid of using relatively large arithmetic expressions with Eigen: it only gives Eigen |
| 90 | more opportunities for optimization. |
| 91 | |
Gael Guennebaud | de1220a | 2010-06-28 00:05:11 +0200 | [diff] [blame] | 92 | \section TutorialArithmeticTranspose Transposition and conjugation |
| 93 | |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 94 | The transpose \f$ a^T \f$, conjugate \f$ \bar{a} \f$, and adjoint (i.e., conjugate transpose) \f$ a^* \f$ of a matrix or vector \f$ a \f$ are obtained by the member functions \link DenseBase::transpose() transpose()\endlink, \link MatrixBase::conjugate() conjugate()\endlink, and \link MatrixBase::adjoint() adjoint()\endlink, respectively. |
Gael Guennebaud | de1220a | 2010-06-28 00:05:11 +0200 | [diff] [blame] | 95 | |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 96 | <table class="example"> |
| 97 | <tr><th>Example:</th><th>Output:</th></tr> |
| 98 | <tr><td> |
| 99 | \include tut_arithmetic_transpose_conjugate.cpp |
Gael Guennebaud | de1220a | 2010-06-28 00:05:11 +0200 | [diff] [blame] | 100 | </td> |
| 101 | <td> |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 102 | \verbinclude tut_arithmetic_transpose_conjugate.out |
Gael Guennebaud | de1220a | 2010-06-28 00:05:11 +0200 | [diff] [blame] | 103 | </td></tr></table> |
| 104 | |
| 105 | For real matrices, \c conjugate() is a no-operation, and so \c adjoint() is 100% equivalent to \c transpose(). |
| 106 | |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 107 | As for basic arithmetic operators, \c transpose() and \c adjoint() simply return a proxy object without doing the actual transposition. If you do <tt>b = a.transpose()</tt>, then the transpose is evaluated at the same time as the result is written into \c b. However, there is a complication here. If you do <tt>a = a.transpose()</tt>, then Eigen starts writing the result into \c a before the evaluation of the transpose is finished. Therefore, the instruction <tt>a = a.transpose()</tt> does not replace \c a with its transpose, as one would expect: |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 108 | <table class="example"> |
| 109 | <tr><th>Example:</th><th>Output:</th></tr> |
| 110 | <tr><td> |
| 111 | \include tut_arithmetic_transpose_aliasing.cpp |
Gael Guennebaud | de1220a | 2010-06-28 00:05:11 +0200 | [diff] [blame] | 112 | </td> |
| 113 | <td> |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 114 | \verbinclude tut_arithmetic_transpose_aliasing.out |
Gael Guennebaud | de1220a | 2010-06-28 00:05:11 +0200 | [diff] [blame] | 115 | </td></tr></table> |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 116 | This is the so-called \ref TopicAliasing "aliasing issue". In "debug mode", i.e., when \ref TopicAssertions "assertions" have not been disabled, such common pitfalls are automatically detected. |
| 117 | |
| 118 | For \em in-place transposition, as for instance in <tt>a = a.transpose()</tt>, simply use the \link DenseBase::transposeInPlace() transposeInPlace()\endlink function: |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 119 | <table class="example"> |
| 120 | <tr><th>Example:</th><th>Output:</th></tr> |
| 121 | <tr><td> |
| 122 | \include tut_arithmetic_transpose_inplace.cpp |
Gael Guennebaud | de1220a | 2010-06-28 00:05:11 +0200 | [diff] [blame] | 123 | </td> |
| 124 | <td> |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 125 | \verbinclude tut_arithmetic_transpose_inplace.out |
Gael Guennebaud | de1220a | 2010-06-28 00:05:11 +0200 | [diff] [blame] | 126 | </td></tr></table> |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 127 | There is also the \link MatrixBase::adjointInPlace() adjointInPlace()\endlink function for complex matrices. |
Gael Guennebaud | de1220a | 2010-06-28 00:05:11 +0200 | [diff] [blame] | 128 | |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 129 | \section TutorialArithmeticMatrixMul Matrix-matrix and matrix-vector multiplication |
| 130 | |
| 131 | Matrix-matrix multiplication is again done with \c operator*. Since vectors are a special |
| 132 | case of matrices, they are implicitly handled there too, so matrix-vector product is really just a special |
| 133 | case of matrix-matrix product, and so is vector-vector outer product. Thus, all these cases are handled by just |
| 134 | two operators: |
| 135 | \li binary operator * as in \c a*b |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 136 | \li compound operator *= as in \c a*=b (this multiplies on the right: \c a*=b is equivalent to <tt>a = a*b</tt>) |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 137 | |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 138 | <table class="example"> |
| 139 | <tr><th>Example:</th><th>Output:</th></tr> |
| 140 | <tr><td> |
| 141 | \include tut_arithmetic_matrix_mul.cpp |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 142 | </td> |
| 143 | <td> |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 144 | \verbinclude tut_arithmetic_matrix_mul.out |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 145 | </td></tr></table> |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 146 | |
| 147 | Note: if you read the above paragraph on expression templates and are worried that doing \c m=m*m might cause |
| 148 | aliasing issues, be reassured for now: Eigen treats matrix multiplication as a special case and takes care of |
| 149 | introducing a temporary here, so it will compile \c m=m*m as: |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 150 | \code |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 151 | tmp = m*m; |
| 152 | m = tmp; |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 153 | \endcode |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 154 | If you know your matrix product can be safely evaluated into the destination matrix without aliasing issue, then you can use the \link MatrixBase::noalias() noalias()\endlink function to avoid the temporary, e.g.: |
Gael Guennebaud | 75da254 | 2010-06-28 00:42:57 +0200 | [diff] [blame] | 155 | \code |
| 156 | c.noalias() += a * b; |
| 157 | \endcode |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 158 | For more details on this topic, see \ref TopicEigenExpressionTemplates "this page". |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 159 | |
Gael Guennebaud | 75da254 | 2010-06-28 00:42:57 +0200 | [diff] [blame] | 160 | \b Note: for BLAS users worried about performance, expressions such as <tt>c.noalias() -= 2 * a.adjoint() * b;</tt> are fully optimized and trigger a single gemm-like function call. |
| 161 | |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 162 | \section TutorialArithmeticDotAndCross Dot product and cross product |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 163 | |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 164 | The above-discussed \c operator* cannot be used to compute dot and cross products directly. For that, you need the \link MatrixBase::dot() dot()\endlink and \link MatrixBase::cross() cross()\endlink methods. |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 165 | <table class="example"> |
| 166 | <tr><th>Example:</th><th>Output:</th></tr> |
| 167 | <tr><td> |
| 168 | \include tut_arithmetic_dot_cross.cpp |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 169 | </td> |
| 170 | <td> |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 171 | \verbinclude tut_arithmetic_dot_cross.out |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 172 | </td></tr></table> |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 173 | |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 174 | Remember that cross product is only for vectors of size 3. Dot product is for vectors of any sizes. |
| 175 | When using complex numbers, Eigen's dot product is conjugate-linear in the first variable and linear in the |
| 176 | second variable. |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 177 | |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 178 | \section TutorialArithmeticRedux Basic arithmetic reduction operations |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 179 | Eigen also provides some reduction operations to reduce a given matrix or vector to a single value such as the sum (computed by \link DenseBase::sum() sum()\endlink), product (\link DenseBase::prod() prod()\endlink), or the maximum (\link DenseBase::maxCoeff() maxCoeff()\endlink) and minimum (\link DenseBase::minCoeff() minCoeff()\endlink) of all its coefficients. |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 180 | |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 181 | <table class="example"> |
| 182 | <tr><th>Example:</th><th>Output:</th></tr> |
| 183 | <tr><td> |
| 184 | \include tut_arithmetic_redux_basic.cpp |
Gael Guennebaud | dbefd7a | 2010-06-28 13:30:10 +0200 | [diff] [blame] | 185 | </td> |
| 186 | <td> |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 187 | \verbinclude tut_arithmetic_redux_basic.out |
Gael Guennebaud | dbefd7a | 2010-06-28 13:30:10 +0200 | [diff] [blame] | 188 | </td></tr></table> |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 189 | |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 190 | The \em trace of a matrix, as returned by the function \link MatrixBase::trace() trace()\endlink, is the sum of the diagonal coefficients and can also be computed as efficiently using <tt>a.diagonal().sum()</tt>, as we will see later on. |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 191 | |
Gael Guennebaud | dbefd7a | 2010-06-28 13:30:10 +0200 | [diff] [blame] | 192 | There also exist variants of the \c minCoeff and \c maxCoeff functions returning the coordinates of the respective coefficient via the arguments: |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 193 | |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 194 | <table class="example"> |
| 195 | <tr><th>Example:</th><th>Output:</th></tr> |
| 196 | <tr><td> |
| 197 | \include tut_arithmetic_redux_minmax.cpp |
Gael Guennebaud | dbefd7a | 2010-06-28 13:30:10 +0200 | [diff] [blame] | 198 | </td> |
| 199 | <td> |
Gael Guennebaud | f66fe26 | 2010-10-19 11:40:49 +0200 | [diff] [blame^] | 200 | \verbinclude tut_arithmetic_redux_minmax.out |
Gael Guennebaud | dbefd7a | 2010-06-28 13:30:10 +0200 | [diff] [blame] | 201 | </td></tr></table> |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 202 | |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 203 | |
Gael Guennebaud | dbefd7a | 2010-06-28 13:30:10 +0200 | [diff] [blame] | 204 | \section TutorialArithmeticValidity Validity of operations |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 205 | Eigen checks the validity of the operations that you perform. When possible, |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 206 | it checks them at compile time, producing compilation errors. These error messages can be long and ugly, |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 207 | but Eigen writes the important message in UPPERCASE_LETTERS_SO_IT_STANDS_OUT. For example: |
| 208 | \code |
| 209 | Matrix3f m; |
| 210 | Vector4f v; |
| 211 | v = m*v; // Compile-time error: YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES |
| 212 | \endcode |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 213 | |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 214 | Of course, in many cases, for example when checking dynamic sizes, the check cannot be performed at compile time. |
Jitse Niesen | 2c03ca3 | 2010-07-09 11:46:07 +0100 | [diff] [blame] | 215 | Eigen then uses runtime assertions. This means that the program will abort with an error message when executing an illegal operation if it is run in "debug mode", and it will probably crash if assertions are turned off. |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 216 | |
Benoit Jacob | e078bb2 | 2010-06-26 14:00:00 -0400 | [diff] [blame] | 217 | \code |
| 218 | MatrixXf m(3,3); |
| 219 | VectorXf v(4); |
| 220 | v = m * v; // Run-time assertion failure here: "invalid matrix product" |
| 221 | \endcode |
| 222 | |
| 223 | For more details on this topic, see \ref TopicAssertions "this page". |
| 224 | |
| 225 | \li \b Next: \ref TutorialArrayClass |
Carlos Becker | 9d44005 | 2010-06-25 20:16:12 -0400 | [diff] [blame] | 226 | |
| 227 | */ |
| 228 | |
| 229 | } |