operações de elemento a elemento com tipos impulso c ++ matriz ublas e vetor
-
13-09-2019 - |
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.
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!