diff --git a/include/boost/numeric/ublas/exception.hpp b/include/boost/numeric/ublas/exception.hpp index 90f32e41..f9eb8140 100644 --- a/include/boost/numeric/ublas/exception.hpp +++ b/include/boost/numeric/ublas/exception.hpp @@ -267,11 +267,19 @@ namespace boost { namespace numeric { namespace ublas { // return (std::min) (size1, size2); // } // #define BOOST_UBLAS_SAME(size1, size2) same_impl ((size1), (size2)) - template + // need two types here because different containers can have + // different size_types (especially sparse types) + template BOOST_UBLAS_INLINE // Kresimir Fresl and Dan Muller reported problems with COMO. // We better change the signature instead of libcomo ;-) // const T &same_impl_ex (const T &size1, const T &size2, const char *file, int line) { + T1 same_impl_ex (const T1 &size1, const T2 &size2, const char *file, int line) { + BOOST_UBLAS_CHECK_EX (size1 == size2, file, line, bad_argument ()); + return (size1 < size2)?(size1):(size2); + } + template + BOOST_UBLAS_INLINE T same_impl_ex (const T &size1, const T &size2, const char *file, int line) { BOOST_UBLAS_CHECK_EX (size1 == size2, file, line, bad_argument ()); return (std::min) (size1, size2); diff --git a/include/boost/numeric/ublas/matrix.hpp b/include/boost/numeric/ublas/matrix.hpp index 9b08c8d7..306c7a5a 100644 --- a/include/boost/numeric/ublas/matrix.hpp +++ b/include/boost/numeric/ublas/matrix.hpp @@ -97,6 +97,10 @@ namespace boost { namespace numeric { namespace ublas { matrix_container (), size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2)) { } + matrix (size_type size1, size_type size2, const value_type &init): + matrix_container (), + size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2), init) { + } BOOST_UBLAS_INLINE matrix (size_type size1, size_type size2, const array_type &data): matrix_container (), diff --git a/include/boost/numeric/ublas/storage.hpp b/include/boost/numeric/ublas/storage.hpp index 95b47ca7..02ebf95d 100644 --- a/include/boost/numeric/ublas/storage.hpp +++ b/include/boost/numeric/ublas/storage.hpp @@ -23,6 +23,7 @@ #endif #include +#include #include @@ -63,19 +64,15 @@ namespace boost { namespace numeric { namespace ublas { explicit BOOST_UBLAS_INLINE unbounded_array (size_type size, const ALLOC &a = ALLOC()): alloc_(a), size_ (size) { - if (size_) { - data_ = alloc_.allocate (size_); - // ISSUE some compilers may zero POD here -#ifdef BOOST_UBLAS_USEFUL_ARRAY_PLACEMENT_NEW - // array form fails on some compilers due to size cookie, is it standard conforming? - new (data_) value_type[size_]; -#else - for (pointer d = data_; d != data_ + size_; ++d) - new (d) value_type; -#endif - } - else - data_ = 0; + if (size_) { + data_ = alloc_.allocate (size_); + if (not detail::has_trivial_constructor::value) { + for (pointer d = data_; d != data_ + size_; ++d) + alloc_.construct(d, value_type()); + } + } + else + data_ = 0; } // No value initialised, but still be default constructed BOOST_UBLAS_INLINE @@ -101,9 +98,12 @@ namespace boost { namespace numeric { namespace ublas { BOOST_UBLAS_INLINE ~unbounded_array () { if (size_) { - const iterator i_end = end(); - for (iterator i = begin (); i != i_end; ++i) { - iterator_destroy (i); + if (not detail::has_trivial_destructor::value) { + // std::_Destroy (begin(), end(), alloc_); + const iterator i_end = end(); + for (iterator i = begin (); i != i_end; ++i) { + iterator_destroy (i); + } } alloc_.deallocate (data_, size_); } @@ -137,20 +137,18 @@ namespace boost { namespace numeric { namespace ublas { } } else { - // ISSUE some compilers may zero POD here -#ifdef BOOST_UBLAS_USEFUL_ARRAY_PLACEMENT_NEW - // array form fails on some compilers due to size cookie, is it standard conforming? - new (data_) value_type[size]; -#else - for (pointer di = data_; di != data_ + size; ++di) - new (di) value_type; -#endif + if (not detail::has_trivial_constructor::value) { + for (pointer di = data_; di != data_ + size; ++di) + alloc_.construct (di, value_type()); + } } } if (size_) { - for (pointer si = p_data; si != p_data + size_; ++si) - alloc_.destroy (si); + if (not detail::has_trivial_destructor::value) { + for (pointer si = p_data; si != p_data + size_; ++si) + alloc_.destroy (si); + } alloc_.deallocate (p_data, size_); } diff --git a/include/boost/numeric/ublas/traits.hpp b/include/boost/numeric/ublas/traits.hpp index d3b3caad..d1b1cf06 100644 --- a/include/boost/numeric/ublas/traits.hpp +++ b/include/boost/numeric/ublas/traits.hpp @@ -25,6 +25,8 @@ #include #include +#include +#include namespace boost { namespace numeric { namespace ublas { @@ -485,6 +487,24 @@ namespace boost { namespace numeric { namespace ublas { it = it_end; } + namespace detail { + + // specialisation which define whether a type has a trivial constructor + // or not. This is used by array types. + template + struct has_trivial_constructor : public boost::has_trivial_constructor {}; + + template + struct has_trivial_destructor : public boost::has_trivial_destructor {}; + + template + struct has_trivial_constructor > : public boost::true_type {}; + + template + struct has_trivial_destructor > : public boost::true_type {}; + + } + }}} #endif diff --git a/include/boost/numeric/ublas/vector.hpp b/include/boost/numeric/ublas/vector.hpp index b47fe138..072efa8f 100644 --- a/include/boost/numeric/ublas/vector.hpp +++ b/include/boost/numeric/ublas/vector.hpp @@ -63,6 +63,10 @@ namespace boost { namespace numeric { namespace ublas { vector_container (), data_ (data) {} BOOST_UBLAS_INLINE + vector (size_type size, const value_type &init): + vector_container (), + data_ (size, init) {} + BOOST_UBLAS_INLINE vector (const vector &v): vector_container (), data_ (v.data_) {}