Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane
From: Guillermo Ruiz Troyano <ruiztroyano <at> gmail.com>
Subject: shallow_array_adaptor bug and fixes
Newsgroups: gmane.comp.lib.boost.ublas
Date: Tuesday 28th February 2012 13:10:41 UTC (over 5 years ago)
I'm been trying to use shallow_array_adaptor as storage with ublas::vector
to modify external data. When you try this:

#define BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR
#include 

struct point {
   double x;
   double y;
   double z;
};

void test() {
   using namespace boost::numeric::ublas;

   point p = { 1, 2, 3 }
   shallow_array_adaptor a(3, &p.x);            // Ok, a holds p
address
   vector > v(a); // Ok, v holds p
address
   
   v += v;     // Ok, now p = { 2, 4, 6 }
   v /= 2;     // Ok, now p = { 1, 2, 3 }
   v = v*2;    // <- Oh no, p = { 1, 2, 3 } !!!
}

The bug comes from swap function of shallow_array_adapter that is used by
vector. When you assign v with an expression, this constructs a temporary
and then swaps with it. The issue is that it swaps pointers without check
if both objects own the data:

class shallow_array_adaptor : … {
   ...
   // Swapping
   BOOST_UBLAS_INLINE
   void swap (shallow_array_adaptor &a) {
      if (this != &a) {
         std::swap (size_, a.size_);
         std::swap (own_, a.own_);
         std::swap (data_, a.data_); // This is definitely infidelity
      }
   }
   ...
};

When both are data owners can do that (as unbounded_array does). But if
they are not then it should swap as bounded_array does. Something like
this:

class shallow_array_adaptor : … {
   ...
   // Swapping
   BOOST_UBLAS_INLINE
   void swap (array_adaptor& a) {
      if (own_ && a.own_) {
         if (this != &a) {
            std::swap(size_, a.size_);
            std::swap(own_, a.own_);
            std::swap(data_, a.data_);
         }
      }
      else if (&data_[0] != &a.data_[0])
         std::swap_ranges(data_, data_+size_, a.data_);
   }
   ...
};

Fixing this function I get:

void test() {
   point p = { 1, 2, 3 }
   shallow_array_adaptor a(3, &p.x);            // Ok, a holds p
address
   vector > v(a); // Ok, v holds p
address
   v = v*2;    // <- Ok, now p = { 2, 4, 6 } and v holds p address!
}

Sometimes you need something like shallow_array_adaptor. On the other hand,
array_adaptor is a redundant class that unbounded_array or bounded_array
can do if they have a constructor like this (or with a pair of iterators as
parameters):

unbounded_array(size_t size, T* data)
: size_(size), data_(new value_type[size]) {
   std::copy(data, data+size, data_);
}

I would like to see:
1. A fixed shallow_array_adaptor or a similar storage class that references
external data.
2. unbounded_array and bounded_array constructor that you pass an iterator
range for copy.  adaptor_array is to use a sledgehammer to crack a nut!

Regards,
Guillermo Ruiz Troyano
_______________________________________________
ublas mailing list
[email protected]
http://lists.boost.org/mailman/listinfo.cgi/ublas
Sent to: [email protected]
 
CD: 12ms