Re: [eigen] Passing result of block() as non-const reference-to-matrix? |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen@xxxxxxxxxxxxxxxxxxx
- Subject: Re: [eigen] Passing result of block() as non-const reference-to-matrix?
- From: Hauke Heibel <hauke.heibel@xxxxxxxxxxxxxx>
- Date: Fri, 9 Jul 2010 12:06:26 +0200
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:mime-version:received:received:in-reply-to :references:date:message-id:subject:from:to:content-type :content-transfer-encoding; bh=gAorXDGz4JtIEBohDvxscvGr88tbA9t81TyX4Z9FpLc=; b=TctwJUpN4uLMiXsUkgJspdoLoGdELotb0M5+NXhMPRzXqXJHzpWMHttlHg+pCIlozy MeSi92aHhJA40e9NmJC6uqi7jKsGyTk16ekO3owsQi0eyAzT8AEMDvkIAoCpyAY+bi63 UOu5MJLXKm0LMw8OuQ3B9zj7mb2BdMBeMVfxA=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type:content-transfer-encoding; b=Ihv00jD8K6d8FMu6yLFwkNvbrfqDUM9L8rPimd+MNyypf81uD2Pyk5XWMPuppFzK2b 1iA7KGZaxQ9+Ied3KfJSHaaPI/oQjAQ2641TtHbkwGqfV855ihV8pmLB3bB5NxWYm8wo Vb0H0RMCfk/IDLGKs6oKevDD7Zk25p2coFhng=
Yes, this is an ugly issue with expression templates. As you said, the
cleanest way is to use rvalue references.
A second option is to define the function as
template <typename Derived>
void incrementBottomRight(const Eigen::MatrixBase<Derived>& m)
and const_cast to "Eigen::MatrixBase<Derived>&" -- as I said, ugly.
The third an most portable option is in fact to call the function like
this:
Eigen::Block<MatrixXd> b = m.testMatrix.block(0, 0, 2, 2); // this has
quasi zero cost
incrementBottomRight(b);
But in case you have access to them rvalue references are the best option here.
Cheers,
Hauke
On Fri, Jul 9, 2010 at 12:01 PM, Martin Senst <martin.senst@xxxxxx> wrote:
> Hi everyone,
>
> a second problem is that the result of testMatrix.block(0, 0, 2, 2) is a
> temporary object which cannot be bound to an lvalue reference. I'm not sure
> how to circumvent this problem in C++ 03, but if you are using C++0x, you can
> define a second function which takes an rvalue reference. The following
> program works with g++ 4.5 and -std=c++0x, and outputs
>
> 0 0 0
> 0 1 0
> 0 0 1
>
>
> Cheers,
> Martin
>
>
>
>
> #include <Eigen/Core>
>
> template <typename Derived>
> void incrementBottomRight(Eigen::MatrixBase<Derived>& m)
> {
> m(m.rows() - 1, m.cols() - 1) += 1.0;
> }
>
>
> template <typename Derived>
> void incrementBottomRight(Eigen::MatrixBase<Derived>&& m)
> {
> m(m.rows() - 1, m.cols() - 1) += 1.0;
> }
>
>
> int main()
> {
> Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> testMatrix(3, 3);
>
> testMatrix.setZero();
>
> // This uses the first version with an lvalue-reference parameter
> incrementBottomRight(testMatrix);
>
> // This uses the second version with an rvalue-reference parameter
> incrementBottomRight(testMatrix.block(0, 0, 2, 2));
>
> std::cout << testMatrix << std::endl;
>
> return 0;
> }
>
>
>
>
> Am Freitag 09 Juli 2010, 11:52:52 schrieb Hauke Heibel:
>> Hi Sidney,
>>
>> that is expected since a matrix block is not a matrix. It is a special
>> matrix expression which shares operations defined in MatrixBase and
>> DenseBase with matrices. So you need to declare your function as a
>> template function like this
>>
>> template <typename Derived>
>> void incrementBottomRight(Eigen::MatrixBase<Derived> & m)
>> {
>> m(m.rows() - 1, m.cols() - 1) += 1.0;
>> }
>>
>> In case this is not an option you could probably do
>>
>> void incrementBottomRight(Eigen::Block<MatrixXd> & m)
>> {
>> m(m.rows() - 1, m.cols() - 1) += 1.0;
>> }
>>
>> but then the function will be limited to blocks only.
>>
>> Regards,
>> Hauke
>>
>> On Fri, Jul 9, 2010 at 11:28 AM, Sidney Cadot <sidney.cadot@xxxxxxxxx>
> wrote:
>> > Hello,
>> >
>> > Today I found, to my surprise, that passing the result of a
>> > Matrix::block() method to a function that takes a reference to an
>> > Eigen::Matrix doesn't seem to work. The program (which doesn't compile)
>> > demonstrates the problem.
>> >
>> > I know that it /is/ possible to pass the result of a Matrix::block()
>> > const call to a const reference to an Eigen::Matrix. Is it intentional
>> > that the non-const version of this does not work?
>> >
>> > Any help would be greatly appreciated.
>> >
>> > Regards, Sidney
>> >
>> > /////////////////////// code fragment starts here
>> >
>> > #include <Eigen/Core>
>> >
>> > void incrementBottomRight(Eigen::Matrix<double, Eigen::Dynamic,
>> > Eigen::Dynamic> & m) {
>> > m(m.rows() - 1, m.cols() - 1) += 1.0;
>> > }
>> >
>> > int main()
>> > {
>> > Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> testMatrix(3,
>> > 3);
>> >
>> > // This works fine
>> > incrementBottomRight(testMatrix);
>> >
>> > // This gives a compiler error
>> > incrementBottomRight(testMatrix.block(0, 0, 2, 2));
>> >
>> > std::cout << testMatrix << std::endl;
>> >
>> > return 0;
>> > }
>
>
>
>