Boost logo

Ublas :

Subject: [ublas] Returning matrices, non-const references to matrix_expressions and matrix_reference
From: Miguel Ramos (miguel_at_[hidden])
Date: 2010-04-12 07:01:02


I've been using ublas for the past four years or so, and I still can't make up
my mind on how to return matrices from generic functions.
My examples bellow are from the field I work on, which is computer graphics and
3d euclidean geometry.

In summary, the issue is, whenever I want a generic function to have a matrix
argument, I know I can use matrix_expression<E> const&; however, whenever I
want a generic function to output a matrix, I never have a very good solution,
let alone one that is good for all cases.

Suppose a function which receives no matrix as input and computes a matrix,
say one which computes a rotation matrix on one of the basis axis.
If I declare it as:

template < class T >
matrix<T> rotation_matrix(std::size_t axis, T angle);

This is not good, because:
- I'm forcing the caller on a specific return type. For instance, the caller
might know a c_matrix and some other floating-point type would be better for
this, or that he wanted a matrix represented in column-major order.

In this case, I resort to letting the caller pass the output matrix as a
parameter, as this:

template < class T, class M >
M& rotation_matrix(std::size_t axis, T angle, M& output_matrix);

But this approach has this disadvantages:
- Imposes an awkward syntax on the caller.
- It does not restrict the type of the third parameter. If the user happens to
pass a vector for the third parameter, he'll have a hard time reading the
compiler output and my function to understand what was the error.

Can matrix_reference help here (on restricting the type of the third
parameter) ? What is matrix_reference for, anyway ?

Another possibility is something like:

template < class M, class T >
M rotation_matrix(std::size_t axis, T angle);

- But this forces the caller to specify the return type as a template argument
even when he doesn't really care.
- Also, it doesn't restrict the return type...
- Furthermore I can't overload this version of the function with the first one,
or give the template argument for the return type a default value, which would
allow the user to specify the return type only if he cared.

Suppose a function which computes the inverse of a matrix.
In this case, it does make sense that the type of the input matrix determines
the type of the output matrix (if the input.

template < class M > M inverse(M const& m);

However, declaring it like this also has disadvantages:
- Again, the type of the argument is not restricted by the declaration to be a
matrix (ok, maybe another library such as concept_check may help here).
- I disallow passing a matrix_expression as an argument.

Suppose a function which computes the covariance. It will take a big matrix
for input, which I'll typically want to be a ublas::matrix, and it will return
a small matrix for output, which I'll typically want to be a c_matrix.

The possibilities are similar, pass the output matrix as an argument, which
has awkward syntax, force the type of the output matrix upon the caller or
force the caller to always specify return type as template argument.

I think some of those issues have no solution.
So, my questions are these:
- Are there any other good ways of returning matrices from generic functions?
- Is matrix_reference<T> suitable to restricting the type of output arguments
to be a matrix? What is it really meant for?

Please comment if you see better solutions for the examples I gave.

Miguel Ramos <miguel_at_[hidden]>
PGP A006A14C