Estoy escribiendo una función de plantilla que debería tomar algunos Eigen::MatrixBase<Derived> como entrada, realizar algunos cálculos y luego devolver un nuevo valor propio. Quiero devolver el valor con el mismo orden de almacenamiento como entrada.

Pero no tengo idea de cómo obtener el orden de almacenamiento de Eigen::MatrixBase<Derived>. ¿Qué puedo hacer en esta situación, y es posible? Sé que puedo pasar el pedido de almacenamiento como otro parámetro de plantilla o recibir Eigen::Matrix<InpScalar, InpStatRows, InpStatCols, InpStorageOrder>, pero quiero evitarlo, si es posible

PD Perdón por mi pobre inglés

0
Dark_Daiver 5 dic. 2019 a las 12:19

2 respuestas

La mejor respuesta

Para ver el orden de almacenamiento de MatrixBase<Derived>, puede consultar la enumeración IsRowMajor:

int const StorageOrder = Derived::IsRowMajor ? Eigen::RowMajor : Eigen::ColMajor;

Si desea tener un tipo con el mismo orden de almacenamiento y el mismo tamaño que Derived, puede usar directamente typename Derived::PlainObject (o PlainMatrix):

template<class Derived>
typename Derived::PlainObject foo(const Eigen::MatrixBase<Derived> & input)
{
   typename Derived::PlainObject return_value;
   // do some complicated calculations
   return return_value;
}
1
chtz 5 dic. 2019 a las 13:06

Para responder a su comentario sobre cómo declarar una función que recibe una matriz general, puede hacer algo como esto:

Dado que las funciones (y métodos) deducen sus parámetros de plantilla de su parámetro de función real como se muestra a continuación

template <typename InpScalar, int InpStatRows, int InpStatCols, int InpStorageOrder>
void foo(Eigen::Matrix<InpScalar, InpStatRows, InpStatCols, InpStorageOrder>& matrix)
{
    //you can utilize InpStorageOrder here
}

Los parámetros de plantilla del parámetro de entrada matrix se deducirán automáticamente, lo que significa que no tiene que especificarlos explícitamente cuando llame a la función, simplemente pásele cualquier Eigen::Matrix

Un ejemplo sobre cómo llamar a la función desde otra función

void bar()
{
    Eigen::Matrix<double, 3, 3, Eigen::RowMajor> mat;
    foo(mat);
}

Si solo desea obtener el orden de almacenamiento de una matriz dada, si ya no existe nada en la biblioteca Eigen para hacerlo, puede implementar un rasgo de tipo para las matrices Eigen

template <typename TMatrix>
struct MatrixTraits {};

//Partial specialization of MatrixTraits class template
//will accept only `Eigen::Matrix` classes as its template argument
template <typename InpScalar, int InpStatRows, int InpStatCols, int InpStorageOrder>
struct MatrixTraits<Eigen::Matrix<InpScalar, InpStatRows, InpStatCols, InpStorageOrder>>
{
    int StorageOrder = InpStorageOrder;
};

Para utilizar esto, puede hacerlo como:

void bar()
{
    Eigen::Matrix<double, 3, 3, Eigen::RowMajor> mat;
    int StorageOrder = MatrixTraits<decltype(mat)>::StorageOrder;
}
1
Petok Lorand 5 dic. 2019 a las 10:18