blob: 85282bd6f544e02bf7c4330837adde410e2771ff [file] [log] [blame]
Austin Schuh189376f2018-12-20 22:11:15 +11001namespace Eigen {
2
3/** \page TopicPitfalls Common pitfalls
4
5
6\section TopicPitfalls_template_keyword Compilation error with template methods
7
8See this \link TopicTemplateKeyword page \endlink.
9
Austin Schuhc55b0172022-02-20 17:52:35 -080010
Austin Schuh189376f2018-12-20 22:11:15 +110011\section TopicPitfalls_aliasing Aliasing
12
13Don't miss this \link TopicAliasing page \endlink on aliasing,
14especially if you got wrong results in statements where the destination appears on the right hand side of the expression.
15
Austin Schuhc55b0172022-02-20 17:52:35 -080016
17\section TopicPitfalls_alignment_issue Alignment Issues (runtime assertion)
18
19%Eigen does explicit vectorization, and while that is appreciated by many users, that also leads to some issues in special situations where data alignment is compromised.
20Indeed, prior to C++17, C++ does not have quite good enough support for explicit data alignment.
21In that case your program hits an assertion failure (that is, a "controlled crash") with a message that tells you to consult this page:
22\code
23http://eigen.tuxfamily.org/dox/group__TopicUnalignedArrayAssert.html
24\endcode
25Have a look at \link TopicUnalignedArrayAssert it \endlink and see for yourself if that's something that you can cope with.
26It contains detailed information about how to deal with each known cause for that issue.
27
28Now what if you don't care about vectorization and so don't want to be annoyed with these alignment issues? Then read \link getrid how to get rid of them \endlink.
29
30
Austin Schuh189376f2018-12-20 22:11:15 +110031\section TopicPitfalls_auto_keyword C++11 and the auto keyword
32
Austin Schuhc55b0172022-02-20 17:52:35 -080033In short: do not use the auto keywords with %Eigen's expressions, unless you are 100% sure about what you are doing. In particular, do not use the auto keyword as a replacement for a \c Matrix<> type. Here is an example:
Austin Schuh189376f2018-12-20 22:11:15 +110034
35\code
36MatrixXd A, B;
37auto C = A*B;
38for(...) { ... w = C * v; ...}
39\endcode
40
Austin Schuhc55b0172022-02-20 17:52:35 -080041In this example, the type of C is not a \c MatrixXd but an abstract expression representing a matrix product and storing references to \c A and \c B.
42Therefore, the product of \c A*B will be carried out multiple times, once per iteration of the for loop.
43Moreover, if the coefficients of `A` or `B` change during the iteration, then `C` will evaluate to different values as in the following example:
44
45\code
46MatrixXd A = ..., B = ...;
47auto C = A*B;
48MatrixXd R1 = C;
49A = ...;
50MatrixXd R2 = C;
51\endcode
52for which we end up with `R1` &ne; `R2`.
53
Austin Schuh189376f2018-12-20 22:11:15 +110054
55Here is another example leading to a segfault:
56\code
57auto C = ((A+B).eval()).transpose();
58// do something with C
59\endcode
Austin Schuhc55b0172022-02-20 17:52:35 -080060The problem is that \c eval() returns a temporary object (in this case a \c MatrixXd) which is then referenced by the \c Transpose<> expression.
61However, this temporary is deleted right after the first line, and then the \c C expression references a dead object.
62One possible fix consists in applying \c eval() on the whole expression:
63\code
64auto C = (A+B).transpose().eval();
65\endcode
66
67The same issue might occur when sub expressions are automatically evaluated by %Eigen as in the following example:
Austin Schuh189376f2018-12-20 22:11:15 +110068\code
69VectorXd u, v;
70auto C = u + (A*v).normalized();
71// do something with C
72\endcode
Austin Schuhc55b0172022-02-20 17:52:35 -080073Here the \c normalized() method has to evaluate the expensive product \c A*v to avoid evaluating it twice.
74Again, one possible fix is to call \c .eval() on the whole expression:
Austin Schuh189376f2018-12-20 22:11:15 +110075\code
76auto C = (u + (A*v).normalized()).eval();
77\endcode
Austin Schuhc55b0172022-02-20 17:52:35 -080078In this case, \c C will be a regular \c VectorXd object.
79Note that DenseBase::eval() is smart enough to avoid copies when the underlying expression is already a plain \c Matrix<>.
80
81
82\section TopicPitfalls_header_issues Header Issues (failure to compile)
83
84With all libraries, one must check the documentation for which header to include.
85The same is true with %Eigen, but slightly worse: with %Eigen, a method in a class may require an additional \c \#include over what the class itself requires!
86For example, if you want to use the \c cross() method on a vector (it computes a cross-product) then you need to:
87\code
88#include<Eigen/Geometry>
89\endcode
90We try to always document this, but do tell us if we forgot an occurrence.
91
92
93\section TopicPitfalls_ternary_operator Ternary operator
94
95In short: avoid the use of the ternary operator <code>(COND ? THEN : ELSE)</code> with %Eigen's expressions for the \c THEN and \c ELSE statements.
96To see why, let's consider the following example:
97\code
98Vector3f A;
99A << 1, 2, 3;
100Vector3f B = ((1 < 0) ? (A.reverse()) : A);
101\endcode
102This example will return <code>B = 3, 2, 1</code>. Do you see why?
103The reason is that in c++ the type of the \c ELSE statement is inferred from the type of the \c THEN expression such that both match.
104Since \c THEN is a <code>Reverse<Vector3f></code>, the \c ELSE statement A is converted to a <code>Reverse<Vector3f></code>, and the compiler thus generates:
105\code
106Vector3f B = ((1 < 0) ? (A.reverse()) : Reverse<Vector3f>(A));
107\endcode
108In this very particular case, a workaround would be to call A.reverse().eval() for the \c THEN statement, but the safest and fastest is really to avoid this ternary operator with %Eigen's expressions and use a if/else construct.
109
110
111\section TopicPitfalls_pass_by_value Pass-by-value
112
113If you don't know why passing-by-value is wrong with %Eigen, read this \link TopicPassingByValue page \endlink first.
114
115While you may be extremely careful and use care to make sure that all of your code that explicitly uses %Eigen types is pass-by-reference you have to watch out for templates which define the argument types at compile time.
116
117If a template has a function that takes arguments pass-by-value, and the relevant template parameter ends up being an %Eigen type, then you will of course have the same alignment problems that you would in an explicitly defined function passing %Eigen types by reference.
118
119Using %Eigen types with other third party libraries or even the STL can present the same problem.
120<code>boost::bind</code> for example uses pass-by-value to store arguments in the returned functor.
121This will of course be a problem.
122
123There are at least two ways around this:
124 - If the value you are passing is guaranteed to be around for the life of the functor, you can use boost::ref() to wrap the value as you pass it to boost::bind. Generally this is not a solution for values on the stack as if the functor ever gets passed to a lower or independent scope, the object may be gone by the time it's attempted to be used.
125 - The other option is to make your functions take a reference counted pointer like boost::shared_ptr as the argument. This avoids needing to worry about managing the lifetime of the object being passed.
126
127
128\section TopicPitfalls_matrix_bool Matrices with boolean coefficients
129
130The current behaviour of using \c Matrix with boolean coefficients is inconsistent and likely to change in future versions of Eigen, so please use it carefully!
131
132A simple example for such an inconsistency is
133
134\code
135template<int Size>
136void foo() {
137 Eigen::Matrix<bool, Size, Size> A, B, C;
138 A.setOnes();
139 B.setOnes();
140
141 C = A * B - A * B;
142 std::cout << C << "\n";
143}
144\endcode
145
146since calling \c foo<3>() prints the zero matrix while calling \c foo<10>() prints the identity matrix.
147
Austin Schuh189376f2018-12-20 22:11:15 +1100148*/
149}