From eef17a00ab7991c310240ed4eec4196c38e8c528 Mon Sep 17 00:00:00 2001 From: Michael Stevens Date: Sun, 16 Apr 2006 09:26:15 +0000 Subject: [PATCH] Reintroduced _array_adaptor needs testing [SVN r33708] --- include/boost/numeric/ublas/storage.hpp | 319 ++++++++++++++++++++---- 1 file changed, 275 insertions(+), 44 deletions(-) diff --git a/include/boost/numeric/ublas/storage.hpp b/include/boost/numeric/ublas/storage.hpp index 9c07c288..54bf2274 100644 --- a/include/boost/numeric/ublas/storage.hpp +++ b/include/boost/numeric/ublas/storage.hpp @@ -18,6 +18,9 @@ #define BOOST_UBLAS_STORAGE_H #include +#ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR +#include +#endif #include #include @@ -435,13 +438,12 @@ namespace boost { namespace numeric { namespace ublas { }; - // C Array adaptor - // As the element storage must be fixed to a C array this class cannot be copy constructed + // Array adaptor with normal deep copy semantics of elements template - class carray_adaptor: - public storage_array > { + class array_adaptor: + public storage_array > { - typedef carray_adaptor self_type; + typedef array_adaptor self_type; public: typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; @@ -453,60 +455,86 @@ namespace boost { namespace numeric { namespace ublas { // Construction and destruction BOOST_UBLAS_INLINE - carray_adaptor (): - size_ (0), data_ (0) { + array_adaptor (): + size_ (0), own_ (true), data_ (new value_type [0]) { + } + explicit BOOST_UBLAS_INLINE + array_adaptor (size_type size): + size_ (size), own_ (true), data_ (new value_type [size]) { } BOOST_UBLAS_INLINE - carray_adaptor (size_type size, pointer data): - size_ (size), data_ (data) {} - BOOST_UBLAS_INLINE - carray_adaptor (size_type size, pointer data, const value_type &init): - size_ (size), data_ (data) { - std::fill (begin(), end(), init) ; + array_adaptor (size_type size, const value_type &init): + size_ (size), own_ (true), data_ (new value_type [size]) { + std::fill (data_, data_ + size_, init); } BOOST_UBLAS_INLINE - ~carray_adaptor () { + array_adaptor (size_type size, pointer data): + size_ (size), own_ (false), data_ (data) {} + BOOST_UBLAS_INLINE + array_adaptor (const array_adaptor &a): + storage_array (), + size_ (a.size_), own_ (true), data_ (new value_type [a.size_]) { + *this = a; + } + BOOST_UBLAS_INLINE + ~array_adaptor () { + if (own_) { + delete [] data_; + } } - // No copy constructor - private: - carray_adaptor (const carray_adaptor& ); - - public: // Resizing + private: + BOOST_UBLAS_INLINE + void resize_internal (size_type size, value_type init, bool preserve = true) { + if (size != size_) { + pointer data = new value_type [size]; + if (preserve) { + std::copy (data_, data_ + (std::min) (size, size_), data); + std::fill (data + (std::min) (size, size_), data + size, init); + } + if (own_) + delete [] data_; + size_ = size; + own_ = true; + data_ = data; + } + } + BOOST_UBLAS_INLINE + void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) { + if (data != data_) { + if (preserve) { + std::copy (data_, data_ + (std::min) (size, size_), data); + std::fill (data + (std::min) (size, size_), data + size, init); + } + if (own_) + delete [] data_; + own_ = false; + data_ = data; + } + else { + std::fill (data + (std::min) (size, size_), data + size, init); + } + size_ = size; + } + public: BOOST_UBLAS_INLINE void resize (size_type size) { - size_ = size; + resize_internal (size, value_type (), false); } BOOST_UBLAS_INLINE void resize (size_type size, value_type init) { - std::fill (data_ + size_, data_ + size, init); - size_ = size; + resize_internal (size, init, true); } BOOST_UBLAS_INLINE void resize (size_type size, pointer data) { - size_ = size; - data_ = data; + resize_internal (size, data, value_type (), false); } BOOST_UBLAS_INLINE void resize (size_type size, pointer data, value_type init) { - std::copy (data_, data_ + std::min (size_, size), data); - std::fill (data_ + size_, data_ + size, init); - size_ = size; - data_ = data; + resize_internal (size, data, init, true); } - // Random Access Container - BOOST_UBLAS_INLINE - size_type max_size () const { - return std::numeric_limits::max (); - } - - BOOST_UBLAS_INLINE - bool empty () const { - return size_ == 0; - } - BOOST_UBLAS_INLINE size_type size () const { return size_; @@ -526,7 +554,7 @@ namespace boost { namespace numeric { namespace ublas { // Assignment BOOST_UBLAS_INLINE - carray_adaptor &operator = (const carray_adaptor &a) { + array_adaptor &operator = (const array_adaptor &a) { if (this != &a) { resize (a.size_); std::copy (a.data_, a.data_ + a.size_, data_); @@ -534,21 +562,25 @@ namespace boost { namespace numeric { namespace ublas { return *this; } BOOST_UBLAS_INLINE - carray_adaptor &assign_temporary (carray_adaptor &a) { - *this = a; + array_adaptor &assign_temporary (array_adaptor &a) { + if (own_ && a.own_) + swap (a); + else + *this = a; return *this; } // Swapping BOOST_UBLAS_INLINE - void swap (carray_adaptor &a) { + void swap (array_adaptor &a) { if (this != &a) { std::swap (size_, a.size_); + std::swap (own_, a.own_); std::swap (data_, a.data_); } } BOOST_UBLAS_INLINE - friend void swap (carray_adaptor &a1, carray_adaptor &a2) { + friend void swap (array_adaptor &a1, array_adaptor &a2) { a1.swap (a2); } @@ -599,9 +631,208 @@ namespace boost { namespace numeric { namespace ublas { private: size_type size_; + bool own_; pointer data_; }; +#ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR + // Array adaptor with shallow (reference) copy semantics of elements. + // shared_array is used to maintain reference counts. + // This class breaks the normal copy semantics for a storage container and is very dangerous! + template + class shallow_array_adaptor: + public storage_array > { + + typedef shallow_array_adaptor self_type; + + template + struct leaker { + typedef void result_type; + typedef TT *argument_type; + + BOOST_UBLAS_INLINE + result_type operator () (argument_type x) {} + }; + + public: + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T value_type; + typedef const T &const_reference; + typedef T &reference; + typedef const T *const_pointer; + typedef T *pointer; + + // Construction and destruction + BOOST_UBLAS_INLINE + shallow_array_adaptor (): + size_ (0), own_ (true), data_ (new value_type [0]) { + } + explicit BOOST_UBLAS_INLINE + shallow_array_adaptor (size_type size): + size_ (size), own_ (true), data_ (new value_type [size]) { + } + BOOST_UBLAS_INLINE + shallow_array_adaptor (size_type size, const value_type &init): + size_ (size), own_ (true), data_ (new value_type [size]) { + std::fill (data_.get (), data_.get () + size_, init); + } + BOOST_UBLAS_INLINE + shallow_array_adaptor (size_type size, pointer data): + size_ (size), own_ (false), data_ (data, leaker ()) {} + + BOOST_UBLAS_INLINE + shallow_array_adaptor (const shallow_array_adaptor &a): + storage_array (), + size_ (a.size_), own_ (a.own_), data_ (a.data_) {} + + BOOST_UBLAS_INLINE + ~shallow_array_adaptor () { + } + + // Resizing + private: + BOOST_UBLAS_INLINE + void resize_internal (size_type size, value_type init, bool preserve = true) { + if (size != size_) { + shared_array data (new value_type [size]); + if (preserve) { + std::copy (data_.get (), data_.get () + (std::min) (size, size_), data.get ()); + std::fill (data.get () + (std::min) (size, size_), data.get () + size, init); + } + size_ = size; + data_ = data; + } + } + BOOST_UBLAS_INLINE + void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) { + if (preserve) { + std::copy (data_.get (), data_.get () + (std::min) (size, size_), data); + std::fill (data + (std::min) (size, size_), data + size, init); + } + size_ = size; + data_ = data; + } + public: + BOOST_UBLAS_INLINE + void resize (size_type size) { + resize_internal (size, value_type (), false); + } + BOOST_UBLAS_INLINE + void resize (size_type size, value_type init) { + resize_internal (size, init, true); + } + BOOST_UBLAS_INLINE + void resize (size_type size, pointer data) { + resize_internal (size, data, value_type (), false); + } + BOOST_UBLAS_INLINE + void resize (size_type size, pointer data, value_type init) { + resize_internal (size, data, init, true); + } + + BOOST_UBLAS_INLINE + size_type size () const { + return size_; + } + + // Element access + BOOST_UBLAS_INLINE + const_reference operator [] (size_type i) const { + BOOST_UBLAS_CHECK (i < size_, bad_index ()); + return data_ [i]; + } + BOOST_UBLAS_INLINE + reference operator [] (size_type i) { + BOOST_UBLAS_CHECK (i < size_, bad_index ()); + return data_ [i]; + } + + // Assignment + BOOST_UBLAS_INLINE + shallow_array_adaptor &operator = (const shallow_array_adaptor &a) { + if (this != &a) { + resize (a.size_); + std::copy (a.data_.get (), a.data_.get () + a.size_, data_.get ()); + } + return *this; + } + BOOST_UBLAS_INLINE + shallow_array_adaptor &assign_temporary (shallow_array_adaptor &a) { + if (own_ && a.own_) + swap (a); + else + *this = a; + return *this; + } + + // 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_); + } + } + BOOST_UBLAS_INLINE + friend void swap (shallow_array_adaptor &a1, shallow_array_adaptor &a2) { + a1.swap (a2); + } + + // Iterators simply are pointers. + + typedef const_pointer const_iterator; + + BOOST_UBLAS_INLINE + const_iterator begin () const { + return data_.get (); + } + BOOST_UBLAS_INLINE + const_iterator end () const { + return data_.get () + size_; + } + + typedef pointer iterator; + + BOOST_UBLAS_INLINE + iterator begin () { + return data_.get (); + } + BOOST_UBLAS_INLINE + iterator end () { + return data_.get () + size_; + } + + // Reverse iterators + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + BOOST_UBLAS_INLINE + const_reverse_iterator rbegin () const { + return const_reverse_iterator (end ()); + } + BOOST_UBLAS_INLINE + const_reverse_iterator rend () const { + return const_reverse_iterator (begin ()); + } + BOOST_UBLAS_INLINE + reverse_iterator rbegin () { + return reverse_iterator (end ()); + } + BOOST_UBLAS_INLINE + reverse_iterator rend () { + return reverse_iterator (begin ()); + } + + private: + size_type size_; + bool own_; + shared_array data_; + }; + +#endif + // Range class template