Registered Member
|
Hi,
I am new here, so let me start by saying thanks for producing and providing Eigen. It's an amazing library. To my issue: I am trying to write a fairly generic implementation of an algorithm. At a few points in my algorithm I need to solve linear problems. To keep things DRY, I decided to wrap the corresponding series of Eigen-calls into a function. Furthermore, to also avoid need-less copies I thought it would be a good idea to return the corresponding expression template instead of a plain matrix object. Unfortunately, this fails due to a violated assertion inside Eigen: When compiled with Clang 3.4:
And when compiled with GCC 4.8.1:
The above assertion is generated by the following example code:
It seems to me, that the result of `solve()` has some internal state, and does not quite like losing its scope before you assign it to something. A GDB back-trace of the GCC compiled version follows in the end. A quite hack-ish way to remedy this problem is to transpose the result twice. I.e. simply replace the `solve` function above by the following piece of code:
Now, my question is: Am I doing something wrong, or is this an issue within Eigen? And why does the double `transpose` fix it? Does it contain an implicit `eval` or is there something else to it? Btw, I've tried it with `fullPivLu` as well. The outcome is the same. Cheers Andreas EDIT: This is with Eigen version 3.2.2 --- The promised back-trace
|
Moderator
|
This is because the ColPivHouseholderQR object is deleted at the end of the function and therefore the object returned by the solve() method stores dead references. In other words, this is because A.colPivHouseholderQr() does not return an abstract expression, but an object containing the result of the decomposition.
|
Registered Member
|
@ggael Thanks for your response.
Okay, I suspected something like this. But then, why does the double transpose fix this? Does it internally do an `eval`, or is it something else? In other words, what is the correct way to implement my function `solve`? And is it possible to return an expression to avoid an extra copy? |
Moderator
|
The first transpose evaluate the result of the solve operation which is put on the stack. The cleanest way would be to either make the result an argument of your function: solve(A,b,x) (C-style) or make your solve function returns a pseudo expression inheriting EigenBase, storing references to A and b, and implementing an evalTo(x) member function doing the actual factorisation and solving.
|
Registered Member
|
@ggael Thank you for these suggestions.
Unfortunately, for technical reasons, the C-type signature is not really an option in my case. So, I gave the pseudo expression a shot. Is there some documentation available on how to do this? I've read this page about customizing/extending Eigen, but couldn't find any instructions on how to write your own expressions. The documentation on expression templates also seems rather sparse. Here is what I've got so far:
It compiles, but when run, it fails with a segmentation fault. According to GDB that happens in this line:
What am I doing wrong? |
Registered Member
|
Unfortunately, I still haven't been able to solve this problem.
May I ask for some pointers on how to properly write my own expressions in Eigen? |
Registered Member
|
Thanks a lot!! Actually you pointed the miss things for me. |
Registered Member
|
It makes sense. The reason for this issue could be because the A.colPivHouseholderQr() method returns an object that contains the result of a matrix decomposition operation, rather than an abstract expression. |
Registered users: Bing [Bot], Google [Bot], kesang, Yahoo [Bot]