Pergunta

i gostaria de executar funções de elemento a elemento de impulso da matriz e do vetor tipos, por exemplo tomar o logaritmo de cada elemento, cada elemento exponentiate, aplicam-se as funções especiais, tais como a gama e digamma, etc (semelhante ao tratamento do Matlab destas funções aplicada a matrizes e vectores.)

suponho escrever uma função auxiliar que brute-forçados isso para cada função desejada seria suficiente, mas isso parece um desperdício.

Da mesma forma, as ofertas impulso wiki algum código para vectorize padrão funções , mas isso parece bastante complexo.

valarray foi sugerido, mas eu gostaria de evitar a conversão entre tipos de dados, como eu preciso os dados tipos ublas para outras operações (produtos de matriz, matrizes esparsas, etc.)

Qualquer ajuda é muito apreciada.

Foi útil?

Solução

ATENÇÃO

A seguinte resposta está incorreta. Ver Editar na parte inferior. Deixei a resposta original como é dar contexto e de crédito para aqueles que apontou o erro.


Eu não estou particularmente familiarizado com as bibliotecas de impulso, de modo que pode haver uma maneira mais padrão de fazer isso, mas acho que você pode fazer o que quiser com iterators ea STL transformar modelo de função. A introdução ao uBLAS documentação da biblioteca diz que suas aulas são projetados para serem compatíveis com o mesmo comportamento iterador que é usado no STL. As matriciais e vetoriais modelos de impulsionar todos Tem iterators que pode ser utilizado para o acesso dos elementos individuais. O vector tem begin() e end(), e a matriz tem begin1(), end1(), begin2(), e end2(). As variedades 1 são iterators direcção de coluna e as variedades 2 são iterators linha por linha. Consulte a documentação do impulso na VectorExpression e MatrixExpression para um pouco mais informações.

Usando o algoritmo STL transform, você pode aplicar uma função a cada elemento de uma seqüência iterable e atribuir o resultado a uma sequência iterable diferente do mesmo comprimento, ou a mesma sequência. Então, para usar isso em um impulso uBLAS vetor que você poderia fazer isso:

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);

Para uma matriz que seria basicamente a mesma coisa, você poderia usar o 1 ou familiar 2 de iteradores. Qual você escolhe para usar depende se o layout de memória de sua matriz é fileira grande ou coluna major. Um exame superficial dos leads documentação uBLAS me a acreditar que poderia ser qualquer um, para que você terá de analisar o código e determinar qual deles está sendo usado para que você escolha a ordem de iteração mais eficiente.

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

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

A função que você passar como o último argumento pode ser uma função que toma um único argumento de casal e retornar um valor duplo. Ele também pode ser um functor .

Este não é exatamente o mesmo que o exemplo vetorização você citou, mas parece que ele deve ser bastante perto do que você quer.


Editar

Parece que eu deveria ter testado a minha recomendação antes de fazer isso. Como foi assinalado por outros, os '1' e '2' iterators única iteração ao longo de uma única linha / coluna da matriz. A documentação visão geral no impulso está seriamente enganosa sobre este assunto. Alega que begin1() "Devolve um apontador iterator1 para o início da matriz" e que end1() "retorna uma apontadores iterator1 até o fim da matriz". Teria matado-los a dizer "uma coluna da matriz" em vez de "matriz"? Presumi que um iterator1 era uma coluna iteração-sábio que iterar sobre toda a matriz. Para a maneira correta de fazer isso, consulte o Lanterna Rouge resposta .

Outras dicas

O uso de begin1() / end1() não vai funcionar, pois fornece acesso ao elemento na posição de coluna padrão (0): consequentemente, basta acessar todos os elementos na primeira coluna. É melhor (no sentido de que você obtenha o comportamento esperado) para obter acesso sequencial via:

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

Eu suspeito que isso pode ser um caso em que a implementação não é bastante completo.

Aproveite!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top