Квадратный корень из всех элементов матрицы Boost Ublas Matrix

Я пытаюсь вычислить квадратный корень из всех элементов матрицы Boost Ublas. Пока у меня есть это, и это работает.

#include <iostream>
#include "boost\numeric\ublas\matrix.hpp"
#include <Windows.h>
#include <math.h>
#include <cmath>
#include <algorithm>
typedef boost::numeric::ublas::matrix<float> matrix;
const size_t X_SIZE = 10;
const size_t Y_SIZE = 10;
void UblasExpr();


int main()
{
    UblasExpr();
    return 0;
}

void UblasExpr()
{
    matrix m1, m2, m3;
    m1.resize(X_SIZE, Y_SIZE);
    m2.resize(X_SIZE, Y_SIZE);
    m3.resize(X_SIZE, Y_SIZE);

    for (int i = 0; i < X_SIZE; i++)
    {
        for (int j = 0; j < Y_SIZE; j++)
        {
            m1(i, j) = 2;
            m2(i, j) = 10;
        }
    }

    m3 = element_prod(m1, m2);
    std::transform(m1.data().begin(), m1.data().end(), m3.data().begin(), std::sqrtf);
    for (int i = 0; i < X_SIZE; i++)
    {
        for (int j = 0; j < Y_SIZE; j++)
        {
            std::cout << m3(i, j) << "   ";
        }
        std::cout << std::endl;
    }
}

Но я хотел бы не использовать std::transform, а вместо этого сделать что-то вроде этого: m3 = sqrtf(m1);

Есть ли способ заставить его работать? Мое приложение очень чувствительно к производительности, поэтому альтернатива приемлема только в том случае, если она не приводит к потере эффективности.

P.S. Я хотел бы сделать это для множества других операций, таких как log10f, cos, acos, sin, asin, pow. Мне нужно все это в моем коде.


person The Vivandiere    schedule 05.07.2014    source источник
comment
почему тебе не нравится std::transform?   -  person TemplateRex    schedule 05.07.2014


Ответы (1)


Вы можете определить свою собственную функцию sqrt с соответствующей подписью:

typedef boost::numeric::ublas::matrix<float> matrix;
matrix sqrt_element(const matrix& a)
{
   matrix result(a.size1(), a.size2());
   std::transform(a.data().begin(), a.data().end(), result.data().begin(), std::sqrtf);
   return result;
}

Вы также можете определить общий «apply_elementwise», чтобы использовать вызываемый объект в качестве аргумента (непроверенный/не скомпилированный):

typedef boost::numeric::ublas::matrix<float> matrix;

template <typename CALLABLE>
matrix apply_elementwise(const CALLABLE& f, const matrix& a)
{
   matrix result(a.size1(), a.size2());
   std::transform(a.data().begin(), a.data().end(), result.data().begin(), f);
   return result;
}

Тогда вы могли бы назвать это как:

matrix y(apply_elementwise(std::sqrt, x));
matrix z;
z = apply_elementwise(std::cos,  x);

В этих функциях мы возвращаем матрицу по значению. В идеале вы хотите убедиться, что используемый вами матричный класс использует конструкторы rvalue-reference и операторы присваивания, чтобы свести к минимуму копирование данных.

person NicholasM    schedule 05.07.2014
comment
отличный ответ, сверх того, что просили очень полезным способом. - person flies; 23.01.2016