Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ boost or STL `y += f(x)` type algorithm

I know I can do this y[i] += f(x[i]) using transform with two input iterators. however it seems somewhat counterintuitive and more complicated than for loop.

Is there a more natural way to do so using existing algorithm in boost or Stl. I could not find clean equivalent.

here is transform (y = y + a*x):

using boost::lambda;
transform(y.begin(), y.end(), x.begin(), y.begin(), (_1 + scale*_2);
//  I thought something may exist:
transform2(x.begin(), x.end(), y.begin(), (_2 + scale*_1);
// it does not, so no biggie. I will write wrapper

Thanks

like image 712
Anycorn Avatar asked Mar 22 '26 14:03

Anycorn


1 Answers

There are several ways to do this.

As you noted you can use transform with a number of predicates, some more or less automatically generated:

std::vector<X> x = /**/;
std::vector<Y> y = /**/;

assert(x.size() == y.size());

//
// STL-way
//
struct Predicate: std::binary_function<X,Y,Y>
{
  Y operator()(X lhs, Y rhs) const { return rhs + f(lhs); }
};

std::transform(x.begin(), x.end(), y.begin(), y.begin(), Predicate());

//
// C++0x way
//
std::transform(x.begin(), x.end(), y.begin(), y.begin(),
               [](X lhs, Y rhs) { return rhs += f(lhs); });

Now, if we had a vector with the range of indices, we could do it in a more "pythony" way:

std::vector<size_t> indices = /**/;


//
// STL-way
//
class Predicate: public std::unary_function<size_t, void>
{
public:
  Predicate(const std::vector<X>& x, std::vector<Y>& y): mX(x), mY(y) {}
  void operator()(size_t i) const { y.at(i) += f(x.at(i)); }
private:
  const std::vector<X>& mX;
  std::vector<Y>& mY;
};

std::foreach(indices.begin(), indices.end(), Predicate(x,y));

//
// C++0x way
//
std::foreach(indices.begin(), indices.end(), [&](size_t i) { y.at(i) += f(x.at(i)); });

//
// Boost way
//
BOOST_FOREACH(size_t i, indices) y.at(i) += f(x.at(i));

I don't know if there could be something to do with views, they normally allow some pretty syntax. Of course it's a bit difficult here I think because of the self-modifying y.

like image 115
Matthieu M. Avatar answered Mar 25 '26 03:03

Matthieu M.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!