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 tmp.cc -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,

Mark