Returning vectors or matrices from user functions

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Returning vectors or matrices from user functions

Mark Johnson-32
Thanks Jesse for your helpful advice with this.  The Curiously Recurring
Template Pattern is very clever!

I also have two further questions -- what types should one use in user
functions that will either return a vector or a matrix, and what types
should one use for arguments to functions that will mutate a vector or
matrix in place?

For function return values, the main issue is how to specify the return
type to avoid needless copying, I think.  Would it be reasonable to
return a vector_expression or a const vector_expression, for example?  I
think this would be safe if these referred to vectors or matrices that
are instantiated in the function call.  But perhaps it's also possible
that a modern compiler would optimize away the unnecessary copy
operations even if one returns ordinary vectors or matrices?

For function arguments that will be modified in place, I think the issue
is whether there is a way to define the types so that non-const vector
expressions can be conveniently passed to the function.

To give an artificially simple example, suppose I need to normalize each
row in a matrix m (i.e., scale the entries so that the sum of the values
in each row is one).  One way to do this is to write a "my_normalize"
function that operates on a single vector, and then call that function
on each row of the matrix m, i.e., my_normalize(row(m, i)).

But this generates compiler errors if my_normalize takes a non-const
reference argument,  as I'm trying to pass a non-const reference to the
temporary vector proxy (i.e., the object returned by row(m,i)).  Again,
I'm not sure what the best thing to do here is.  Perhaps I should pass
the argument to my_normalize by value?  But then if I call my_normalize
with a regular vector as its argument, then it makes a copy of its
argument and therefore fails to mutate that argument.

Thanks again for you help,

Mark
_______________________________________________
ublas mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/ublas
Sent to: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Returning vectors or matrices from user functions

Gunter Winkler
Hello Mark,

I think I can answer some of your questions

Mark Johnson schrieb:
> Thanks Jesse for your helpful advice with this.  The Curiously
> Recurring Template Pattern is very clever!
Yes, but please keep in mind to always pass matirx/vector expressions as
(const) references. The const correctness also influences the performance.

>
> I also have two further questions -- what types should one use in user
> functions that will either return a vector or a matrix, and what types
> should one use for arguments to functions that will mutate a vector or
> matrix in place?
In this case you can always return the vector/matrix by value. If you do
not want to rely on the compiler to remove temporaries in the following code

matrix<double> A( generate_matrix_A(...) );
// or
matrix<double> A =  generate_matrix_A(...) ;

the you can explicitly call assign_temporary( rhs ), e.g. like

matrix<double> A(0,0);
A.assign_temporary( generate_matrix_A(...) );


if you want to modify the value then you simple use a non-const
reference to a matrix_expression, e.g.,

template < class E >
void fill_matrix(matrix_expression<E> & me) {
  E & matrix = me();
  // do something with matrix
}
>
> For function return values, the main issue is how to specify the
> return type to avoid needless copying, I think.  Would it be
> reasonable to return a vector_expression or a const vector_expression,
> for example?  I think this would be safe if these referred to vectors
> or matrices that are instantiated in the function call.  But perhaps
> it's also possible that a modern compiler would optimize away the
> unnecessary copy operations even if one returns ordinary vectors or
> matrices?
g++ 4 is quite smart on optimizing the construction. However you have
always the option to write a custom expression similar to the
expressions generated by trans(), prod(), operator+ ... You should not
return matrix_expressions by value. At least I had some strange issues here.
>
> For function arguments that will be modified in place, I think the
> issue is whether there is a way to define the types so that non-const
> vector expressions can be conveniently passed to the function.
this is no problem: the free function project() is very handy here:

t = norm_1( project( const_vec, range(0,5) ) );
project( vec, range(0,5) ) = scalar_vector<double>(5.1.0);
// even better
noalias( project( vec, range(0,5) ) ) = scalar_vector<double>(5.1.0);

>
> To give an artificially simple example, suppose I need to normalize
> each row in a matrix m (i.e., scale the entries so that the sum of the
> values in each row is one).  One way to do this is to write a
> "my_normalize" function that operates on a single vector, and then
> call that function on each row of the matrix m, i.e.,
> my_normalize(row(m, i)).
>
can you paste a few lines of code?

mfg
Gunter
_______________________________________________
ublas mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/ublas
Sent to: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Returning vectors or matrices from user functions

Mark Johnson-33
In reply to this post by Mark Johnson-32
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



_______________________________________________
ublas mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/ublas
Sent to: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Returning vectors or matrices from user functions

Mark Johnson-32
In reply to this post by Mark Johnson-32
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




_______________________________________________
ublas mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/ublas
Sent to: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Returning vectors or matrices from user functions

sanann
In reply to this post by Mark Johnson-33
hello,
I am trying to return a array of matrices from a function but when i use
return there is always an error can you please help me.


typedef boost::numeric::ublas::matrix<double> BMT;

     BMT fun();
       {
       BMT mym;
       mym.resize(3,3);
       for(int i = 0; i<9;++i) mym(i/3,i%3)=i;
       std::cout << mym << std::endl;
       return mym;
       }
error: cannot convert 'BMT {aka boost::numeric::ublas::matrix<double>}' to
'int' in return
        return mym;
               ^

why do i get this error how do i overcome it.