Index: boost/numeric/ublas/vector.hpp =================================================================== --- boost/numeric/ublas/vector.hpp (revision 64584) +++ boost/numeric/ublas/vector.hpp (working copy) @@ -867,6 +867,80 @@ }; + // -------------------- + // Fixed vector class + // -------------------- + + /// \brief a dense vector of values of type \c T, of fixed size \f$N\f$. + /// A dense vector of values of type \c T, of fixed size \f$N\f$. + /// Elements are constructed by the storage type \c fixed_array, which \b need \b not \b initialise their value. + template + class fixed_vector: + public vector > { + + typedef vector > vector_type; + public: + typedef typename vector_type::size_type size_type; + static const size_type max_size = N; + + // Construction and destruction + BOOST_UBLAS_INLINE + fixed_vector (): + vector_type (N) {} + BOOST_UBLAS_INLINE + fixed_vector (size_type size): + vector_type (size) { BOOST_UBLAS_CHECK (size == N, bad_size ()); } + BOOST_UBLAS_INLINE + fixed_vector (const fixed_vector &v): + vector_type (v) {} + template // Allow vector construction + BOOST_UBLAS_INLINE + fixed_vector (const vector &v): + vector_type (v) {} + template + BOOST_UBLAS_INLINE + fixed_vector (const vector_expression &ae): + vector_type (ae) {} + BOOST_UBLAS_INLINE + ~fixed_vector () {} + + // Assignment +#ifdef BOOST_UBLAS_MOVE_SEMANTICS + + /*! @note "pass by value" the key idea to enable move semantics */ + BOOST_UBLAS_INLINE + fixed_vector &operator = (fixed_vector v) { + vector_type::operator = (v); + return *this; + } +#else + BOOST_UBLAS_INLINE + fixed_vector &operator = (const fixed_vector &v) { + vector_type::operator = (v); + return *this; + } +#endif + template // Generic vector assignment + BOOST_UBLAS_INLINE + fixed_vector &operator = (const vector &v) { + vector_type::operator = (v); + return *this; + } + template // Container assignment without temporary + BOOST_UBLAS_INLINE + fixed_vector &operator = (const vector_container &v) { + vector_type::operator = (v); + return *this; + } + template + BOOST_UBLAS_INLINE + fixed_vector &operator = (const vector_expression &ae) { + vector_type::operator = (ae); + return *this; + } + }; + + // ----------------- // Zero vector class // ----------------- Index: boost/numeric/ublas/storage.hpp =================================================================== --- boost/numeric/ublas/storage.hpp (revision 64584) +++ boost/numeric/ublas/storage.hpp (working copy) @@ -468,6 +468,168 @@ }; + // Fixed array - with allocator for size_type and difference_type + template + class fixed_array: + public storage_array > { + + typedef fixed_array self_type; + public: + // No allocator_type as ALLOC is not used for allocation + typedef typename ALLOC::size_type size_type; + typedef typename ALLOC::difference_type difference_type; + typedef T value_type; + typedef const T &const_reference; + typedef T &reference; + typedef const T *const_pointer; + typedef T *pointer; + typedef const_pointer const_iterator; + typedef pointer iterator; + + // Construction and destruction + BOOST_UBLAS_INLINE + fixed_array () { + } + explicit BOOST_UBLAS_INLINE + fixed_array (size_type size) { + BOOST_UBLAS_CHECK (size == N, bad_size ()); + // data_ (an array) elements are already default constructed + } + BOOST_UBLAS_INLINE + fixed_array (size_type size, const value_type &init) { + BOOST_UBLAS_CHECK (size == N, bad_size ()); + // ISSUE elements should be value constructed here, but we must fill instead as already default constructed + std::fill (begin(), end(), init) ; + } + BOOST_UBLAS_INLINE + fixed_array (const fixed_array &c) { + // ISSUE elements should be copy constructed here, but we must copy instead as already default constructed + std::copy (c.begin(), c.end(), begin()); + } + + // Resizing + BOOST_UBLAS_INLINE + void resize (size_type size) { + BOOST_UBLAS_CHECK (size == N, bad_size ()); + } + BOOST_UBLAS_INLINE + void resize (size_type size, value_type init) { + BOOST_UBLAS_CHECK (size == N, bad_size ()); + } + + // Random Access Container + BOOST_UBLAS_INLINE + size_type max_size () const { + return N; + } + + BOOST_UBLAS_INLINE + bool empty () const { + return N == 0; + } + + BOOST_UBLAS_INLINE + size_type size () const { + return N; + } + + // Element access + BOOST_UBLAS_INLINE + const_reference operator [] (size_type i) const { + BOOST_UBLAS_CHECK (i < N, bad_index ()); + return data_ [i]; + } + BOOST_UBLAS_INLINE + reference operator [] (size_type i) { + BOOST_UBLAS_CHECK (i < N, bad_index ()); + return data_ [i]; + } + + // Assignment + BOOST_UBLAS_INLINE + fixed_array &operator = (const fixed_array &a) { + if (this != &a) { + std::copy (a.data_, a.data_ + N, data_); + } + return *this; + } + BOOST_UBLAS_INLINE + fixed_array &assign_temporary (fixed_array &a) { + *this = a; + return *this; + } + + // Swapping + BOOST_UBLAS_INLINE + void swap (fixed_array &a) { + if (this != &a) { + std::swap_ranges (data_, data_ + N, a.data_); + } + } + BOOST_UBLAS_INLINE + friend void swap (fixed_array &a1, fixed_array &a2) { + a1.swap (a2); + } + + BOOST_UBLAS_INLINE + const_iterator begin () const { + return data_; + } + BOOST_UBLAS_INLINE + const_iterator end () const { + return data_ + N; + } + + BOOST_UBLAS_INLINE + iterator begin () { + return data_; + } + BOOST_UBLAS_INLINE + iterator end () { + return data_ + N; + } + + // 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: + // Serialization + friend class boost::serialization::access; + + template + void serialize(Archive & ar, const unsigned int version) + { + serialization::collection_size_type s(N); + ar & serialization::make_nvp("size", s); + if ( Archive::is_loading::value ) { + if (s != N) bad_size("wrong size in fixed_array::load()\n").raise(); + } + ar & serialization::make_array(data_, s); + } + + private: + BOOST_UBLAS_FIXED_ARRAY_ALIGN value_type data_ [N]; + }; + + // Array adaptor with normal deep copy semantics of elements template class array_adaptor: Index: boost/numeric/ublas/matrix.hpp =================================================================== --- boost/numeric/ublas/matrix.hpp (revision 64584) +++ boost/numeric/ublas/matrix.hpp (working copy) @@ -72,6 +72,81 @@ } } + template + class matrix_size_dynamic + { + public: + typedef Z size_type; + + BOOST_UBLAS_INLINE + matrix_size_dynamic (): + size1_ (0), size2_ (0) {} + BOOST_UBLAS_INLINE + matrix_size_dynamic (size_type size1, size_type size2): + size1_ (size1), size2_ (size2) {} + + // Accessors + BOOST_UBLAS_INLINE + size_type size1 () const { + return size1_; + } + BOOST_UBLAS_INLINE + size_type size2 () const { + return size2_; + } + + BOOST_UBLAS_INLINE + void resize(size_type size1, size_type size2) { + size1_ = size1; + size2_ = size2; + } + BOOST_UBLAS_INLINE + void swap(matrix_size_dynamic &other) { + std::swap (size1_, other.size1_); + std::swap (size2_, other.size2_); + } + + private: + size_type size1_; + size_type size2_; + }; + + template + class matrix_size_static + { + public: + typedef std::size_t size_type; + + BOOST_UBLAS_INLINE + matrix_size_static () {} + BOOST_UBLAS_INLINE + matrix_size_static (size_type size1, size_type size2) { + BOOST_UBLAS_CHECK (size1 == M, bad_size ()); + BOOST_UBLAS_CHECK (size2 == N, bad_size ()); + } + + // Accessors + BOOST_UBLAS_INLINE + size_type size1 () const { + return M; + } + BOOST_UBLAS_INLINE + size_type size2 () const { + return N; + } + + BOOST_UBLAS_INLINE + void resize(size_type size1, size_type size2) { + BOOST_UBLAS_CHECK (size1 == M, bad_size ()); + BOOST_UBLAS_CHECK (size2 == N, bad_size ()); + } + BOOST_UBLAS_INLINE + void swap(const matrix_size_static &other) { + BOOST_UBLAS_CHECK (other.size1() == M, bad_size ()); + BOOST_UBLAS_CHECK (other.size2() == N, bad_size ()); + } + }; + /** \brief A dense matrix of values of type \c T. * * For a \f$(m \times n)\f$-dimensional matrix and \f$ 0 \leq i < m, 0 \leq j < n\f$, every element \f$ m_{i,j} \f$ is mapped to @@ -86,13 +161,13 @@ * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major * \tparam A the type of Storage array. Default is \c unbounded_array */ - template + template class matrix: - public matrix_container > { + public matrix_container >, public S { typedef T *pointer; typedef L layout_type; - typedef matrix self_type; + typedef matrix self_type; public: #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS using matrix_container::operator (); @@ -103,6 +178,7 @@ typedef const T &const_reference; typedef T &reference; typedef A array_type; + typedef S matrix_size_type; typedef const matrix_reference const_closure_type; typedef matrix_reference closure_type; typedef vector vector_temporary_type; @@ -117,42 +193,32 @@ BOOST_UBLAS_INLINE matrix (): matrix_container (), - size1_ (0), size2_ (0), data_ () {} + data_ () {} BOOST_UBLAS_INLINE matrix (size_type size1, size_type size2): matrix_container (), - size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2)) { + matrix_size_type(size1, 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) { + matrix_size_type(size1, 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 (), - size1_ (size1), size2_ (size2), data_ (data) {} + matrix_size_type(size1, size2), data_ (data) {} BOOST_UBLAS_INLINE matrix (const matrix &m): matrix_container (), - size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {} + matrix_size_type(m.size1(), m.size2()), data_ (m.data_) {} template BOOST_UBLAS_INLINE matrix (const matrix_expression &ae): matrix_container (), - size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::storage_size (size1_, size2_)) { + matrix_size_type(ae ().size1 (), ae ().size2 ()), data_ (layout_type::storage_size (this->size1(), this->size2())) { matrix_assign (*this, ae); } - // Accessors - BOOST_UBLAS_INLINE - size_type size1 () const { - return size1_; - } - BOOST_UBLAS_INLINE - size_type size2 () const { - return size2_; - } - // Storage accessors BOOST_UBLAS_INLINE const array_type &data () const { @@ -172,19 +238,18 @@ } else { data ().resize (layout_type::storage_size (size1, size2)); - size1_ = size1; - size2_ = size2; + matrix_size_type::resize(size1, size2); } } // Element access BOOST_UBLAS_INLINE const_reference operator () (size_type i, size_type j) const { - return data () [layout_type::element (i, size1_, j, size2_)]; + return data () [layout_type::element (i, this->size1(), j, this->size2())]; } BOOST_UBLAS_INLINE reference at_element (size_type i, size_type j) { - return data () [layout_type::element (i, size1_, j, size2_)]; + return data () [layout_type::element (i, this->size1(), j, this->size2())]; } BOOST_UBLAS_INLINE reference operator () (size_type i, size_type j) { @@ -218,8 +283,7 @@ #else BOOST_UBLAS_INLINE matrix &operator = (const matrix &m) { - size1_ = m.size1_; - size2_ = m.size2_; + matrix_size_type::resize(m.size1(), m.size2()); data () = m.data (); return *this; } @@ -301,8 +365,7 @@ BOOST_UBLAS_INLINE void swap (matrix &m) { if (this != &m) { - std::swap (size1_, m.size1_); - std::swap (size2_, m.size2_); + matrix_size_type::swap (m); data ().swap (m.data ()); } } @@ -340,7 +403,7 @@ #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator1 (*this, i, j); #else - return const_iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_)); + return const_iterator1 (*this, data ().begin () + layout_type::address (i, this->size1(), j, this->size2())); #endif } BOOST_UBLAS_INLINE @@ -348,7 +411,7 @@ #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator1 (*this, i, j); #else - return iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_)); + return iterator1 (*this, data ().begin () + layout_type::address (i, this->size1(), j, this->size2())); #endif } BOOST_UBLAS_INLINE @@ -356,7 +419,7 @@ #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return const_iterator2 (*this, i, j); #else - return const_iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_)); + return const_iterator2 (*this, data ().begin () + layout_type::address (i, this->size1(), j, this->size2())); #endif } BOOST_UBLAS_INLINE @@ -364,7 +427,7 @@ #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR return iterator2 (*this, i, j); #else - return iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_)); + return iterator2 (*this, data ().begin () + layout_type::address (i, this->size1(), j, this->size2())); #endif } @@ -511,7 +574,7 @@ } BOOST_UBLAS_INLINE const_iterator1 end1 () const { - return find1 (0, size1_, 0); + return find1 (0, this->size1(), 0); } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR @@ -653,7 +716,7 @@ } BOOST_UBLAS_INLINE iterator1 end1 () { - return find1 (0, size1_, 0); + return find1 (0, this->size1(), 0); } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR @@ -798,7 +861,7 @@ } BOOST_UBLAS_INLINE const_iterator2 end2 () const { - return find2 (0, 0, size2_); + return find2 (0, 0, this->size2()); } #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR @@ -940,7 +1003,7 @@ } BOOST_UBLAS_INLINE iterator2 end2 () { - return find2 (0, 0, size2_); + return find2 (0, 0, this->size2()); } // Reverse iterators @@ -987,8 +1050,8 @@ // we need to copy to a collection_size_type to get a portable // and efficient serialization - serialization::collection_size_type s1 (size1_); - serialization::collection_size_type s2 (size2_); + serialization::collection_size_type s1 (this->size1()); + serialization::collection_size_type s2 (this->size2()); // serialize the sizes ar & serialization::make_nvp("size1",s1) @@ -996,15 +1059,12 @@ // copy the values back if loading if (Archive::is_loading::value) { - size1_ = s1; - size2_ = s2; + matrix_size_type::resize(s1, s2); } ar & serialization::make_nvp("data",data_); } private: - size_type size1_; - size_type size2_; array_type data_; }; @@ -1044,9 +1104,9 @@ BOOST_UBLAS_INLINE bounded_matrix (const bounded_matrix &m): matrix_type (m) {} - template // Allow matrix > construction + template // Allow matrix > construction BOOST_UBLAS_INLINE - bounded_matrix (const matrix &m): + bounded_matrix (const matrix &m): matrix_type (m) {} template BOOST_UBLAS_INLINE @@ -1071,9 +1131,9 @@ return *this; } #endif - template // Generic matrix assignment + template // Generic matrix assignment BOOST_UBLAS_INLINE - bounded_matrix &operator = (const matrix &m) { + bounded_matrix &operator = (const matrix &m) { matrix_type::operator = (m); return *this; } @@ -1091,6 +1151,88 @@ } }; + /** \brief A dense matrix of values of type \c T with a fixed size of \f$M\f$ by \f$N\f$. + * + * For a \f$(m \times n)\f$-dimensional matrix and \f$ 0 \leq i < m, 0 \leq j < n\f$, every element \f$m_{i,j}\f$ is mapped + * to the \f$(i.n + j)\f$-th element of the container for row major orientation or the \f$(i + j.m)\f$-th element + * of the container for column major orientation. Finally in a dense matrix all elements are represented in memory + * in a contiguous chunk of memory. + * + * Orientation can be specified. Default is \c row_major + * Elements are constructed by the storage type \c fixed_array, which need not initialise their value. + * + * \tparam T the type of object stored in the matrix (like double, float, complex, etc...) + * \tparam M fixed number of rows + * \tparam N fixed number of columns + * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major + */ + template + class fixed_matrix: + public matrix, matrix_size_static > { + + typedef matrix, matrix_size_static > matrix_type; + public: + typedef typename matrix_type::size_type size_type; + static const size_type max_size1 = M; + static const size_type max_size2 = N; + + // Construction and destruction + BOOST_UBLAS_INLINE + fixed_matrix (): + matrix_type (M, N) {} + BOOST_UBLAS_INLINE + fixed_matrix (size_type size1, size_type size2): + matrix_type (size1, size2) {} + BOOST_UBLAS_INLINE + fixed_matrix (const fixed_matrix &m): + matrix_type (m) {} + template // Allow matrix > construction + BOOST_UBLAS_INLINE + fixed_matrix (const matrix &m): + matrix_type (m) {} + template + BOOST_UBLAS_INLINE + fixed_matrix (const matrix_expression &ae): + matrix_type (ae) {} + BOOST_UBLAS_INLINE + ~fixed_matrix () {} + + // Assignment +#ifdef BOOST_UBLAS_MOVE_SEMANTICS + + /*! @note "pass by value" the key idea to enable move semantics */ + BOOST_UBLAS_INLINE + fixed_matrix &operator = (fixed_matrix m) { + matrix_type::operator = (m); + return *this; + } +#else + BOOST_UBLAS_INLINE + fixed_matrix &operator = (const fixed_matrix &m) { + matrix_type::operator = (m); + return *this; + } +#endif + template // Generic matrix assignment + BOOST_UBLAS_INLINE + fixed_matrix &operator = (const matrix &m) { + matrix_type::operator = (m); + return *this; + } + template // Container assignment without temporary + BOOST_UBLAS_INLINE + fixed_matrix &operator = (const matrix_container &m) { + matrix_type::operator = (m); + return *this; + } + template + BOOST_UBLAS_INLINE + fixed_matrix &operator = (const matrix_expression &ae) { + matrix_type::operator = (ae); + return *this; + } + }; + /** \brief A dense matrix of values of type \c T stored as a vector of vectors. * * Rows or columns are not stored into contiguous chunks of memory but data inside rows (or columns) are. Index: boost/numeric/ublas/detail/config.hpp =================================================================== --- boost/numeric/ublas/detail/config.hpp (revision 64584) +++ boost/numeric/ublas/detail/config.hpp (working copy) @@ -266,6 +266,11 @@ #define BOOST_UBLAS_BOUNDED_ARRAY_ALIGN #endif +// Alignment of fixed_array type +#ifndef BOOST_UBLAS_FIXED_ARRAY_ALIGN +#define BOOST_UBLAS_FIXED_ARRAY_ALIGN +#endif + // Enable different sparse element proxies #ifndef BOOST_UBLAS_NO_ELEMENT_PROXIES // Sparse proxies prevent reference invalidation problems in expressions such as: Index: boost/numeric/ublas/fwd.hpp =================================================================== --- boost/numeric/ublas/fwd.hpp (revision 64584) +++ boost/numeric/ublas/fwd.hpp (working copy) @@ -26,6 +26,9 @@ template > class bounded_array; + template > + class fixed_array; + template class basic_range; template @@ -90,6 +93,8 @@ class vector; template class bounded_vector; + template + class fixed_vector; template > class unit_vector; @@ -123,10 +128,17 @@ struct basic_column_major; typedef basic_column_major<> column_major; - template > + template + class matrix_size_dynamic; + template + class matrix_size_static; + + template, class S = matrix_size_dynamic<> > class matrix; template class bounded_matrix; + template + class fixed_matrix; template > class identity_matrix; Index: libs/numeric/ublas/test/Jamfile.v2 =================================================================== --- libs/numeric/ublas/test/Jamfile.v2 (revision 64584) +++ libs/numeric/ublas/test/Jamfile.v2 (working copy) @@ -63,13 +63,13 @@ : : : $(UBLAS_TESTSET) ] - [ run test3.cpp - test31.cpp - test32.cpp - test33.cpp - : : : - $(UBLAS_TESTSET_SPARSE) - ] +# [ run test3.cpp +# test31.cpp +# test32.cpp +# test33.cpp +# : : : +# $(UBLAS_TESTSET_SPARSE) +# ] [ run test4.cpp test42.cpp test43.cpp @@ -128,10 +128,10 @@ ] [ run size.cpp ] - [ run test_coordinate_matrix_sort.cpp - ] +# [ run test_coordinate_matrix_sort.cpp +# ] [ run test_complex_norms.cpp ] - [ run test_assignment.cpp - ] +# [ run test_assignment.cpp +# ] ;