Boost logo

Ublas :

From: Vardan Akopian (vakopian_at_[hidden])
Date: 2007-10-21 17:44:35


Hello,

I just stumbled against the inconsistency between operator=() and
assign() one more time (previous thread:
http://lists.boost.org/MailArchives/ublas/2007/09/2360.php ). This
time it's for vector.

The first problem is that the documentation for assign() says:
"Assigns a vector expression to the vector. Left and right hand side
of the assignment should be independent."
There is no mention about any requirements, namely that the sizes of
the vectors should be the same. However this is a requirement in the
code (see e.g. vector_assign.hpp:265).

The second problem is that assign() will behave differently depending
whether NDEBUG is defined or not. When NDEBUG is not defined, the
sizes are checked and an error is thrown in case of mismatch. But with
NDEBUG, assign() will copy as much as there is room in the left hand
side vector. This is especially bad if the left hand side vector is
smaller, since the problem will go unnoticed until much later.
I think, this behavior is against the documentation (no matter if the
requirement above is added or not).

The whole issue is made even more confusing because of the noalias mechanism.
noalias(a) = b
syntactically looks very similar to a = b, but really acts like
a.assign(b), and thus is prone to the confusions described above.

Here is a simple code to see the differences in behavior. Uncomment
one of the assign lines at a time and compile it with and without
NDEBUG.

#include <boost/numeric/ublas/vector.hpp>
#include <iostream>

int main(int argc, char ** argv)
{
    boost::numeric::ublas::vector<double> v1, v2(10);
    //v1 = v2; // 1. ok
    //v1.assign(v2); // 2. confusing
    noalias(v1) = v2; // looks like 1., but acts like 2.
    std::cout << "v1.size=" << v1.size() << ", v2.size=" << v2.size()
<< std::endl;
    return 0;
}

I understand that assign() is there for performance reasons (no
allocations), but I think both the code and documentation needs to be
fixed to reflect what it really does. If we decide that it's ok for
assign() not to behave identically to operator=(), then maybe we
should consider making the size check in assign() mandatory even for
optimized code (how much overhead can one comparison really add
compared to the copy in the loop?).

-Vardan