Вычислить сумму абсолютных значений с помощью алгоритмов stl

Я хотел бы использовать алгоритмы std::numeric чтобы вычислить сумму абсолютных значений массива, чтобы использовать параллельные расширения gnu (размер массива> 500000).

Вот мой текущий код:

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

Вот я и подумал:

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

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

Но это неэффективно, потому что если выполняется алгоритм редукции (на который я искренне надеюсь ради быстрых вычислений!), std::abs будет применяться к значениям, которые уже> = 0.

Так есть ли способ сделать это? возможно, выполняя первый шаг сокращения «вручную», и пусть std::accumulate сделать простое дополнение между остальными? Но будет копия и попадание в память …

2

Решение

Вы можете передать функцию в метод накопления и выполнить оценку «вручную» внутри функции. Кстати, в вашем коде вы применяете метод abs к первому параметру, который не нужен.

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

Использование этого кода может быть:

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

Другие решения

Это будет использовать минимальное количество звонков на std::abs необходимо:

#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), entries[0], abssum) - entries[0];
}

Т.е. если entries[0] положительный, его нужно вычесть потом; если отрицательный, он отменяется в std::accumulate а также должен быть вычтен впоследствии.

0

По вопросам рекламы [email protected]