A blog which discusses various GPU applications including visualization, GPGPU and games.

Friday, May 22, 2009

C++0x Lambdas

I recently installed the VS2010 beta so I could experiment with some of the new C++0x features. In this post, I would like to cover a few simple lambda examples.

Let's start off simple - without lambdas. Suppose we have a vector allocated for 100 floats, and we want to fill it up with random numbers in [0,1). The most obvious way is to use a looping construct of some kind.

vector<float> vec(100);

for (unsigned int i = 0; i < 100; i++)
{
vec[i] = static_cast<float>(rand()) / (static_cast<float>(RAND_MAX) + 1.0f);
}

Okay, I realize I didn't need that many casts, but I like being safe. ;) While this code does the job, we can also use std::generate() to avoid the explicit loop construct:

float randval()
{
return rand() / (RAND_MAX + 1.0f);
}

vector<float> vec(100);

generate(vec.begin(), vec.end(), randval);

Looks fine, right? What can we possibly do differently? We can use a lambda:

vector<float> vec(100);

generate(vec.begin(), vec.end(), []() -> float
{
return rand() / (RAND_MAX + 1.0f);
});

Now consider the slightly more complicated example where we have two vectors and want to produce a third vector from them. We can use a variant of std::transform() to do this.

We have vectors invec1 and invec2, and want to produce outvec which is simply the elementwise product of invec1 and invec2.

First try:

float product(float x, float y)
{
return x * y;
}

transform(invec1.begin(), invec1.end(), invec2.begin(), outvec.begin(), product);

Second try:

transform(invec1.begin(), invec1.end(), invec2.begin(), outvec.begin(), [](float x, float y) -> float
{
return x * y;
});

Another application for lambdas is to use one as a sort predicate:

sort(vec.begin(), vec.end(), [](float x, float y) -> bool { return x > y; });

Don't forget, we can always assign a lambda to a variable to clean things up a little:

void somefunc()
{
auto f = [](float x, float y) -> bool { return x > y; };
sort(vec.begin(), vec.end(), f);
}

Now for some code to put it all together:

vector<float> vec(10);

// Fill up the vector with random numbers in [0,1)
generate(vec.begin(), vec.end(), []() -> float { return rand() / (RAND_MAX + 1.0f); });

// Sort the vector in descending order
sort(vec.begin(), vec.end(), [](float x, float y) -> bool { return x > y; });

// Print the vector
copy(vec.begin(), vec.end(), ostream_iterator<float>(cout, " "));
cout << endl;

No comments:

Post a Comment

Followers