Domanda

vorrei per eseguire funzioni di elemento-saggio sulla matrice spinta e il vettore di tipi, ad esempio prendere il logaritmo di ciascun elemento, exponentiate ciascun elemento, applicare funzioni speciali, come gamma e digamma, ecc (simile al trattamento di MATLAB di queste funzioni applicate alle matrici e vettori.)

Credo che la scrittura di una funzione di supporto che bruta costretto questo per ogni funzione desiderata sarebbe sufficiente, ma questo sembra uno spreco.

Allo stesso modo, il wiki spinta offre qualche codice per Vectorize di serie funzioni , ma questo sembra abbastanza complesso.

valarray è stato suggerito, ma vorrei evitare la conversione tra tipi di dati, come ho bisogno del uBLAS tipi di dati per le altre operazioni (prodotti matrici, matrici sparse, ecc.)

ogni aiuto è molto apprezzato.

È stato utile?

Soluzione

ATTENZIONE

La risposta seguente non è corretta. Vedere Modifica nella parte inferiore. Ho lasciato la risposta originale, come è quello di dare contesto e credito a chi ha sottolineato l'errore.


Io non sono particolarmente familiarità con le librerie Boost, quindi ci può essere un modo più standard per fare questo, ma credo che si può fare quello che vuoi con iteratori e l'STL trasformare modello di funzione. Il introduzione alla documentazione della libreria uBLAS dice che i suoi corsi sono stati progettati per essere compatibili con lo stesso comportamento iteratore che viene utilizzato nel STL. La matrice e vettoriali modelli rafforzato per tutto Ha iteratori che possono essere utilizzati per accedere ai singoli elementi. Il vettore ha begin() e end(), e la matrice ha begin1(), end1(), begin2() e end2(). Le varietà 1 sono iteratori colonna-saggio e le varietà 2 sono iteratori riga-saggio. Vedere la documentazione spinta sulla VectorExpression e MatrixExpression per un po 'più di informazioni.

Usando l'algoritmo STL transform, è possibile applicare una funzione a ogni elemento di una sequenza iterabile e assegnare il risultato a una diversa sequenza iterabile della stessa lunghezza, o la stessa sequenza. Quindi, per usare questo su un vettore uBLAS spinta si potrebbe fare questo:

using namespace boost::numeric::ublas;

// Create a 30 element vector of doubles
vector<double> vec(30);

// Assign 8.0 to each element.
std::fill(vec.begin(), vec.end(), 8.0);

// Perform the "Gamma" function on each element and assign the result back
// to the original element in the vector.
std::transform(vec.begin(), vec.end(), vec.begin(), boost::math::tgamma);

Per una matrice sarebbe fondamentalmente la stessa cosa, si dovrebbe utilizzare sia la 1 o la famiglia 2 di iteratori. Che uno si sceglie di utilizzare dipende se il layout di memoria del vostro matrice è maggiore di riga o colonna importante. Una scansione superficiale della documentazione uBLAS mi porta a credere che potrebbe essere uno dei due, quindi sarà necessario esaminare il codice e determinare quella che viene utilizzato in modo da scegliere l'ordine di iterazione più efficiente.

matrix<double> mat(30, 30);
.
.
.

std::transform(mat.begin1(), mat.end1(), mat.begin1(), boost::math::tgamma);

La funzione si passa come ultimo argomento può essere una funzione di prendere un singolo argomento double e restituisce un valore doppio. Può anche essere un functor .

Questo non è esattamente lo stesso come l'esempio vettorializzazione hai citato, ma sembra che dovrebbe essere abbastanza vicino a quello che si desidera.


Modifica

Sembra che avrei provato la mia raccomandazione prima di renderlo. Come è stato sottolineato da altri, l'iteratori '1' e '2' iterare solo lungo una singola riga / colonna della matrice. La documentazione panoramica di Boost è gravemente fuorviante su questo. Essa sostiene che begin1() "Restituisce un puntamento iterator1 all'inizio della matrice" e che end1() "Restituisce un iterator1 indicando la fine della matrice". Sarebbe li hanno uccisi a dire "una colonna della matrice" invece di "matrice"? Ho assunto che un iterator1 era un iteratore colonna-saggio che iterare dell'intera matrice. Per il modo corretto per fare questo, vedi di Lanterna Rouge risposta .

Altri suggerimenti

L'uso di begin1() / end1() non funzionerà perché fornisce accesso all'elemento nella posizione di colonna predefinito (0): di conseguenza, basta accedere a tutti gli elementi della prima colonna. E 'meglio (nel senso che si ottiene il comportamento previsto) per ottenere l'accesso sequenziale tramite:

std::transform(mat.data().begin(), mat.data().end(),
               mat.data().begin(), boost::math::tgamma) ;

Ho il sospetto che questo può essere un caso in cui l'implementazione non è abbastanza completo.

Enjoy!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top