Boost logo

Ublas :

Subject: [ublas] Getting elementwise transformations of vectors/matrices to work...
From: Oswin Krause (Oswin.Krause_at_[hidden])
Date: 2012-03-24 12:47:06

Hi List,

A while ago, I wrote a mail about vector_unary not giving correct
results with sparse arguments, when the functor doesnt have the property
f(0) = 0.
Also there was a not so recent mail from someone complaining that you
couldn't use arbitrary function objects for the matrix expressions.

So I decided to try to fix both of the problems at the same time.
Unfortunately I couldn't solve it completely and while it is working, it
is certainly not perfect. But maybe some of you ublas pros can give me
some advice/tips to further improve? I would be happy to release a
cleaned up version later under some more freely available license than
GPL afterwards.

(I link to my project repository out of lazyness, this is not intended
to be advertising in any way...)
here is the code:

So there are two important classes here:
VectorUnaryTransformation which replaces usage of vector_unary,
vector_binary_scalar1 and vector_binary_scalar2

MatrixUnaryTransformation does the job of matrix_unary1
matrix_unary_scalar1 and matrix_unary_scalar2

At the end both are generalized using a class called
UnaryTransformation which allows me to generate a lot of functions for
matrix and vector expressions at the same time, as you might see here:

It works for all functions defined in cmath (also including pow, etc).

I tried to solve the sparse argument problem using a flag in the
functors: if F::zero_identity is true, than f(0) = 0 and everything
works nicely. In the other case i decided to "densify" the expression,
meaning that the iterators iterate over every possible position of the
matrix. However there is now a speed problem, because I couldn't figure
out how to properly iterate over the rows/columns and had to use random
access using indizes. My first approach to implement operator++ for the
iterators didn't work very well:

densifying_const_iterator2& operator ++ () {
     while(m_index2 >= m_iterator2.index2()){//m_iterator2 starts at the
beginning of the row
     return *this;
It seems, that the index of an iterator starts at 0 even though it is a
past the end iterator. (e.g. when the matrix row it references is
Is there some other way to do it? An alternate solution would be to
prevent this situation with a STATIC_ASSERT. At least this wouldn't
break code silently, and calling something like exp(sparse_vector)
doesn't happen very often... (still i would feel a lot better if it
would work)

Oswin Krause