문제

I would like to use the algorithms of std::numeric to compute the sum of the absolute values of an array, in order to use the gnu parallel extensions (array size is > 500000).

Here is my current code :

double ret = 0;
for (auto i = 0U; i < length; ++i)
{
    ret += std::abs(tab[i]);
}
return ret;

So I thought about doing :

auto sumabs = [] (double a, double b) 
{
    return std::abs(a) + std::abs(b);
} 

std::accumulate(tab, tab + length, 0, sumabs);

But it is inefficient because if a reduction algorithm is performed (which I sincerely hope for the sake of fast computation!), std::abs will be applied to values which are already >= 0.

So is there any way to do this ? perhaps performing the first step of the reduction "by hand", and let std::accumulate do a simple addition between the rest ? But there will be a copy and a memory hit...

도움이 되었습니까?

해결책

You can pass a function to the accumlate method and perform the "by hand" evaluation inside the function. By the way in your code you apply the abs method to the first parameter which is not necessary.

int fAccumulate (int accumulated, int accumulateIncrement) 
{
    int retValue = 0;
    if (accumulateIncrement >= 0)
    {
        retValue = accumulated + accumulateIncrement;
    }
    else
    {
        retValue = accumulated + std::abs(accumulateIncrement);
    }
    return retValue;
}

The use of this code could be:

int init = 0;
int numbers[] = {10,20,-30};
int a = std::accumulate (numbers, numbers+3, init, fAccumulate);

다른 팁

This will use the minimum number of calls to std::abs necessary:

#include <algorithm>
#include <cmath>

int main() {
    static const auto abssum = [] (auto x, auto y) {return x + std::abs(y);};
    
    float entries[4] = {1.0f, 2.0f, 3.0f, 4.0f};

    auto sum = std::accumulate(std::begin(entries), std::end(entries), 0.0f, abssum);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top