[eigen] Generic conservativeResize() for both matrices and vectors?

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]


Hi again,

Writing a function that takes as argument a generic
"MatrixBase<Derived>" I found that apparently there is no easy-to-use
conservativeResize() that works for both NxM matrices and column or
row matrices (vectors). The problem is that the signature changes from
2 to 1 dimensions.

I attach a test case that shows this, with a #define that, if
declared, uses the ugly workaround I wrote.
Comment that #define line to see the build errors of this first, simple idea:

template <class Derived>
void foo( Eigen::MatrixBase<Derived> &m, int nRows, int nCols )
{
	m.derived().conservativeResize(nRows,nCols);
}

With the workaround, that becomes:

	detail::MatOrVecResizer<Derived::RowsAtCompileTime,Derived::ColsAtCompileTime>::doit(
		m.derived(),nRows,nCols);

plus the auxiliary struct "MatOrVecResizer" and two specializations....

For me it's OK to keep this solution, but just in case: Is there any
other shorter way to deal with this in Eigen??

Best,
JL
#include <iostream>
#include <Eigen/Core>

using namespace std;
using namespace Eigen;

#define USE_WORKAROUND

#ifndef USE_WORKAROUND
// ============ The first, simple idea =============
template <class Derived>
void foo( Eigen::MatrixBase<Derived> &m, int nRows, int nCols )
{
	m.derived().conservativeResize(nRows,nCols);
}
#else
// ============ The solution I found (but ugly...) ==============
namespace detail
{
	// Generic version for all kind of matrices:
	template<int R, int C>
	struct MatOrVecResizer
	{
		template <typename S, int Opt, int MaxR, int MaxC>
		static inline void doit(Eigen::Matrix<S,R,C,Opt,MaxR,MaxC> &mat, size_t new_rows,size_t new_cols)
		{
			mat.derived().conservativeResize(new_rows,new_cols);
		}
	};
	// Specialization for column matrices:
	template<int R>
	struct MatOrVecResizer<R,1>
	{
		template <typename S, int Opt, int MaxR, int MaxC>
		static inline void doit(Eigen::Matrix<S,R,1,Opt,MaxR,MaxC> &mat, size_t new_rows,size_t new_cols)
		{
			mat.derived().conservativeResize(new_rows);
		}
	};
	// Specialization for row matrices:
	template<int C>
	struct MatOrVecResizer<1,C>
	{
		template <typename S, int Opt, int MaxR, int MaxC>
		static inline void doit(Eigen::Matrix<S,1,C,Opt,MaxR,MaxC> &mat, size_t new_rows,size_t new_cols)
		{
			mat.derived().conservativeResize(new_cols);
		}
	};
}

template <class Derived>
void foo( Eigen::MatrixBase<Derived> &m, int nRows, int nCols )
{
	detail::MatOrVecResizer<Derived::RowsAtCompileTime,Derived::ColsAtCompileTime>::doit(
		m.derived(),nRows,nCols);
}
#endif

int main()
{
	// This one works always:
	{
		Matrix<double,Dynamic,Dynamic>  M;
		foo(M,3,4);
		cout << "M:\n"<<M << endl;
	}

	// These two are the problem:
	{
		Matrix<double,1,Dynamic>  M;
		foo(M,1,4);
		cout << "M:\n"<<M << endl;
	}
	{
		Matrix<double,Dynamic,1>  M;
		foo(M,4,1);
		cout << "M:\n"<<M << endl;
	}

	return 0;
}



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/