i want to use std::transform to do something similar to binary_op but with one additional constant, for example, to get a product of two vectors: x1 = (10,20,30,40,50) and x2 = (2,4,6,8,10), we can write:
#include <iostream>
#include <algorithm>
#include <vector>
double multiply(double x, double y){
return x*y;
}
int main () {
std::vector<int> x1;
std::vector<int> x2;
for (int i=1; i<6; i++)
x1.push_back (i*10); //10,20,30,40,50
for (int i=1; i<6; i++)
x2.push_back (i*2); //2,4,6,8,10
std::transform (x1.begin(), x1.end(), x2.begin(), x1.begin(),multiply);
for (std::vector<int>::iterator it=x1.begin(); it!=x1.end(); ++it)
std::cout << ' ' << *it;
//output: 20,80,180,320,500
return 0;
}
The above code will multiply x1 and x2 elementwise and return (20,80,180,320,500).
However, if i want to calculate x1 $\dot$ x2 + c, where c is a scalar constant such as 1, like the function below:
double multiply(double x, double y, double c){
return x*y + c;
}
In this case, how can i use std::transform to apply on two vectors x1 and x2? do i have to make the scalar constant c to become a vector with the same elements like (c,c,c...c)?
Thanks in advance.
Try this
int c = 20;
std::transform (x1.begin(), x1.end(), x2.begin(), x1.begin(),[&c](auto i, auto j) { return multiply(i,j) + c ; });
It is lambda function; i is the element from x1, j is element from x2. [&] signalizing capturing all values defined outside the lambda by reference.
You do this by supplying a functor, i.e. a struct that has a call operator that does what you want. The old way to do this would be to do something like this:
struct MultWithConstantAdder {
const double adder;
MultWithConstantAdder(double adder): adder(adder) {}
double operator()(double x, double y) { return add(x,y,adder); }
};
// ... rest of your code
std::transform(x1.begin(), x2.end(), x2.begin(), x1.begin(), MultWithConstantAdder(someConstantThatYouWant));
C++11 adds lambdas which let you do this in place without having to define a struct in some other part of the code:
std::transform(x1.begin(), x2.end(), x2.begin(), x1.begin(),
[](double x, double y) { return add(x,y, someConstant); });
The syntax might look a bit funky if you're not used to it, but this basically does the same thing as the thing above.
The []
part in the lambda determines what parts of the outer scope (i.e. everything that's not in the lambda itself) should be visible. []
means nothing, [=]
means everything copied by value, and [&]
means everything visible by reference. You can also just name things directly, so for example [someConstant, &someOtherConstant]
would capture someConstant
by value and someOtherConstant
by reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With