views:

204

answers:

3

Hi,

I'd like to calculate the square and square-root of a vector of doubles. For example given:

 vector<double> Array1(10,2.0); 
 vector<double> Array2(10,2.0); 

 for(unsigned int i=0; i<Array1.size(); i++)
     Array1[i] = sqrt(Array1[i]);

 for(unsigned int i=0; i<Array2.size(); i++)
     Array2[i] = Array2[i] * Array2[i]; 

Is there a way of doing the above using a STL function such as transform? Perhaps there is an in-built sqrt function that acts on arrays?

+5  A: 

Same answer as your previous question...

static inline double computeSquare (double x) { return x*x; }

...

std::transform(Array1.begin(), Array1.end(), Array1.begin(), (double(*)(double)) sqrt);
std::transform(Array2.begin(), Array2.end(), Array2.begin(), computeSquare);

(The (double(*)(double)) cast is to force the sqrt function to use the double variant — it's an overloaded function. You could use std::ptr_fun<double, double>(sqrt) to avoid the cast.)

KennyTM
Aside question: does `ptr_fun(sqrt<double>)` portably work instead of the ugly cast ? I recall compilers often choke on pointers to `<cmath>` overloaded functions.
Alexandre C.
@Alex: `std::ptr_fun<double, double>(sqrt)`, but I don't think it's much prettier.
KennyTM
@KennyTM: There is no template deduction if we use `sqrt<double>` ?
Alexandre C.
@Alex: `error: no matching function for call to ‘ptr_fun(<unresolved overloaded function type>)’`. (`sqrt` is overloaded, not templated. I don't even think `sqrt<double>` is valid.)
KennyTM
+2  A: 

I think the second transform can be simplified, I'm just not sure how.

#include <algorithm>
using namespace std;

vector<double> Array1(10,2.0); 
vector<double> Array2(10,2.0); 

transform( Array1.begin(), Array1.end(), Array1.begin(), sqrt );
transform( Array2.begin(), Array2.end(), Array2.begin(), Array2.begin(), multiplies<double>() );
genpfault
I think the 2nd `transform` is simple enough.
KennyTM
+2  A: 

If your compiler has C++0x support, KennyTM's answer can be tweaked a little:

std::transform(Array1.begin(), Array1.end(), Array1.begin(), [](double f)->double { return f * f; });

Or if you're using Boost, you can use Boost::lambda:

#include <boost/lambda.hpp>
using namespace boost::lambda;

std::transform(Array1.begin(), Array1.end(), Array1.begin(), _1 * _1);
greyfade