Boost logo

Ublas :

Subject: Re: [ublas] Returning vectors or matrices from user functions
From: Mark Johnson (mj1_at_[hidden])
Date: 2009-09-09 19:04:38

Thanks Gunter for your helpful suggestions.

You asked for a code fragment demonstrating the problem I was describing
about passing arguments to user functions that will mutate those arguments.

This fragment initializes a matrix a, and then calls normalize_row() on
each of its rows to scale their values so they sum to 1.

template<typename V>
void normalize_row(V& v) {
   v /= sum(v);

int main(int argc, char** argv) {
boost::numeric::ublas::matrix<float> a(2,2);
   a(0,0) = 1; a(0,1) = 4; a(1,0) = 2; a(1,1) = 2;
   std::cout<< "initial a = "<< a<< std::endl;

   // verbose fragment that uses explicit temporary
   for (unsigned i = 0; i< a.size1(); ++i) {
     auto r = row(a,i); // save row in temporary
     normalize_row(r); // normalize row
   std::cout<< "row normalized a = "<< a<< std::endl;

g++ -std=c++0x -o tmp; tmp
initial a = [2,2]((1,4),(2,2))
row normalized a = [2,2]((0.2,0.8),(0.5,0.5))

However, I'd prefer to write the last loop in the program as something
like this:

   for (unsigned i = 0; i< a.size1(); ++i)
     normalize_row(row(a,i)); // extract and normalize row

Unfortunately this fails to compile because the temporary constructed by
row() can't be passed as a non-const reference.

The new auto type capabilities of C++0x certainly make it easier to
store each row in an explicit temporary variable, but it would be
clearer not to use an explicit variable here at all.

Thanks in advance,