Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rewrite a nested loop using the C++ STL algorithms?

The loop is simple enough, but I just can't seem to wrap my head around using the STL algorithms to give the same nested loop below.

const int a_size = 5; // input
const int c_size = 2; // output
const int b_size = a_size * c_size; // multipliers

std::vector<float> a(a_size);
std::vector<float> b(b_size);
std::vector<float> c(c_size);

// fill a and b with data

// this nested loop
for(int i = 0; i<c_size; i++) {
    c[i] = 0.0;
    for(int k = 0; k<a_size; k++) {
        c[i] += (a[k] * b[i*a_size+k]);
    }
    c[i] = sigmoid(c[i]);
}

The reason why I would like to do this, is for the Boost.Compute library, which would do the calculations on the GPU using STL-like algorithms (std::transform, std::for_each, etc.).

like image 761
user1973386 Avatar asked Oct 30 '13 09:10

user1973386


2 Answers

in fact the nested loop is algorithm std::inner_product.

auto first = std::begin( b );
auto increment = std::distance( std::begin( a ), std::end( a ) );
//,,

c[i] = std::inner_product( std::begin( a ), std::end( a ), first, 0 );
std::advance( first, increment );

Instead of the outer loop you could use algorithm std::generate.

like image 79
Vlad from Moscow Avatar answered Oct 24 '22 07:10

Vlad from Moscow


I came up with:

auto i = 0;
generate(begin(c), end(c), [&i, &a, &b]
{
    return sigmoid(inner_product
    (
        begin(a), end(a),
        begin(b) + distance(begin(a), end(a)) * i++, 0.f
    ));
});

But it does not look pretty well - probably in such case I would prefer to write my own algorithm.

Or use matrix-form. With Eigen library it will became:

MatrixXd b;
VectorXd a, c;
// ...
c = (b*a).unaryExpr(sigmoid);
like image 32
Evgeny Panasyuk Avatar answered Oct 24 '22 07:10

Evgeny Panasyuk