# Boost :

From: Kresimir Fresl (fresl_at_[hidden])
Date: 2002-05-06 17:33:24

Joerg Walter wrote:

> But Toon is right, if he mentions, that
> ublas clear() doesn't have the same semantics as STL clear(). Shouldn't we
> better use the name zeroize() instead of clear()?

Ha! You have finally opened the Pandora's box ;o)

Let's see one small example:

==========================================
typedef numerics::vector<double> uvector;
typedef
numerics::vector< double, numerics::bounded_array<double, 16> > bvector;
typedef numerics::vector< double, std::vector<double> > svector;

int main() {

uvector uv (8);
bvector bv (8);
svector sv (8);
for (int i = 0; i < 8; ++i)
uv[i] = bv[i] = sv[i] = i+1;
cout << endl << "original:\n" << "uv: " << uv << endl;
cout << "bv: " << bv << endl;
cout << "sv: " << sv << endl;

uv.insert (4, 100);
bv.insert (4, 100);
sv.insert (4, 100);
cout << endl << "after insert():\n" << "uv: " << uv << endl;
cout << "bv: " << bv << endl;
cout << "sv: " << sv << endl;

uv.erase (4);
bv.erase (4);
sv.erase (4);
cout << endl << "after erase():\n" << "uv: " << uv << endl;
cout << "bv: " << bv << endl;
cout << "sv: " << sv << endl;

uv.resize (12);
bv.resize (12);
sv.resize (12);
cout << endl << "after resize():\n" << "uv: " << uv << endl;
cout << "bv: " << bv << endl;
cout << "sv: " << sv << endl << endl;

}
=========================================

The output is:

=========================================
original:
uv: [8](1,2,3,4,5,6,7,8)
bv: [8](1,2,3,4,5,6,7,8)
sv: [8](1,2,3,4,5,6,7,8)

after insert():
uv: [8](1,2,3,4,100,6,7,8)
bv: [8](1,2,3,4,100,6,7,8)
sv: [8](1,2,3,4,100,5,6,7)

after erase():
uv: [8](1,2,3,4,0,6,7,8)
bv: [8](1,2,3,4,0,6,7,8)
sv: [8](1,2,3,4,5,6,7,8)

after resize():
uv: [12](0,0,0,0,0,0,0,0,0,0,0,0)
bv: [12](1,2,3,4,0,6,7,8,4.85584e-270,4.92833e-270,2.81476,2.09812)
sv: [12](1,2,3,4,5,6,7,8,0,0,0,0)
==========================================

The behaviour of ublas::vector<>, when insert(), erase() or
resize() are called, depends on array_type, because
these functions call array_type's functions with same
names. And those have different semantics.

On the other hand, behaviour of clear() is always the
same, because ublas::vector<>::clear() does not
call array_type::clear() but std::fill().

This is rather confusing: behaviour of some functions
depends on underlying array_type and is the same
as corresponding array_type's function, while behaviour
of some other functions doesn't depend and is *different*
from the corresponding array_type's function.

I don't think that renaming is the cure.

ublas::vector<> should be regarded as adaptor/decorator
which adds linear algebra functionality to underlying `array_type'
(of course, this should be clearly and loudly stated in documentation)
and it should not change the behaviour of array_type's functions
with same names.

Concretely, ublas::vector<>::clear() should call
array_type::clear(), whatever it does.

Problem that results in current version of ublas::vector<>::clear()
was (thread `ublas & custom containers (2)'):

>> If a sparse matrix result is assigned to a dense matrix,
>> the assignment operation should be dispatched to
>> the sparse matrix logic: clear the dense matrix and insert
>> the rhs elements at the corresponding positions.
[...]
> `numerics::vector_assign<>::operator()' with `sparse_tag'
> uses `array_type::clear()' to clear `numerics::vector<>'
> before assignement, that is, before the call to
> `array_type::insert()'. But the behaviour and semantics of
> `numerics::unbounded_array<>::clear()' and
> from the behaviour of `std::vector<>::clear()'.
> First two simply assign `0' to all elements. But
> `std::vector<>::clear()' really clears the vector,
> ie. it *removes* all elements

I proposed to call std::fill (v.begin(), v.end(), value_type());
in vector_assign<>::operator() (vct_t v, vct_expr, sparse_tag)
instead of ublas::vector::clear(). Joerg put std::fill() in

At that time I didn't see any reason to object, but now I think
that my proposal should be reconsidered.

Sincerely,

fres

PS. It should be noted that semantics of std::valarray<>::resize()
is different from std::vector<>::resize():

==========================================
std::vector<double> vct (4);
std::valarray<double> va (4);
for (int i = 0; i < 4; ++i)
vct[i] = va[i] = i;

vct.resize (6, 100);
va.resize (6, 100);

for (int i = 0; i < 6; ++i)
std::cout << vct[i] << " " << va[i] << "\n";
===========================================

Output is:

0 100
1 100
2 100
3 100
100 100
100 100