Std :: accumulate () only the real part of the complex std :: vector

I used the sum of the symmetric (Hermitian) matrix (the matrix is ​​in std::vector), which is a huge loss, because the imaginary part will always be added to zero (I'm talking about huge matrices with side lengths n>1000, so I think it matters.

So, now I add only the upper triangular part of the matrix. But I want to optimize this further and not add the difficult part, because I do not need it.

I am currently using:

std::real(std::accumulate(myMatrix.begin(), myMatrix.end(), std::complex<Real>(0,0)));

This adds the whole item from myMatrixto std::complex<Real>(0,0), resulting in the amount I need.

But this will add real and imaginary components to my vector, which is a waste! How can I write the most optimized version of this that adds only the real part of this matrix?


UPDATE:

While I was accepting an answer that worked, I found that it was slower than adding up the real and imaginary parts of my matrix. This is 5% -10% slower for a matrix with a side length of 128. This is surprising. Any other faster offers are highly appreciated.

Ask if you need more information.

+4
source share
3 answers
Real real_sum = std::accumulate(
    myMatrix.cbegin(), myMatrix.cend(), Real{},
    [](Real const acc, std::complex<Real> const& c) { return acc + std::real(c); }
);
+8
source

std::accumulate has two overloads, one of which takes an operator:

template< class InputIt, class T, class BinaryOperation >
T accumulate( InputIt first, InputIt last, T init,
              BinaryOperation op );

, +:

std::accumulate(myMatrix.begin(), myMatrix.end(), Real{0},
    [](Real const& sum, std::complex<Real> const& next){
        return sum + std::real(next);
    });

- , boost::transform_iterator:

auto make_real = [](std::complex<Real> const& c) {
    return std::real(c);
};

std::accumulate(
    boost::make_transform_iterator(myMatrix.begin(), make_real),
    boost::make_transform_iterator(myMatrix.end(), make_real),
    Real{0});

range-v3:

accumulate(myMatrix,
    Real{0},
    std::plus<>{},
    [](std::complex<Real> const& c) { return c.real(); }
);

, real , std::real<Real> &std::complex<Real>::real .

+4

std::accumulate ?

    Real acc = 0;
    for(auto c : myMatrix)
       acc += real(c);

, , , , , .

g++ - 4.8.4:

  template<typename _InputIterator, typename _Tp>
    inline _Tp
    accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
    {
      // concept requirements
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      __glibcxx_requires_valid_range(__first, __last);

      for (; __first != __last; ++__first)
    __init = __init + *__first;
      return __init;
    }

, , .

+1

Source: https://habr.com/ru/post/1648556/


All Articles