2013-06-04 16 views
5

Quello che vorrei fare è essenzialmente implementare questa funzione:Crea un Eigen Matrix da una matrice C

template<typename T> 
Matrix<T, Dynamic, Dynamic, ColMajor>* dataToEigen(T* const data, const int rows, const int cols); 

senza copiare i dati. So che il modo standard per realizzare qualcosa di simile è con una mappa, ma ho diversi problemi con questo approccio.

  1. Non voglio riscrivere il resto del mio codice di accettare Maps come ingressi (senza copiare il Map in una matrice temporanea, che è). So che potrei fare questo generalizzando le mie funzioni per prendere gli oggetti MatrixBase come input, ma ho definito specifici modelli Matrix nei miei input per un motivo - se la mia funzione prende uno Matrix<T, Dynamic, Dynamic, ColMajor>, allora è perché dovrebbero essere usate solo matrici di quel tipo come input.

  2. Idealmente, mi piacerebbe che la matrice creata prendesse possesso del puntatore dati, quindi posso semplicemente gestire Matrix tramite shared_ptr e non dover toccare nuovamente il puntatore dati originale.

Il mio pensiero iniziale era che avrei potuto fare qualcosa di simile a creare un oggetto Matrix non inizializzato dimensioni in modo dinamico, e poi basta impostare le dimensioni ed i dati puntatore dell'oggetto, ma questo non sembra essere possibile in API Eigen. Qualcuno sa di eventuali soluzioni alternative?

risposta

3

Ci sono poche probabilità che Eigen :: Matrix sia mai autorizzato a racchiudere direttamente i buffer esterni, e ci sono molte buone ragioni per ciò che includono la compatibilità ABI, la coerenza delle API tra matrici allocate dinamicamente e staticamente.

Un brutto soluzione alternativa potrebbe essere quella di definire una struct con lo stesso layout MatrixX_:

template<typename T> struct Foo { 
    T* data; 
    DenseIndex rows, cols; 
    Matrix<T, Dynamic, Dynamic, ColMajor>& asMatrix() { 
    return reinterpret_cast<Matrix<T, Dynamic, Dynamic, ColMajor>&>(*this); 
    } 
}; 

Un'altra soluzione potrebbe essere quella di passare al ramo devel (abbastanza stabile), e utilizzare il nuovo Ref<> classe che era progettato per risolvere il tuo problema esatto e altro ancora. Il suo documentation dovrebbe essere sufficiente per usarlo correttamente. L'unica difficoltà è che puoi templatizzare facilmente il tipo scalare perché Ref <> non è una classe base di Matrix o Map, e quindi dovrai chiamare la tua funzione specificando esplicitamente il tipo scalare, oppure creare il Rif < > copiare se stessi:

foo<T>(M); 
foo(Ref<MatrixXd>(M)); 
+1

La tua brutta soluzione sembra essere la soluzione più semplice, ma non è abbastanza pericolosa? Al momento non sono troppo preoccupato del fatto che il codice compilato sia portatile, ma c'è qualche garanzia per Foo e un MatrixX basato su modelli finirebbe con la stessa disposizione in memoria? Per quanto riguarda la seconda opzione, suona come ho potuto riscrivere i miei metodi per cercare qualcosa di simile: modello vuoto Foo (const Rif >) e questo li permetterebbe accettare gli input di Matrix e Map >? – user2452966

+1

Il layout della memoria è garantito (compatibilità ABI su tutte le versioni di Eigen). Per Ref <> sì, ecco come usarlo.Il problema è che è meno conveniente quando è parzialmente definito con il parametro template, in quanto Matrix o Map non ereditano Ref <> e quindi al compilatore non sarà consentito istanziare implicitamente gli argomenti del template giusti. Quindi devi fornirlo esplicitamente, o fare esplicitamente la conversione in Ref <>, o se sei preoccupato solo di 2 o 3 tipi di scalari, puoi anche fare in modo che i sovraccarichi 2-3 chiamino la versione generica (soluzione più pulita). – ggael

-1

Penso che la soluzione è facile come il seguente: Colonna

float **data = new float[numRows][numCols]; 
MatrixXf M(numRows,numCols); 
M.data() = data; 

per impostazione predefinita, i dati in una matrice è organizzato Maggiore, quindi se si desidera che il matrice per l'accesso i dati float ** in ordine di Riga Maggiore, è possibile trasporre la matrice dopo l'assegnazione.