I figured this one out by decomposing
the C++ statements until the compiler message was more specific.
It turns out that the compiler was being asked to match
Stride<0,0> with Stride<-1,-1>. The former is
defaulted in some declarations, while the latter is for dynamic
stride. When would one want to use
Stride<0,0>?
Thank you.
On 09/16/2012 08:54 AM, Norman Goldstein wrote:
The compiler is not matching a
function call, and I don't know why.
MapBase is a direct parent of Map, yet here is the error
message:
============ Error Message: First Try ============
error: no matching function for call to
incr( Eigen::Map< Eigen::Matrix<double, -0x000000001,
-0x000000001>,
0,
Eigen::Stride<-0x000000001,
-0x000000001> >& )
note: candidate is:
template< class Derived >
void incr( Eigen::MapBase<Derived>& )
======================================
I thought that, perhaps, the "Level" parameter should be
explicit
in the MapBase description, but then I got the same message:
============= Error Message: Second Try ============
error: no matching function for call to
incr( Eigen::Map< Eigen::Matrix<double, -0x000000001,
-0x000000001>,
0,
Eigen::Stride<-0x000000001,
-0x000000001> >& )
note: candidate is:
template<class Derived, int Level>
void incr(Eigen::MapBase<Derived, Level>&)
==========================================
Any ideas?
Thank you,
Norm
PS I am still working on the recursion, and have switched form
focusing on Block,
to working with Map, instead (as, I believe, someone did suggest
a while ago).
On 08/28/2012 12:29 PM, Norman Goldstein wrote:
OK, I
added
# ifdef EIGEN_BLOCK_TRUE_PLUGIN
# include EIGEN_BLOCK_TRUE_PLUGIN
# endif
just before the protected part of HasDirectAccess==true
in
Block.h,
and have this in Block_true_plugin.h:
////////////////////// Block_true_plugin
code ////////////////
inline
Block<XprType, BlockRows, BlockCols,
InnerPanel, true>
block( Index startRow2,
Index startCol2,
Index blockRows2,
Index blockCols2 )
{
return
Block<XprType, BlockRows, BlockCols,
InnerPanel, true>
( derived(),
startRow2 + startRow(), // <--
Accessor does not exist
startCol2 + startCol(), // <--
Accessor does not exist
blockRows2,
blockCols2 );
}
///////////////////////////////////////////////////////////////////
but, as I discovered, this specialization
inherits from MapBase<Block>, and
unlike the generic Block definition: there is no
startRow() and startCol()
accessors. Any suggestions, please?
On 08/28/2012 01:01 AM, Gael Guennebaud
wrote:
there is a specialization for Block (right after the generic
implementation) for HasDirectAccess==true, so you need to add your
specialization there too.
With the devel branch you might try:
void incr(Ref<MatrixXd> mat) {
// no cast needed
....
}
gael
On Tue, Aug 28, 2012 at 9:07 AM, Norman Goldstein <normvcr@xxxxxxxxx> wrote:
Thank you for the pointers. It is reassuring to know that it was a bug that
stumped me.
I coded up an override Block::block() method to avoid the infinite
recursion:
////////////////////// Plugin Code //////////////////////////////////////
// EIGEN_BLOCK_PLUGIN
inline
Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess>
block( Index startRow2,
Index startCol2,
Index blockRows2,
Index blockCols2 )
{
return
Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess>
( derived(),
startRow2 + startRow(),
startCol2 + startCol(),
blockRows2,
blockCols2 );
}
/////////////////////////////////////////////////////////////////////////////
There is no Block plugin hook, so I put one in right before the protected
section of Block.h .
Also, I slightly modified the test driver:
//////////////////////////////// Code ////////////////////////////////////
#include <Eigen/Core>
using namespace Eigen;
#include <iostream>
using namespace std;
template< class Derived >
void incr( const Block< Derived >& mat ) // <-- Using Block< Derived >
{
Block< Derived >& matV =
const_cast< Block< Derived >& >( mat );
++matV(0,0);
if( ( 1 == mat.rows() ) ||
( 1 == mat.cols() ) )
{
return;
}
else
{
incr( matV.block( 1, // <-- Using
dynamic blocks, only
1,
mat.rows() - 1,
mat.cols() - 1 ) );
}
}// incr
int main( int argc, char* argv[] )
{
MatrixXd mat( 2, 3 );
mat << 1, 2, 3, 4, 5, 6;
cout << "Before: " << mat << endl;
incr( mat.block( 0, 0, mat.rows(), mat.cols() ) ); // <-- Start off with
a block
cout << "After: " << mat << endl;
return 0;
}// main
////////////////////////////////////////////////////////////////////////////////////////////////////
But there is still infinite recursion, even though the Block::block
method returns the same type of Block. What am I missing?
On 08/27/2012 12:13 PM, Christoph Hertzberg wrote:
On 27.08.2012 19:33, Norman Goldstein wrote:
I haven't been able to figure out how to write a routine that calls
itself recursively
with successively smaller sub-blocks of the original matrix. Here is a
simple example,
With the current stable branch this is not possible, because this would
possibly generate infinitely many template instanciations. See also:
http://eigen.tuxfamily.org/bz/show_bug.cgi?id=408
There is an experimental solution here:
http://eigen.tuxfamily.org/bz/show_bug.cgi?id=481.
[...]
template< class Derived >
void incr( const DenseBase< Derived >& mat )
{
DenseBase< Derived >& matV =
const_cast< DenseBase< Derived >& >( mat );
[...]
{
incr( mat.bottomRightCorner( mat.rows() - 1,
mat.cols() - 1 ) );
Your problem here, however, is that mat is const, so
mat.bottomRightCorner(...) is a Block<const ...> and that inner const is not
removed by a const_cast. If you do matV.bottomRightCorner(...) instead, you
should get to the problem above ^^.
Btw:
If you just do tail recursion, you don't need to do recursion at all, just
do sth like this:
template<class Derived>
void incr(const DenseBase<Derived>& mat){
for(int i=mat.rows(); i>0; --i) {
++mat.bottomRightCorner(i,i)(0,0);
}
}
This version only works for square matrices, I guess you get the idea,
though.
Christoph
|