1 // 2 // Copyright (c) 2000-2010 3 // Joerg Walter, Mathias Koch, Gunter Winkler, David Bellot 4 // Copyright (c) 2014, Athanasios Iliopoulos 5 // 6 // Distributed under the Boost Software License, Version 1.0. (See 7 // accompanying file LICENSE_1_0.txt or copy at 8 // http://www.boost.org/LICENSE_1_0.txt) 9 // 10 // The authors gratefully acknowledge the support of 11 // GeNeSys mbH & Co. KG in producing this work. 12 // 13 14 #ifndef _BOOST_UBLAS_MATRIX_ 15 #define _BOOST_UBLAS_MATRIX_ 16 17 #include <boost/config.hpp> 18 #include <boost/numeric/ublas/vector.hpp> 19 #include <boost/numeric/ublas/matrix_expression.hpp> 20 #include <boost/numeric/ublas/detail/matrix_assign.hpp> 21 #include <boost/serialization/collection_size_type.hpp> 22 #include <boost/serialization/array.hpp> 23 #include <boost/serialization/nvp.hpp> 24 25 // Iterators based on ideas of Jeremy Siek 26 27 namespace boost { namespace numeric { 28 29 /** \brief main namespace of uBLAS. 30 * 31 * Use this namespace for all operations with uBLAS. It can also be abbreviated with 32 * \code namespace ublas = boost::numeric::ublas; \endcode 33 * 34 * A common practice is to bring this namespace into the current scope with 35 * \code using namespace boost::numeric::ublas; \endcode. 36 * 37 * However, be warned that using the ublas namespace and the std::vector at the same time can lead to the compiler to confusion. 38 * The solution is simply to prefix each ublas vector like \c boost::numeric::ublas::vector<T>. If you think it's too long to 39 * write, you can define a new namespace like \c namespace ublas = boost::numeric::ublas and then just declare your vectors 40 * with \c ublas::vector<T>. STL vectors will be declared as vector<T>. No need to prefix with \c std:: 41 */ 42 namespace ublas { 43 44 namespace detail { 45 using namespace boost::numeric::ublas; 46 47 // Matrix resizing algorithm 48 template <class L, class M> 49 BOOST_UBLAS_INLINE matrix_resize_preserve(M & m,M & temporary)50 void matrix_resize_preserve (M& m, M& temporary) { 51 typedef L layout_type; 52 typedef typename M::size_type size_type; 53 const size_type msize1 (m.size1 ()); // original size 54 const size_type msize2 (m.size2 ()); 55 const size_type size1 (temporary.size1 ()); // new size is specified by temporary 56 const size_type size2 (temporary.size2 ()); 57 // Common elements to preserve 58 const size_type size1_min = (std::min) (size1, msize1); 59 const size_type size2_min = (std::min) (size2, msize2); 60 // Order for major and minor sizes 61 const size_type major_size = layout_type::size_M (size1_min, size2_min); 62 const size_type minor_size = layout_type::size_m (size1_min, size2_min); 63 // Indexing copy over major 64 for (size_type major = 0; major != major_size; ++major) { 65 for (size_type minor = 0; minor != minor_size; ++minor) { 66 // find indexes - use invertability of element_ functions 67 const size_type i1 = layout_type::index_M(major, minor); 68 const size_type i2 = layout_type::index_m(major, minor); 69 temporary.data () [layout_type::element (i1, size1, i2, size2)] = 70 m.data() [layout_type::element (i1, msize1, i2, msize2)]; 71 } 72 } 73 m.assign_temporary (temporary); 74 } 75 } 76 77 /** \brief A dense matrix of values of type \c T. 78 * 79 * 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 80 * 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 81 * the container for column major orientation. In a dense matrix all elements are represented in memory in a 82 * contiguous chunk of memory by definition. 83 * 84 * Orientation and storage can also be specified, otherwise a \c row_major and \c unbounded_array are used. It is \b not 85 * required by the storage to initialize elements of the matrix. 86 * 87 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...) 88 * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major 89 * \tparam A the type of Storage array. Default is \c unbounded_array 90 */ 91 template<class T, class L, class A> 92 class matrix: 93 public matrix_container<matrix<T, L, A> > { 94 95 typedef T *pointer; 96 typedef L layout_type; 97 typedef matrix<T, L, A> self_type; 98 public: 99 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 100 using matrix_container<self_type>::operator (); 101 #endif 102 typedef typename A::size_type size_type; 103 typedef typename A::difference_type difference_type; 104 typedef T value_type; 105 typedef const T &const_reference; 106 typedef T &reference; 107 typedef A array_type; 108 typedef const matrix_reference<const self_type> const_closure_type; 109 typedef matrix_reference<self_type> closure_type; 110 typedef vector<T, A> vector_temporary_type; 111 typedef self_type matrix_temporary_type; 112 typedef dense_tag storage_category; 113 // This could be better for performance, 114 // typedef typename unknown_orientation_tag orientation_category; 115 // but others depend on the orientation information... 116 typedef typename L::orientation_category orientation_category; 117 118 // Construction and destruction 119 120 /// Default dense matrix constructor. Make a dense matrix of size (0,0) 121 BOOST_UBLAS_INLINE matrix()122 matrix (): 123 matrix_container<self_type> (), 124 size1_ (0), size2_ (0), data_ () {} 125 126 /** Dense matrix constructor with defined size 127 * \param size1 number of rows 128 * \param size2 number of columns 129 */ 130 BOOST_UBLAS_INLINE matrix(size_type size1,size_type size2)131 matrix (size_type size1, size_type size2): 132 matrix_container<self_type> (), 133 size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2)) { 134 } 135 136 /** Dense matrix constructor with defined size a initial value for all the matrix elements 137 * \param size1 number of rows 138 * \param size2 number of columns 139 * \param init initial value assigned to all elements 140 */ matrix(size_type size1,size_type size2,const value_type & init)141 matrix (size_type size1, size_type size2, const value_type &init): 142 matrix_container<self_type> (), 143 size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2), init) { 144 } 145 146 /** Dense matrix constructor with defined size and an initial data array 147 * \param size1 number of rows 148 * \param size2 number of columns 149 * \param data array to copy into the matrix. Must have the same dimension as the matrix 150 */ 151 BOOST_UBLAS_INLINE matrix(size_type size1,size_type size2,const array_type & data)152 matrix (size_type size1, size_type size2, const array_type &data): 153 matrix_container<self_type> (), 154 size1_ (size1), size2_ (size2), data_ (data) {} 155 156 /** Copy-constructor of a dense matrix 157 * \param m is a dense matrix 158 */ 159 BOOST_UBLAS_INLINE matrix(const matrix & m)160 matrix (const matrix &m): 161 matrix_container<self_type> (), 162 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {} 163 164 /** Copy-constructor of a dense matrix from a matrix expression 165 * \param ae is a matrix expression 166 */ 167 template<class AE> 168 BOOST_UBLAS_INLINE matrix(const matrix_expression<AE> & ae)169 matrix (const matrix_expression<AE> &ae): 170 matrix_container<self_type> (), 171 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::storage_size (size1_, size2_)) { 172 matrix_assign<scalar_assign> (*this, ae); 173 } 174 175 // Accessors 176 /** Return the number of rows of the matrix 177 * You can also use the free size<>() function in operation/size.hpp as size<1>(m) where m is a matrix 178 */ 179 BOOST_UBLAS_INLINE size1() const180 size_type size1 () const { 181 return size1_; 182 } 183 184 /** Return the number of colums of the matrix 185 * You can also use the free size<>() function in operation/size.hpp as size<2>(m) where m is a matrix 186 */ 187 BOOST_UBLAS_INLINE size2() const188 size_type size2 () const { 189 return size2_; 190 } 191 192 // Storage accessors 193 /** Return a constant reference to the internal storage of a dense matrix, i.e. the raw data 194 * It's type depends on the type used by the matrix to store its data 195 */ 196 BOOST_UBLAS_INLINE data() const197 const array_type &data () const { 198 return data_; 199 } 200 /** Return a reference to the internal storage of a dense matrix, i.e. the raw data 201 * It's type depends on the type used by the matrix to store its data 202 */ 203 BOOST_UBLAS_INLINE data()204 array_type &data () { 205 return data_; 206 } 207 208 // Resizing 209 /** Resize a matrix to new dimensions 210 * If data are preserved, then if the size if bigger at least on one dimension, extra values are filled with zeros. 211 * If data are not preserved, then nothing has to be assumed regarding the content of the matrix after resizing. 212 * \param size1 the new number of rows 213 * \param size2 the new number of colums 214 * \param preserve a boolean to say if one wants the data to be preserved during the resizing. Default is true. 215 */ 216 BOOST_UBLAS_INLINE resize(size_type size1,size_type size2,bool preserve=true)217 void resize (size_type size1, size_type size2, bool preserve = true) { 218 if (preserve) { 219 self_type temporary (size1, size2); 220 detail::matrix_resize_preserve<layout_type> (*this, temporary); 221 } 222 else { 223 data ().resize (layout_type::storage_size (size1, size2)); 224 size1_ = size1; 225 size2_ = size2; 226 } 227 } 228 229 // Element access 230 231 /** Access a matrix element. Here we return a const reference 232 * \param i the first coordinate of the element. By default it's the row 233 * \param j the second coordinate of the element. By default it's the column 234 * \return a const reference to the element 235 */ 236 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const237 const_reference operator () (size_type i, size_type j) const { 238 return data () [layout_type::element (i, size1_, j, size2_)]; 239 } 240 241 /** Access a matrix element. Here we return a reference 242 * \param i the first coordinate of the element. By default it's the row 243 * \param j the second coordinate of the element. By default it's the column 244 * \return a reference to the element 245 */ 246 BOOST_UBLAS_INLINE at_element(size_type i,size_type j)247 reference at_element (size_type i, size_type j) { 248 return data () [layout_type::element (i, size1_, j, size2_)]; 249 } 250 251 /** Access a matrix element. Here we return a reference 252 * \param i the first coordinate of the element. By default it's the row 253 * \param j the second coordinate of the element. By default it's the column 254 * \return a reference to the element 255 */ 256 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j)257 reference operator () (size_type i, size_type j) { 258 return at_element (i, j); 259 } 260 261 /** Access a matrix element. Here we return a reference 262 * \param i the first coordinate of the element. By default it's the row 263 * \param j the second coordinate of the element. By default it's the column 264 * \return a reference to the element 265 */ 266 BOOST_UBLAS_INLINE operator ()(size_type i)267 reference operator () (size_type i) { 268 return data()[i]; 269 } 270 271 BOOST_UBLAS_INLINE operator ()(size_type i) const272 const_reference operator () (size_type i) const { 273 return data()[i]; 274 } 275 276 // /** Access a matrix element. Here we return a reference 277 // * \param i the first coordinate of the element. By default it's the row 278 // * \param j the second coordinate of the element. By default it's the column 279 // * \return a reference to the element 280 // */ 281 // BOOST_UBLAS_INLINE 282 // const_reference operator () const (size_type i) { 283 // return data()[i]; 284 // } 285 // Element assignment 286 287 /** Change the value of a matrix element. Return back a reference to it 288 * \param i the first coordinate of the element. By default it's the row 289 * \param j the second coordinate of the element. By default it's the column 290 * \param t the new value of the element 291 * \return a reference to the newly changed element 292 */ 293 BOOST_UBLAS_INLINE insert_element(size_type i,size_type j,const_reference t)294 reference insert_element (size_type i, size_type j, const_reference t) { 295 return (at_element (i, j) = t); 296 } 297 298 /** Erase the element 299 * For most types (int, double, etc...) it means setting 0 (zero) the element at zero in fact. 300 * For user-defined types, it could be another value if you decided it. Your type in that case must 301 * contain a default null value. 302 * \param i the first coordinate of the element. By default it's the row 303 * \param j the second coordinate of the element. By default it's the column 304 */ erase_element(size_type i,size_type j)305 void erase_element (size_type i, size_type j) { 306 at_element (i, j) = value_type/*zero*/(); 307 } 308 309 // Zeroing 310 /** Erase all elements in the matrix 311 * For most types (int, double, etc...) it means writing 0 (zero) everywhere. 312 * For user-defined types, it could be another value if you decided it. Your type in that case must 313 * contain a default null value. 314 */ 315 BOOST_UBLAS_INLINE clear()316 void clear () { 317 std::fill (data ().begin (), data ().end (), value_type/*zero*/()); 318 } 319 320 // Assignment 321 #ifdef BOOST_UBLAS_MOVE_SEMANTICS 322 323 /*! @note "pass by value" the key idea to enable move semantics */ 324 BOOST_UBLAS_INLINE operator =(matrix m)325 matrix &operator = (matrix m) { 326 assign_temporary(m); 327 return *this; 328 } 329 #else 330 BOOST_UBLAS_INLINE operator =(const matrix & m)331 matrix &operator = (const matrix &m) { 332 size1_ = m.size1_; 333 size2_ = m.size2_; 334 data () = m.data (); 335 return *this; 336 } 337 #endif 338 template<class C> // Container assignment without temporary 339 BOOST_UBLAS_INLINE operator =(const matrix_container<C> & m)340 matrix &operator = (const matrix_container<C> &m) { 341 resize (m ().size1 (), m ().size2 (), false); 342 assign (m); 343 return *this; 344 } 345 BOOST_UBLAS_INLINE assign_temporary(matrix & m)346 matrix &assign_temporary (matrix &m) { 347 swap (m); 348 return *this; 349 } 350 template<class AE> 351 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)352 matrix &operator = (const matrix_expression<AE> &ae) { 353 self_type temporary (ae); 354 return assign_temporary (temporary); 355 } 356 template<class AE> 357 BOOST_UBLAS_INLINE assign(const matrix_expression<AE> & ae)358 matrix &assign (const matrix_expression<AE> &ae) { 359 matrix_assign<scalar_assign> (*this, ae); 360 return *this; 361 } 362 template<class AE> 363 BOOST_UBLAS_INLINE operator +=(const matrix_expression<AE> & ae)364 matrix& operator += (const matrix_expression<AE> &ae) { 365 self_type temporary (*this + ae); 366 return assign_temporary (temporary); 367 } 368 template<class C> // Container assignment without temporary 369 BOOST_UBLAS_INLINE operator +=(const matrix_container<C> & m)370 matrix &operator += (const matrix_container<C> &m) { 371 plus_assign (m); 372 return *this; 373 } 374 template<class AE> 375 BOOST_UBLAS_INLINE plus_assign(const matrix_expression<AE> & ae)376 matrix &plus_assign (const matrix_expression<AE> &ae) { 377 matrix_assign<scalar_plus_assign> (*this, ae); 378 return *this; 379 } 380 template<class AE> 381 BOOST_UBLAS_INLINE operator -=(const matrix_expression<AE> & ae)382 matrix& operator -= (const matrix_expression<AE> &ae) { 383 self_type temporary (*this - ae); 384 return assign_temporary (temporary); 385 } 386 template<class C> // Container assignment without temporary 387 BOOST_UBLAS_INLINE operator -=(const matrix_container<C> & m)388 matrix &operator -= (const matrix_container<C> &m) { 389 minus_assign (m); 390 return *this; 391 } 392 template<class AE> 393 BOOST_UBLAS_INLINE minus_assign(const matrix_expression<AE> & ae)394 matrix &minus_assign (const matrix_expression<AE> &ae) { 395 matrix_assign<scalar_minus_assign> (*this, ae); 396 return *this; 397 } 398 template<class AT> 399 BOOST_UBLAS_INLINE operator *=(const AT & at)400 matrix& operator *= (const AT &at) { 401 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 402 return *this; 403 } 404 template<class AT> 405 BOOST_UBLAS_INLINE operator /=(const AT & at)406 matrix& operator /= (const AT &at) { 407 matrix_assign_scalar<scalar_divides_assign> (*this, at); 408 return *this; 409 } 410 411 // Swapping 412 BOOST_UBLAS_INLINE swap(matrix & m)413 void swap (matrix &m) { 414 if (this != &m) { 415 std::swap (size1_, m.size1_); 416 std::swap (size2_, m.size2_); 417 data ().swap (m.data ()); 418 } 419 } 420 BOOST_UBLAS_INLINE swap(matrix & m1,matrix & m2)421 friend void swap (matrix &m1, matrix &m2) { 422 m1.swap (m2); 423 } 424 425 // Iterator types 426 private: 427 // Use the storage array iterator 428 typedef typename A::const_iterator const_subiterator_type; 429 typedef typename A::iterator subiterator_type; 430 431 public: 432 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 433 typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1; 434 typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2; 435 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1; 436 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2; 437 #else 438 class const_iterator1; 439 class iterator1; 440 class const_iterator2; 441 class iterator2; 442 #endif 443 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 444 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 445 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 446 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 447 448 // Element lookup 449 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j) const450 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const { 451 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 452 return const_iterator1 (*this, i, j); 453 #else 454 return const_iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_)); 455 #endif 456 } 457 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j)458 iterator1 find1 (int /* rank */, size_type i, size_type j) { 459 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 460 return iterator1 (*this, i, j); 461 #else 462 return iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_)); 463 #endif 464 } 465 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j) const466 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const { 467 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 468 return const_iterator2 (*this, i, j); 469 #else 470 return const_iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_)); 471 #endif 472 } 473 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j)474 iterator2 find2 (int /* rank */, size_type i, size_type j) { 475 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 476 return iterator2 (*this, i, j); 477 #else 478 return iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_)); 479 #endif 480 } 481 482 483 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 484 class const_iterator1: 485 public container_const_reference<matrix>, 486 public random_access_iterator_base<dense_random_access_iterator_tag, 487 const_iterator1, value_type> { 488 public: 489 typedef typename matrix::value_type value_type; 490 typedef typename matrix::difference_type difference_type; 491 typedef typename matrix::const_reference reference; 492 typedef const typename matrix::pointer pointer; 493 494 typedef const_iterator2 dual_iterator_type; 495 typedef const_reverse_iterator2 dual_reverse_iterator_type; 496 497 // Construction and destruction 498 BOOST_UBLAS_INLINE const_iterator1()499 const_iterator1 (): 500 container_const_reference<self_type> (), it_ () {} 501 BOOST_UBLAS_INLINE const_iterator1(const self_type & m,const const_subiterator_type & it)502 const_iterator1 (const self_type &m, const const_subiterator_type &it): 503 container_const_reference<self_type> (m), it_ (it) {} 504 BOOST_UBLAS_INLINE const_iterator1(const iterator1 & it)505 const_iterator1 (const iterator1 &it): 506 container_const_reference<self_type> (it ()), it_ (it.it_) {} 507 508 // Arithmetic 509 BOOST_UBLAS_INLINE operator ++()510 const_iterator1 &operator ++ () { 511 layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ()); 512 return *this; 513 } 514 BOOST_UBLAS_INLINE operator --()515 const_iterator1 &operator -- () { 516 layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ()); 517 return *this; 518 } 519 BOOST_UBLAS_INLINE operator +=(difference_type n)520 const_iterator1 &operator += (difference_type n) { 521 layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 522 return *this; 523 } 524 BOOST_UBLAS_INLINE operator -=(difference_type n)525 const_iterator1 &operator -= (difference_type n) { 526 layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 527 return *this; 528 } 529 BOOST_UBLAS_INLINE operator -(const const_iterator1 & it) const530 difference_type operator - (const const_iterator1 &it) const { 531 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 532 return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ()); 533 } 534 535 // Dereference 536 BOOST_UBLAS_INLINE operator *() const537 const_reference operator * () const { 538 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 539 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 540 return *it_; 541 } 542 BOOST_UBLAS_INLINE operator [](difference_type n) const543 const_reference operator [] (difference_type n) const { 544 return *(*this + n); 545 } 546 547 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 548 BOOST_UBLAS_INLINE 549 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 550 typename self_type:: 551 #endif begin() const552 const_iterator2 begin () const { 553 const self_type &m = (*this) (); 554 return m.find2 (1, index1 (), 0); 555 } 556 BOOST_UBLAS_INLINE 557 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 558 typename self_type:: 559 #endif cbegin() const560 const_iterator2 cbegin () const { 561 return begin (); 562 } 563 BOOST_UBLAS_INLINE 564 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 565 typename self_type:: 566 #endif end() const567 const_iterator2 end () const { 568 const self_type &m = (*this) (); 569 return m.find2 (1, index1 (), m.size2 ()); 570 } 571 BOOST_UBLAS_INLINE 572 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 573 typename self_type:: 574 #endif cend() const575 const_iterator2 cend () const { 576 return end (); 577 } 578 BOOST_UBLAS_INLINE 579 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 580 typename self_type:: 581 #endif rbegin() const582 const_reverse_iterator2 rbegin () const { 583 return const_reverse_iterator2 (end ()); 584 } 585 BOOST_UBLAS_INLINE 586 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 587 typename self_type:: 588 #endif crbegin() const589 const_reverse_iterator2 crbegin () const { 590 return rbegin (); 591 } 592 BOOST_UBLAS_INLINE 593 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 594 typename self_type:: 595 #endif rend() const596 const_reverse_iterator2 rend () const { 597 return const_reverse_iterator2 (begin ()); 598 } 599 BOOST_UBLAS_INLINE 600 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 601 typename self_type:: 602 #endif crend() const603 const_reverse_iterator2 crend () const { 604 return rend (); 605 } 606 #endif 607 608 // Indices 609 BOOST_UBLAS_INLINE index1() const610 size_type index1 () const { 611 const self_type &m = (*this) (); 612 return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ()); 613 } 614 BOOST_UBLAS_INLINE index2() const615 size_type index2 () const { 616 const self_type &m = (*this) (); 617 return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ()); 618 } 619 620 // Assignment 621 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)622 const_iterator1 &operator = (const const_iterator1 &it) { 623 container_const_reference<self_type>::assign (&it ()); 624 it_ = it.it_; 625 return *this; 626 } 627 628 // Comparison 629 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const630 bool operator == (const const_iterator1 &it) const { 631 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 632 return it_ == it.it_; 633 } 634 BOOST_UBLAS_INLINE operator <(const const_iterator1 & it) const635 bool operator < (const const_iterator1 &it) const { 636 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 637 return it_ < it.it_; 638 } 639 640 private: 641 const_subiterator_type it_; 642 643 friend class iterator1; 644 }; 645 #endif 646 647 BOOST_UBLAS_INLINE begin1() const648 const_iterator1 begin1 () const { 649 return find1 (0, 0, 0); 650 } 651 BOOST_UBLAS_INLINE cbegin1() const652 const_iterator1 cbegin1 () const { 653 return begin1 (); 654 } 655 BOOST_UBLAS_INLINE end1() const656 const_iterator1 end1 () const { 657 return find1 (0, size1_, 0); 658 } 659 BOOST_UBLAS_INLINE cend1() const660 const_iterator1 cend1 () const { 661 return end1 (); 662 } 663 664 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 665 class iterator1: 666 public container_reference<matrix>, 667 public random_access_iterator_base<dense_random_access_iterator_tag, 668 iterator1, value_type> { 669 public: 670 typedef typename matrix::value_type value_type; 671 typedef typename matrix::difference_type difference_type; 672 typedef typename matrix::reference reference; 673 typedef typename matrix::pointer pointer; 674 675 typedef iterator2 dual_iterator_type; 676 typedef reverse_iterator2 dual_reverse_iterator_type; 677 678 // Construction and destruction 679 BOOST_UBLAS_INLINE iterator1()680 iterator1 (): 681 container_reference<self_type> (), it_ () {} 682 BOOST_UBLAS_INLINE iterator1(self_type & m,const subiterator_type & it)683 iterator1 (self_type &m, const subiterator_type &it): 684 container_reference<self_type> (m), it_ (it) {} 685 686 // Arithmetic 687 BOOST_UBLAS_INLINE operator ++()688 iterator1 &operator ++ () { 689 layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ()); 690 return *this; 691 } 692 BOOST_UBLAS_INLINE operator --()693 iterator1 &operator -- () { 694 layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ()); 695 return *this; 696 } 697 BOOST_UBLAS_INLINE operator +=(difference_type n)698 iterator1 &operator += (difference_type n) { 699 layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 700 return *this; 701 } 702 BOOST_UBLAS_INLINE operator -=(difference_type n)703 iterator1 &operator -= (difference_type n) { 704 layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 705 return *this; 706 } 707 BOOST_UBLAS_INLINE operator -(const iterator1 & it) const708 difference_type operator - (const iterator1 &it) const { 709 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 710 return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ()); 711 } 712 713 // Dereference 714 BOOST_UBLAS_INLINE operator *() const715 reference operator * () const { 716 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 717 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 718 return *it_; 719 } 720 BOOST_UBLAS_INLINE operator [](difference_type n) const721 reference operator [] (difference_type n) const { 722 return *(*this + n); 723 } 724 725 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 726 BOOST_UBLAS_INLINE 727 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 728 typename self_type:: 729 #endif begin() const730 iterator2 begin () const { 731 self_type &m = (*this) (); 732 return m.find2 (1, index1 (), 0); 733 } 734 BOOST_UBLAS_INLINE 735 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 736 typename self_type:: 737 #endif end() const738 iterator2 end () const { 739 self_type &m = (*this) (); 740 return m.find2 (1, index1 (), m.size2 ()); 741 } 742 BOOST_UBLAS_INLINE 743 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 744 typename self_type:: 745 #endif rbegin() const746 reverse_iterator2 rbegin () const { 747 return reverse_iterator2 (end ()); 748 } 749 BOOST_UBLAS_INLINE 750 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 751 typename self_type:: 752 #endif rend() const753 reverse_iterator2 rend () const { 754 return reverse_iterator2 (begin ()); 755 } 756 #endif 757 758 // Indices 759 BOOST_UBLAS_INLINE index1() const760 size_type index1 () const { 761 self_type &m = (*this) (); 762 return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ()); 763 } 764 BOOST_UBLAS_INLINE index2() const765 size_type index2 () const { 766 self_type &m = (*this) (); 767 return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ()); 768 } 769 770 // Assignment 771 BOOST_UBLAS_INLINE operator =(const iterator1 & it)772 iterator1 &operator = (const iterator1 &it) { 773 container_reference<self_type>::assign (&it ()); 774 it_ = it.it_; 775 return *this; 776 } 777 778 // Comparison 779 BOOST_UBLAS_INLINE operator ==(const iterator1 & it) const780 bool operator == (const iterator1 &it) const { 781 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 782 return it_ == it.it_; 783 } 784 BOOST_UBLAS_INLINE operator <(const iterator1 & it) const785 bool operator < (const iterator1 &it) const { 786 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 787 return it_ < it.it_; 788 } 789 790 private: 791 subiterator_type it_; 792 793 friend class const_iterator1; 794 }; 795 #endif 796 797 BOOST_UBLAS_INLINE begin1()798 iterator1 begin1 () { 799 return find1 (0, 0, 0); 800 } 801 BOOST_UBLAS_INLINE end1()802 iterator1 end1 () { 803 return find1 (0, size1_, 0); 804 } 805 806 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 807 class const_iterator2: 808 public container_const_reference<matrix>, 809 public random_access_iterator_base<dense_random_access_iterator_tag, 810 const_iterator2, value_type> { 811 public: 812 typedef typename matrix::value_type value_type; 813 typedef typename matrix::difference_type difference_type; 814 typedef typename matrix::const_reference reference; 815 typedef const typename matrix::pointer pointer; 816 817 typedef const_iterator1 dual_iterator_type; 818 typedef const_reverse_iterator1 dual_reverse_iterator_type; 819 820 // Construction and destruction 821 BOOST_UBLAS_INLINE const_iterator2()822 const_iterator2 (): 823 container_const_reference<self_type> (), it_ () {} 824 BOOST_UBLAS_INLINE const_iterator2(const self_type & m,const const_subiterator_type & it)825 const_iterator2 (const self_type &m, const const_subiterator_type &it): 826 container_const_reference<self_type> (m), it_ (it) {} 827 BOOST_UBLAS_INLINE const_iterator2(const iterator2 & it)828 const_iterator2 (const iterator2 &it): 829 container_const_reference<self_type> (it ()), it_ (it.it_) {} 830 831 // Arithmetic 832 BOOST_UBLAS_INLINE operator ++()833 const_iterator2 &operator ++ () { 834 layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ()); 835 return *this; 836 } 837 BOOST_UBLAS_INLINE operator --()838 const_iterator2 &operator -- () { 839 layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ()); 840 return *this; 841 } 842 BOOST_UBLAS_INLINE operator +=(difference_type n)843 const_iterator2 &operator += (difference_type n) { 844 layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 845 return *this; 846 } 847 BOOST_UBLAS_INLINE operator -=(difference_type n)848 const_iterator2 &operator -= (difference_type n) { 849 layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 850 return *this; 851 } 852 BOOST_UBLAS_INLINE operator -(const const_iterator2 & it) const853 difference_type operator - (const const_iterator2 &it) const { 854 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 855 return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ()); 856 } 857 858 // Dereference 859 BOOST_UBLAS_INLINE operator *() const860 const_reference operator * () const { 861 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 862 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 863 return *it_; 864 } 865 BOOST_UBLAS_INLINE operator [](difference_type n) const866 const_reference operator [] (difference_type n) const { 867 return *(*this + n); 868 } 869 870 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 871 BOOST_UBLAS_INLINE 872 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 873 typename self_type:: 874 #endif begin() const875 const_iterator1 begin () const { 876 const self_type &m = (*this) (); 877 return m.find1 (1, 0, index2 ()); 878 } 879 BOOST_UBLAS_INLINE 880 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 881 typename self_type:: 882 #endif cbegin() const883 const_iterator1 cbegin () const { 884 return begin (); 885 } 886 BOOST_UBLAS_INLINE 887 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 888 typename self_type:: 889 #endif end() const890 const_iterator1 end () const { 891 const self_type &m = (*this) (); 892 return m.find1 (1, m.size1 (), index2 ()); 893 } 894 BOOST_UBLAS_INLINE 895 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 896 typename self_type:: 897 #endif cend() const898 const_iterator1 cend () const { 899 return end (); 900 } 901 BOOST_UBLAS_INLINE 902 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 903 typename self_type:: 904 #endif rbegin() const905 const_reverse_iterator1 rbegin () const { 906 return const_reverse_iterator1 (end ()); 907 } 908 BOOST_UBLAS_INLINE 909 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 910 typename self_type:: 911 #endif crbegin() const912 const_reverse_iterator1 crbegin () const { 913 return rbegin (); 914 } 915 BOOST_UBLAS_INLINE 916 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 917 typename self_type:: 918 #endif rend() const919 const_reverse_iterator1 rend () const { 920 return const_reverse_iterator1 (begin ()); 921 } 922 BOOST_UBLAS_INLINE 923 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 924 typename self_type:: 925 #endif crend() const926 const_reverse_iterator1 crend () const { 927 return rend (); 928 } 929 #endif 930 931 // Indices 932 BOOST_UBLAS_INLINE index1() const933 size_type index1 () const { 934 const self_type &m = (*this) (); 935 return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ()); 936 } 937 BOOST_UBLAS_INLINE index2() const938 size_type index2 () const { 939 const self_type &m = (*this) (); 940 return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ()); 941 } 942 943 // Assignment 944 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)945 const_iterator2 &operator = (const const_iterator2 &it) { 946 container_const_reference<self_type>::assign (&it ()); 947 it_ = it.it_; 948 return *this; 949 } 950 951 // Comparison 952 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const953 bool operator == (const const_iterator2 &it) const { 954 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 955 return it_ == it.it_; 956 } 957 BOOST_UBLAS_INLINE operator <(const const_iterator2 & it) const958 bool operator < (const const_iterator2 &it) const { 959 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 960 return it_ < it.it_; 961 } 962 963 private: 964 const_subiterator_type it_; 965 966 friend class iterator2; 967 }; 968 #endif 969 970 BOOST_UBLAS_INLINE begin2() const971 const_iterator2 begin2 () const { 972 return find2 (0, 0, 0); 973 } 974 BOOST_UBLAS_INLINE cbegin2() const975 const_iterator2 cbegin2 () const { 976 return begin2 (); 977 } 978 BOOST_UBLAS_INLINE end2() const979 const_iterator2 end2 () const { 980 return find2 (0, 0, size2_); 981 } 982 BOOST_UBLAS_INLINE cend2() const983 const_iterator2 cend2 () const { 984 return end2 (); 985 } 986 987 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 988 class iterator2: 989 public container_reference<matrix>, 990 public random_access_iterator_base<dense_random_access_iterator_tag, 991 iterator2, value_type> { 992 public: 993 typedef typename matrix::value_type value_type; 994 typedef typename matrix::difference_type difference_type; 995 typedef typename matrix::reference reference; 996 typedef typename matrix::pointer pointer; 997 998 typedef iterator1 dual_iterator_type; 999 typedef reverse_iterator1 dual_reverse_iterator_type; 1000 1001 // Construction and destruction 1002 BOOST_UBLAS_INLINE iterator2()1003 iterator2 (): 1004 container_reference<self_type> (), it_ () {} 1005 BOOST_UBLAS_INLINE iterator2(self_type & m,const subiterator_type & it)1006 iterator2 (self_type &m, const subiterator_type &it): 1007 container_reference<self_type> (m), it_ (it) {} 1008 1009 // Arithmetic 1010 BOOST_UBLAS_INLINE operator ++()1011 iterator2 &operator ++ () { 1012 layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ()); 1013 return *this; 1014 } 1015 BOOST_UBLAS_INLINE operator --()1016 iterator2 &operator -- () { 1017 layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ()); 1018 return *this; 1019 } 1020 BOOST_UBLAS_INLINE operator +=(difference_type n)1021 iterator2 &operator += (difference_type n) { 1022 layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 1023 return *this; 1024 } 1025 BOOST_UBLAS_INLINE operator -=(difference_type n)1026 iterator2 &operator -= (difference_type n) { 1027 layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 1028 return *this; 1029 } 1030 BOOST_UBLAS_INLINE operator -(const iterator2 & it) const1031 difference_type operator - (const iterator2 &it) const { 1032 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1033 return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ()); 1034 } 1035 1036 // Dereference 1037 BOOST_UBLAS_INLINE operator *() const1038 reference operator * () const { 1039 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 1040 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 1041 return *it_; 1042 } 1043 BOOST_UBLAS_INLINE operator [](difference_type n) const1044 reference operator [] (difference_type n) const { 1045 return *(*this + n); 1046 } 1047 1048 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 1049 BOOST_UBLAS_INLINE 1050 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1051 typename self_type:: 1052 #endif begin() const1053 iterator1 begin () const { 1054 self_type &m = (*this) (); 1055 return m.find1 (1, 0, index2 ()); 1056 } 1057 BOOST_UBLAS_INLINE 1058 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1059 typename self_type:: 1060 #endif end() const1061 iterator1 end () const { 1062 self_type &m = (*this) (); 1063 return m.find1 (1, m.size1 (), index2 ()); 1064 } 1065 BOOST_UBLAS_INLINE 1066 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1067 typename self_type:: 1068 #endif rbegin() const1069 reverse_iterator1 rbegin () const { 1070 return reverse_iterator1 (end ()); 1071 } 1072 BOOST_UBLAS_INLINE 1073 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1074 typename self_type:: 1075 #endif rend() const1076 reverse_iterator1 rend () const { 1077 return reverse_iterator1 (begin ()); 1078 } 1079 #endif 1080 1081 // Indices 1082 BOOST_UBLAS_INLINE index1() const1083 size_type index1 () const { 1084 self_type &m = (*this) (); 1085 return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ()); 1086 } 1087 BOOST_UBLAS_INLINE index2() const1088 size_type index2 () const { 1089 self_type &m = (*this) (); 1090 return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ()); 1091 } 1092 1093 // Assignment 1094 BOOST_UBLAS_INLINE operator =(const iterator2 & it)1095 iterator2 &operator = (const iterator2 &it) { 1096 container_reference<self_type>::assign (&it ()); 1097 it_ = it.it_; 1098 return *this; 1099 } 1100 1101 // Comparison 1102 BOOST_UBLAS_INLINE operator ==(const iterator2 & it) const1103 bool operator == (const iterator2 &it) const { 1104 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1105 return it_ == it.it_; 1106 } 1107 BOOST_UBLAS_INLINE operator <(const iterator2 & it) const1108 bool operator < (const iterator2 &it) const { 1109 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1110 return it_ < it.it_; 1111 } 1112 1113 private: 1114 subiterator_type it_; 1115 1116 friend class const_iterator2; 1117 }; 1118 #endif 1119 1120 BOOST_UBLAS_INLINE begin2()1121 iterator2 begin2 () { 1122 return find2 (0, 0, 0); 1123 } 1124 BOOST_UBLAS_INLINE end2()1125 iterator2 end2 () { 1126 return find2 (0, 0, size2_); 1127 } 1128 1129 // Reverse iterators 1130 1131 BOOST_UBLAS_INLINE rbegin1() const1132 const_reverse_iterator1 rbegin1 () const { 1133 return const_reverse_iterator1 (end1 ()); 1134 } 1135 BOOST_UBLAS_INLINE crbegin1() const1136 const_reverse_iterator1 crbegin1 () const { 1137 return rbegin1 (); 1138 } 1139 BOOST_UBLAS_INLINE rend1() const1140 const_reverse_iterator1 rend1 () const { 1141 return const_reverse_iterator1 (begin1 ()); 1142 } 1143 BOOST_UBLAS_INLINE crend1() const1144 const_reverse_iterator1 crend1 () const { 1145 return rend1 (); 1146 } 1147 1148 BOOST_UBLAS_INLINE rbegin1()1149 reverse_iterator1 rbegin1 () { 1150 return reverse_iterator1 (end1 ()); 1151 } 1152 BOOST_UBLAS_INLINE rend1()1153 reverse_iterator1 rend1 () { 1154 return reverse_iterator1 (begin1 ()); 1155 } 1156 1157 BOOST_UBLAS_INLINE rbegin2() const1158 const_reverse_iterator2 rbegin2 () const { 1159 return const_reverse_iterator2 (end2 ()); 1160 } 1161 BOOST_UBLAS_INLINE crbegin2() const1162 const_reverse_iterator2 crbegin2 () const { 1163 return rbegin2 (); 1164 } 1165 BOOST_UBLAS_INLINE rend2() const1166 const_reverse_iterator2 rend2 () const { 1167 return const_reverse_iterator2 (begin2 ()); 1168 } 1169 BOOST_UBLAS_INLINE crend2() const1170 const_reverse_iterator2 crend2 () const { 1171 return rend2 (); 1172 } 1173 1174 BOOST_UBLAS_INLINE rbegin2()1175 reverse_iterator2 rbegin2 () { 1176 return reverse_iterator2 (end2 ()); 1177 } 1178 BOOST_UBLAS_INLINE rend2()1179 reverse_iterator2 rend2 () { 1180 return reverse_iterator2 (begin2 ()); 1181 } 1182 1183 // Serialization 1184 template<class Archive> serialize(Archive & ar,const unsigned int)1185 void serialize(Archive & ar, const unsigned int /* file_version */){ 1186 1187 // we need to copy to a collection_size_type to get a portable 1188 // and efficient serialization 1189 serialization::collection_size_type s1 (size1_); 1190 serialization::collection_size_type s2 (size2_); 1191 1192 // serialize the sizes 1193 ar & serialization::make_nvp("size1",s1) 1194 & serialization::make_nvp("size2",s2); 1195 1196 // copy the values back if loading 1197 if (Archive::is_loading::value) { 1198 size1_ = s1; 1199 size2_ = s2; 1200 } 1201 ar & serialization::make_nvp("data",data_); 1202 } 1203 1204 private: 1205 size_type size1_; 1206 size_type size2_; 1207 array_type data_; 1208 }; 1209 1210 1211 #ifdef BOOST_UBLAS_CPP_GE_2011 1212 /** \brief A fixed size dense matrix of values of type \c T. Equivalent to a c-style 2 dimensional array. 1213 * 1214 * For a \f$(m \times n)\f$-dimensional fixed_matrix and \f$ 0 \leq i < m, 0 \leq j < n\f$, every element \f$ m_{i,j} \f$ is mapped to 1215 * 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 1216 * the container for column major orientation. In a dense matrix all elements are represented in memory in a 1217 * contiguous chunk of memory by definition. 1218 * 1219 * Orientation and storage can also be specified, otherwise \c row_major and \c std::array are used. It is \b not 1220 * required by the storage container to initialize elements of the matrix. 1221 * 1222 * \tparam T the type of object stored in the matrix (like double, float, std::complex<double>, etc...) 1223 * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major 1224 * \tparam A the type of Storage array. Default is \c std::array<T, M*N> 1225 */ 1226 template<class T, std::size_t M, std::size_t N, class L, class A> 1227 class fixed_matrix: 1228 public matrix_container<fixed_matrix<T, M, N, L, A> > { 1229 1230 typedef T *pointer; 1231 typedef L layout_type; 1232 typedef fixed_matrix<T, M, N, L, A> self_type; 1233 public: 1234 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 1235 using matrix_container<self_type>::operator (); 1236 #endif 1237 typedef typename A::size_type size_type; 1238 typedef typename A::difference_type difference_type; 1239 typedef T value_type; 1240 typedef const T &const_reference; 1241 typedef T &reference; 1242 typedef A array_type; 1243 typedef const matrix_reference<const self_type> const_closure_type; 1244 typedef matrix_reference<self_type> closure_type; 1245 typedef vector<T, A> vector_temporary_type; 1246 typedef self_type matrix_temporary_type; 1247 typedef dense_tag storage_category; 1248 // This could be better for performance, 1249 // typedef typename unknown_orientation_tag orientation_category; 1250 // but others depend on the orientation information... 1251 typedef typename L::orientation_category orientation_category; 1252 1253 // Construction and destruction 1254 1255 /// Default dense fixed_matrix constructor. Make a dense fixed_matrix of size M x N 1256 BOOST_UBLAS_INLINE fixed_matrix()1257 fixed_matrix (): 1258 matrix_container<self_type> (), 1259 data_ () {} 1260 1261 /** Dense fixed_matrix constructor with defined initial value for all the matrix elements 1262 * \param init initial value assigned to all elements 1263 */ fixed_matrix(const value_type & init)1264 fixed_matrix (const value_type &init): 1265 matrix_container<self_type> (), 1266 data_ ( ) { 1267 data_.fill(init); 1268 } 1269 1270 /** Dense matrix constructor with defined initial data array 1271 * \param data array to copy into the matrix. Must have the same dimension as the matrix 1272 */ 1273 BOOST_UBLAS_INLINE fixed_matrix(const array_type & data)1274 fixed_matrix (const array_type &data): 1275 matrix_container<self_type> (), 1276 data_ (data) {} 1277 1278 /** Copy-constructor of a dense fixed_matrix 1279 * \param m is a dense fixed_matrix 1280 */ 1281 BOOST_UBLAS_INLINE fixed_matrix(const fixed_matrix & m)1282 fixed_matrix (const fixed_matrix &m): 1283 matrix_container<self_type> (), 1284 data_ (m.data_) {} 1285 1286 /** Copy-constructor of a dense matrix from a matrix expression 1287 * \param ae is a matrix expression 1288 */ 1289 template<class AE> 1290 BOOST_UBLAS_INLINE fixed_matrix(const matrix_expression<AE> & ae)1291 fixed_matrix (const matrix_expression<AE> &ae): 1292 matrix_container<self_type> (), 1293 data_ () { 1294 matrix_assign<scalar_assign> (*this, ae); 1295 } 1296 1297 /// \brief Construct a fixed_matrix from a list of values 1298 /// The list may be included in curly braces. Typical syntax is choices are : 1299 /// fixed_matrix<double, 2,2> v = { 1, 2, 3, 4 } or fixed_matrix<double,4> v( {1, 2, 3, 4} ) or fixed_matrix<double,2,2> v( 1, 2, 3, 4 ) 1300 template <typename... Types> 1301 BOOST_UBLAS_INLINE fixed_matrix(value_type v0,Types...vrest)1302 fixed_matrix(value_type v0, Types... vrest) : 1303 matrix_container<self_type> (), 1304 data_( array_type{ v0, vrest... } ) {} 1305 1306 // Accessors 1307 /** Return the number of rows of the fixed_matrix 1308 * You can also use the free size<>() function in operation/size.hpp as size<1>(m) where m is a fixed_matrix 1309 */ 1310 BOOST_UBLAS_INLINE size1() const1311 BOOST_CONSTEXPR size_type size1 () const { 1312 return M; 1313 } 1314 1315 /** Return the number of colums of the fixed_matrix 1316 * You can also use the free size<>() function in operation/size.hpp as size<2>(m) where m is a fixed_matrix 1317 */ 1318 BOOST_UBLAS_INLINE size2() const1319 BOOST_CONSTEXPR size_type size2 () const { 1320 return N; 1321 } 1322 1323 // Storage accessors 1324 /** Return a constant reference to the internal storage of a dense matrix, i.e. the raw data 1325 * It's type depends on the type used by the matrix to store its data 1326 */ 1327 BOOST_UBLAS_INLINE data() const1328 const array_type &data () const { 1329 return data_; 1330 } 1331 /** Return a reference to the internal storage of a dense fixed_matrix, i.e. the raw data 1332 * It's type depends on the type used by the fixed_matrix to store its data 1333 */ 1334 BOOST_UBLAS_INLINE data()1335 array_type &data () { 1336 return data_; 1337 } 1338 1339 1340 // Element access 1341 1342 /** Access a fixed_matrix element. Here we return a const reference 1343 * \param i the first coordinate of the element. By default it's the row 1344 * \param j the second coordinate of the element. By default it's the column 1345 * \return a const reference to the element 1346 */ 1347 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const1348 const_reference operator () (size_type i, size_type j) const { 1349 return data () [layout_type::element (i, M, j, N)]; // Fixme: add static lookup for element(...) i.e.: element<M, N>(i,j) 1350 } 1351 1352 /** Access a fixed_matrix element. Here we return a reference 1353 * \param i the first coordinate of the element. By default it's the row 1354 * \param j the second coordinate of the element. By default it's the column 1355 * \return a reference to the element 1356 */ 1357 BOOST_UBLAS_INLINE at_element(size_type i,size_type j)1358 reference at_element (size_type i, size_type j) { 1359 return data () [layout_type::element (i, M, j, N)]; 1360 } 1361 1362 /** Access a fixed_matrix element. Here we return a reference 1363 * \param i the first coordinate of the element. By default it's the row 1364 * \param j the second coordinate of the element. By default it's the column 1365 * \return a reference to the element 1366 */ 1367 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j)1368 reference operator () (size_type i, size_type j) { 1369 return at_element (i, j); 1370 } 1371 1372 // Element assignment 1373 1374 /** Change the value of a fixed_matrix element. Return back a reference to it 1375 * \param i the first coordinate of the element. By default it's the row 1376 * \param j the second coordinate of the element. By default it's the column 1377 * \param t the new value of the element 1378 * \return a reference to the newly changed element 1379 */ 1380 BOOST_UBLAS_INLINE insert_element(size_type i,size_type j,const_reference t)1381 reference insert_element (size_type i, size_type j, const_reference t) { 1382 return (at_element (i, j) = t); 1383 } 1384 1385 /** Erase the element 1386 * For most types (int, double, etc...) it means setting 0 (zero) the element at zero in fact. 1387 * For user-defined types, it could be another value if you decided it. Your type in that case must 1388 * contain a default null value. 1389 * \param i the first coordinate of the element. By default it's the row 1390 * \param j the second coordinate of the element. By default it's the column 1391 */ erase_element(size_type i,size_type j)1392 void erase_element (size_type i, size_type j) { 1393 at_element (i, j) = value_type/*zero*/(); 1394 } 1395 1396 // Zeroing 1397 /** Erase all elements in the fixed_matrix 1398 * For most types (int, double, etc...) it means writing 0 (zero) everywhere. 1399 * For user-defined types, it could be another value if you decided it. Your type in that case must 1400 * contain a default null value. 1401 */ 1402 BOOST_UBLAS_INLINE clear()1403 void clear () { 1404 std::fill (data ().begin (), data ().end (), value_type/*zero*/()); 1405 } 1406 1407 // Assignment 1408 #ifdef BOOST_UBLAS_MOVE_SEMANTICS 1409 1410 /*! @note "pass by value" the key idea to enable move semantics */ 1411 BOOST_UBLAS_INLINE operator =(fixed_matrix m)1412 fixed_matrix &operator = (fixed_matrix m) { 1413 assign_temporary(m); 1414 return *this; 1415 } 1416 #else 1417 BOOST_UBLAS_INLINE operator =(const fixed_matrix & m)1418 fixed_matrix &operator = (const fixed_matrix &m) { 1419 data () = m.data (); 1420 return *this; 1421 } 1422 #endif 1423 template<class C> // Container assignment without temporary 1424 BOOST_UBLAS_INLINE operator =(const matrix_container<C> & m)1425 fixed_matrix &operator = (const matrix_container<C> &m) { 1426 resize (m ().size1 (), m ().size2 (), false); 1427 assign (m); 1428 return *this; 1429 } 1430 BOOST_UBLAS_INLINE assign_temporary(fixed_matrix & m)1431 fixed_matrix &assign_temporary (fixed_matrix &m) { 1432 swap (m); 1433 return *this; 1434 } 1435 template<class AE> 1436 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)1437 fixed_matrix &operator = (const matrix_expression<AE> &ae) { 1438 self_type temporary (ae); 1439 return assign_temporary (temporary); 1440 } 1441 template<class AE> 1442 BOOST_UBLAS_INLINE assign(const matrix_expression<AE> & ae)1443 fixed_matrix &assign (const matrix_expression<AE> &ae) { 1444 matrix_assign<scalar_assign> (*this, ae); 1445 return *this; 1446 } 1447 template<class AE> 1448 BOOST_UBLAS_INLINE operator +=(const matrix_expression<AE> & ae)1449 fixed_matrix& operator += (const matrix_expression<AE> &ae) { 1450 self_type temporary (*this + ae); 1451 return assign_temporary (temporary); 1452 } 1453 template<class C> // Container assignment without temporary 1454 BOOST_UBLAS_INLINE operator +=(const matrix_container<C> & m)1455 fixed_matrix &operator += (const matrix_container<C> &m) { 1456 plus_assign (m); 1457 return *this; 1458 } 1459 template<class AE> 1460 BOOST_UBLAS_INLINE plus_assign(const matrix_expression<AE> & ae)1461 fixed_matrix &plus_assign (const matrix_expression<AE> &ae) { 1462 matrix_assign<scalar_plus_assign> (*this, ae); 1463 return *this; 1464 } 1465 template<class AE> 1466 BOOST_UBLAS_INLINE operator -=(const matrix_expression<AE> & ae)1467 fixed_matrix& operator -= (const matrix_expression<AE> &ae) { 1468 self_type temporary (*this - ae); 1469 return assign_temporary (temporary); 1470 } 1471 template<class C> // Container assignment without temporary 1472 BOOST_UBLAS_INLINE operator -=(const matrix_container<C> & m)1473 fixed_matrix &operator -= (const matrix_container<C> &m) { 1474 minus_assign (m); 1475 return *this; 1476 } 1477 template<class AE> 1478 BOOST_UBLAS_INLINE minus_assign(const matrix_expression<AE> & ae)1479 fixed_matrix &minus_assign (const matrix_expression<AE> &ae) { 1480 matrix_assign<scalar_minus_assign> (*this, ae); 1481 return *this; 1482 } 1483 template<class AT> 1484 BOOST_UBLAS_INLINE operator *=(const AT & at)1485 fixed_matrix& operator *= (const AT &at) { 1486 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 1487 return *this; 1488 } 1489 template<class AT> 1490 BOOST_UBLAS_INLINE operator /=(const AT & at)1491 fixed_matrix& operator /= (const AT &at) { 1492 matrix_assign_scalar<scalar_divides_assign> (*this, at); 1493 return *this; 1494 } 1495 1496 // Swapping 1497 BOOST_UBLAS_INLINE swap(fixed_matrix & m)1498 void swap (fixed_matrix &m) { 1499 if (this != &m) { 1500 data ().swap (m.data ()); 1501 } 1502 } 1503 BOOST_UBLAS_INLINE swap(fixed_matrix & m1,fixed_matrix & m2)1504 friend void swap (fixed_matrix &m1, fixed_matrix &m2) { 1505 m1.swap (m2); 1506 } 1507 1508 // Iterator types 1509 private: 1510 // Use the storage array iterator 1511 typedef typename A::const_iterator const_subiterator_type; 1512 typedef typename A::iterator subiterator_type; 1513 1514 public: 1515 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1516 typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1; 1517 typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2; 1518 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1; 1519 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2; 1520 #else 1521 class const_iterator1; 1522 class iterator1; 1523 class const_iterator2; 1524 class iterator2; 1525 #endif 1526 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 1527 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 1528 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 1529 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 1530 1531 // Element lookup 1532 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j) const1533 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const { 1534 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1535 return const_iterator1 (*this, i, j); 1536 #else 1537 return const_iterator1 (*this, data ().begin () + layout_type::address (i, M, j, N)); 1538 #endif 1539 } 1540 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j)1541 iterator1 find1 (int /* rank */, size_type i, size_type j) { 1542 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1543 return iterator1 (*this, i, j); 1544 #else 1545 return iterator1 (*this, data ().begin () + layout_type::address (i, M, j, N)); 1546 #endif 1547 } 1548 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j) const1549 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const { 1550 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1551 return const_iterator2 (*this, i, j); 1552 #else 1553 return const_iterator2 (*this, data ().begin () + layout_type::address (i, M, j, N)); 1554 #endif 1555 } 1556 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j)1557 iterator2 find2 (int /* rank */, size_type i, size_type j) { 1558 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1559 return iterator2 (*this, i, j); 1560 #else 1561 return iterator2 (*this, data ().begin () + layout_type::address (i, M, j, N)); 1562 #endif 1563 } 1564 1565 1566 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 1567 class const_iterator1: 1568 public container_const_reference<fixed_matrix>, 1569 public random_access_iterator_base<dense_random_access_iterator_tag, 1570 const_iterator1, value_type> { 1571 public: 1572 typedef typename fixed_matrix::value_type value_type; 1573 typedef typename fixed_matrix::difference_type difference_type; 1574 typedef typename fixed_matrix::const_reference reference; 1575 typedef const typename fixed_matrix::pointer pointer; 1576 1577 typedef const_iterator2 dual_iterator_type; 1578 typedef const_reverse_iterator2 dual_reverse_iterator_type; 1579 1580 // Construction and destruction 1581 BOOST_UBLAS_INLINE const_iterator1()1582 const_iterator1 (): 1583 container_const_reference<self_type> (), it_ () {} 1584 BOOST_UBLAS_INLINE const_iterator1(const self_type & m,const const_subiterator_type & it)1585 const_iterator1 (const self_type &m, const const_subiterator_type &it): 1586 container_const_reference<self_type> (m), it_ (it) {} 1587 BOOST_UBLAS_INLINE const_iterator1(const iterator1 & it)1588 const_iterator1 (const iterator1 &it): 1589 container_const_reference<self_type> (it ()), it_ (it.it_) {} 1590 1591 // Arithmetic 1592 BOOST_UBLAS_INLINE operator ++()1593 const_iterator1 &operator ++ () { 1594 layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ()); 1595 return *this; 1596 } 1597 BOOST_UBLAS_INLINE operator --()1598 const_iterator1 &operator -- () { 1599 layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ()); 1600 return *this; 1601 } 1602 BOOST_UBLAS_INLINE operator +=(difference_type n)1603 const_iterator1 &operator += (difference_type n) { 1604 layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 1605 return *this; 1606 } 1607 BOOST_UBLAS_INLINE operator -=(difference_type n)1608 const_iterator1 &operator -= (difference_type n) { 1609 layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 1610 return *this; 1611 } 1612 BOOST_UBLAS_INLINE operator -(const const_iterator1 & it) const1613 difference_type operator - (const const_iterator1 &it) const { 1614 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1615 return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ()); 1616 } 1617 1618 // Dereference 1619 BOOST_UBLAS_INLINE operator *() const1620 const_reference operator * () const { 1621 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 1622 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 1623 return *it_; 1624 } 1625 BOOST_UBLAS_INLINE operator [](difference_type n) const1626 const_reference operator [] (difference_type n) const { 1627 return *(*this + n); 1628 } 1629 1630 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 1631 BOOST_UBLAS_INLINE 1632 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1633 typename self_type:: 1634 #endif begin() const1635 const_iterator2 begin () const { 1636 const self_type &m = (*this) (); 1637 return m.find2 (1, index1 (), 0); 1638 } 1639 BOOST_UBLAS_INLINE 1640 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1641 typename self_type:: 1642 #endif cbegin() const1643 const_iterator2 cbegin () const { 1644 return begin (); 1645 } 1646 BOOST_UBLAS_INLINE 1647 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1648 typename self_type:: 1649 #endif end() const1650 const_iterator2 end () const { 1651 const self_type &m = (*this) (); 1652 return m.find2 (1, index1 (), m.size2 ()); 1653 } 1654 BOOST_UBLAS_INLINE 1655 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1656 typename self_type:: 1657 #endif cend() const1658 const_iterator2 cend () const { 1659 return end (); 1660 } 1661 BOOST_UBLAS_INLINE 1662 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1663 typename self_type:: 1664 #endif rbegin() const1665 const_reverse_iterator2 rbegin () const { 1666 return const_reverse_iterator2 (end ()); 1667 } 1668 BOOST_UBLAS_INLINE 1669 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1670 typename self_type:: 1671 #endif crbegin() const1672 const_reverse_iterator2 crbegin () const { 1673 return rbegin (); 1674 } 1675 BOOST_UBLAS_INLINE 1676 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1677 typename self_type:: 1678 #endif rend() const1679 const_reverse_iterator2 rend () const { 1680 return const_reverse_iterator2 (begin ()); 1681 } 1682 BOOST_UBLAS_INLINE 1683 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1684 typename self_type:: 1685 #endif crend() const1686 const_reverse_iterator2 crend () const { 1687 return rend (); 1688 } 1689 #endif 1690 1691 // Indices 1692 BOOST_UBLAS_INLINE index1() const1693 size_type index1 () const { 1694 const self_type &m = (*this) (); 1695 return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ()); 1696 } 1697 BOOST_UBLAS_INLINE index2() const1698 size_type index2 () const { 1699 const self_type &m = (*this) (); 1700 return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ()); 1701 } 1702 1703 // Assignment 1704 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)1705 const_iterator1 &operator = (const const_iterator1 &it) { 1706 container_const_reference<self_type>::assign (&it ()); 1707 it_ = it.it_; 1708 return *this; 1709 } 1710 1711 // Comparison 1712 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const1713 bool operator == (const const_iterator1 &it) const { 1714 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1715 return it_ == it.it_; 1716 } 1717 BOOST_UBLAS_INLINE operator <(const const_iterator1 & it) const1718 bool operator < (const const_iterator1 &it) const { 1719 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1720 return it_ < it.it_; 1721 } 1722 1723 private: 1724 const_subiterator_type it_; 1725 1726 friend class iterator1; 1727 }; 1728 #endif 1729 1730 BOOST_UBLAS_INLINE begin1() const1731 const_iterator1 begin1 () const { 1732 return find1 (0, 0, 0); 1733 } 1734 BOOST_UBLAS_INLINE cbegin1() const1735 const_iterator1 cbegin1 () const { 1736 return begin1 (); 1737 } 1738 BOOST_UBLAS_INLINE end1() const1739 const_iterator1 end1 () const { 1740 return find1 (0, M, 0); 1741 } 1742 BOOST_UBLAS_INLINE cend1() const1743 const_iterator1 cend1 () const { 1744 return end1 (); 1745 } 1746 1747 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 1748 class iterator1: 1749 public container_reference<fixed_matrix>, 1750 public random_access_iterator_base<dense_random_access_iterator_tag, 1751 iterator1, value_type> { 1752 public: 1753 typedef typename fixed_matrix::value_type value_type; 1754 typedef typename fixed_matrix::difference_type difference_type; 1755 typedef typename fixed_matrix::reference reference; 1756 typedef typename fixed_matrix::pointer pointer; 1757 1758 typedef iterator2 dual_iterator_type; 1759 typedef reverse_iterator2 dual_reverse_iterator_type; 1760 1761 // Construction and destruction 1762 BOOST_UBLAS_INLINE iterator1()1763 iterator1 (): 1764 container_reference<self_type> (), it_ () {} 1765 BOOST_UBLAS_INLINE iterator1(self_type & m,const subiterator_type & it)1766 iterator1 (self_type &m, const subiterator_type &it): 1767 container_reference<self_type> (m), it_ (it) {} 1768 1769 // Arithmetic 1770 BOOST_UBLAS_INLINE operator ++()1771 iterator1 &operator ++ () { 1772 layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ()); 1773 return *this; 1774 } 1775 BOOST_UBLAS_INLINE operator --()1776 iterator1 &operator -- () { 1777 layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ()); 1778 return *this; 1779 } 1780 BOOST_UBLAS_INLINE operator +=(difference_type n)1781 iterator1 &operator += (difference_type n) { 1782 layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 1783 return *this; 1784 } 1785 BOOST_UBLAS_INLINE operator -=(difference_type n)1786 iterator1 &operator -= (difference_type n) { 1787 layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 1788 return *this; 1789 } 1790 BOOST_UBLAS_INLINE operator -(const iterator1 & it) const1791 difference_type operator - (const iterator1 &it) const { 1792 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1793 return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ()); 1794 } 1795 1796 // Dereference 1797 BOOST_UBLAS_INLINE operator *() const1798 reference operator * () const { 1799 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 1800 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 1801 return *it_; 1802 } 1803 BOOST_UBLAS_INLINE operator [](difference_type n) const1804 reference operator [] (difference_type n) const { 1805 return *(*this + n); 1806 } 1807 1808 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 1809 BOOST_UBLAS_INLINE 1810 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1811 typename self_type:: 1812 #endif begin() const1813 iterator2 begin () const { 1814 self_type &m = (*this) (); 1815 return m.find2 (1, index1 (), 0); 1816 } 1817 BOOST_UBLAS_INLINE 1818 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1819 typename self_type:: 1820 #endif end() const1821 iterator2 end () const { 1822 self_type &m = (*this) (); 1823 return m.find2 (1, index1 (), m.size2 ()); 1824 } 1825 BOOST_UBLAS_INLINE 1826 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1827 typename self_type:: 1828 #endif rbegin() const1829 reverse_iterator2 rbegin () const { 1830 return reverse_iterator2 (end ()); 1831 } 1832 BOOST_UBLAS_INLINE 1833 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1834 typename self_type:: 1835 #endif rend() const1836 reverse_iterator2 rend () const { 1837 return reverse_iterator2 (begin ()); 1838 } 1839 #endif 1840 1841 // Indices 1842 BOOST_UBLAS_INLINE index1() const1843 size_type index1 () const { 1844 self_type &m = (*this) (); 1845 return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ()); 1846 } 1847 BOOST_UBLAS_INLINE index2() const1848 size_type index2 () const { 1849 self_type &m = (*this) (); 1850 return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ()); 1851 } 1852 1853 // Assignment 1854 BOOST_UBLAS_INLINE operator =(const iterator1 & it)1855 iterator1 &operator = (const iterator1 &it) { 1856 container_reference<self_type>::assign (&it ()); 1857 it_ = it.it_; 1858 return *this; 1859 } 1860 1861 // Comparison 1862 BOOST_UBLAS_INLINE operator ==(const iterator1 & it) const1863 bool operator == (const iterator1 &it) const { 1864 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1865 return it_ == it.it_; 1866 } 1867 BOOST_UBLAS_INLINE operator <(const iterator1 & it) const1868 bool operator < (const iterator1 &it) const { 1869 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1870 return it_ < it.it_; 1871 } 1872 1873 private: 1874 subiterator_type it_; 1875 1876 friend class const_iterator1; 1877 }; 1878 #endif 1879 1880 BOOST_UBLAS_INLINE begin1()1881 iterator1 begin1 () { 1882 return find1 (0, 0, 0); 1883 } 1884 BOOST_UBLAS_INLINE end1()1885 iterator1 end1 () { 1886 return find1 (0, M, 0); 1887 } 1888 1889 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 1890 class const_iterator2: 1891 public container_const_reference<fixed_matrix>, 1892 public random_access_iterator_base<dense_random_access_iterator_tag, 1893 const_iterator2, value_type> { 1894 public: 1895 typedef typename fixed_matrix::value_type value_type; 1896 typedef typename fixed_matrix::difference_type difference_type; 1897 typedef typename fixed_matrix::const_reference reference; 1898 typedef const typename fixed_matrix::pointer pointer; 1899 1900 typedef const_iterator1 dual_iterator_type; 1901 typedef const_reverse_iterator1 dual_reverse_iterator_type; 1902 1903 // Construction and destruction 1904 BOOST_UBLAS_INLINE const_iterator2()1905 const_iterator2 (): 1906 container_const_reference<self_type> (), it_ () {} 1907 BOOST_UBLAS_INLINE const_iterator2(const self_type & m,const const_subiterator_type & it)1908 const_iterator2 (const self_type &m, const const_subiterator_type &it): 1909 container_const_reference<self_type> (m), it_ (it) {} 1910 BOOST_UBLAS_INLINE const_iterator2(const iterator2 & it)1911 const_iterator2 (const iterator2 &it): 1912 container_const_reference<self_type> (it ()), it_ (it.it_) {} 1913 1914 // Arithmetic 1915 BOOST_UBLAS_INLINE operator ++()1916 const_iterator2 &operator ++ () { 1917 layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ()); 1918 return *this; 1919 } 1920 BOOST_UBLAS_INLINE operator --()1921 const_iterator2 &operator -- () { 1922 layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ()); 1923 return *this; 1924 } 1925 BOOST_UBLAS_INLINE operator +=(difference_type n)1926 const_iterator2 &operator += (difference_type n) { 1927 layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 1928 return *this; 1929 } 1930 BOOST_UBLAS_INLINE operator -=(difference_type n)1931 const_iterator2 &operator -= (difference_type n) { 1932 layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 1933 return *this; 1934 } 1935 BOOST_UBLAS_INLINE operator -(const const_iterator2 & it) const1936 difference_type operator - (const const_iterator2 &it) const { 1937 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1938 return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ()); 1939 } 1940 1941 // Dereference 1942 BOOST_UBLAS_INLINE operator *() const1943 const_reference operator * () const { 1944 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 1945 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 1946 return *it_; 1947 } 1948 BOOST_UBLAS_INLINE operator [](difference_type n) const1949 const_reference operator [] (difference_type n) const { 1950 return *(*this + n); 1951 } 1952 1953 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 1954 BOOST_UBLAS_INLINE 1955 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1956 typename self_type:: 1957 #endif begin() const1958 const_iterator1 begin () const { 1959 const self_type &m = (*this) (); 1960 return m.find1 (1, 0, index2 ()); 1961 } 1962 BOOST_UBLAS_INLINE 1963 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1964 typename self_type:: 1965 #endif cbegin() const1966 const_iterator1 cbegin () const { 1967 return begin (); 1968 } 1969 BOOST_UBLAS_INLINE 1970 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1971 typename self_type:: 1972 #endif end() const1973 const_iterator1 end () const { 1974 const self_type &m = (*this) (); 1975 return m.find1 (1, m.size1 (), index2 ()); 1976 } 1977 BOOST_UBLAS_INLINE 1978 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1979 typename self_type:: 1980 #endif cend() const1981 const_iterator1 cend () const { 1982 return end (); 1983 } 1984 BOOST_UBLAS_INLINE 1985 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1986 typename self_type:: 1987 #endif rbegin() const1988 const_reverse_iterator1 rbegin () const { 1989 return const_reverse_iterator1 (end ()); 1990 } 1991 BOOST_UBLAS_INLINE 1992 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1993 typename self_type:: 1994 #endif crbegin() const1995 const_reverse_iterator1 crbegin () const { 1996 return rbegin (); 1997 } 1998 BOOST_UBLAS_INLINE 1999 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2000 typename self_type:: 2001 #endif rend() const2002 const_reverse_iterator1 rend () const { 2003 return const_reverse_iterator1 (begin ()); 2004 } 2005 BOOST_UBLAS_INLINE 2006 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2007 typename self_type:: 2008 #endif crend() const2009 const_reverse_iterator1 crend () const { 2010 return rend (); 2011 } 2012 #endif 2013 2014 // Indices 2015 BOOST_UBLAS_INLINE index1() const2016 size_type index1 () const { 2017 const self_type &m = (*this) (); 2018 return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ()); 2019 } 2020 BOOST_UBLAS_INLINE index2() const2021 size_type index2 () const { 2022 const self_type &m = (*this) (); 2023 return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ()); 2024 } 2025 2026 // Assignment 2027 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)2028 const_iterator2 &operator = (const const_iterator2 &it) { 2029 container_const_reference<self_type>::assign (&it ()); 2030 it_ = it.it_; 2031 return *this; 2032 } 2033 2034 // Comparison 2035 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const2036 bool operator == (const const_iterator2 &it) const { 2037 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2038 return it_ == it.it_; 2039 } 2040 BOOST_UBLAS_INLINE operator <(const const_iterator2 & it) const2041 bool operator < (const const_iterator2 &it) const { 2042 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2043 return it_ < it.it_; 2044 } 2045 2046 private: 2047 const_subiterator_type it_; 2048 2049 friend class iterator2; 2050 }; 2051 #endif 2052 2053 BOOST_UBLAS_INLINE begin2() const2054 const_iterator2 begin2 () const { 2055 return find2 (0, 0, 0); 2056 } 2057 BOOST_UBLAS_INLINE cbegin2() const2058 const_iterator2 cbegin2 () const { 2059 return begin2 (); 2060 } 2061 BOOST_UBLAS_INLINE end2() const2062 const_iterator2 end2 () const { 2063 return find2 (0, 0, N); 2064 } 2065 BOOST_UBLAS_INLINE cend2() const2066 const_iterator2 cend2 () const { 2067 return end2 (); 2068 } 2069 2070 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 2071 class iterator2: 2072 public container_reference<fixed_matrix>, 2073 public random_access_iterator_base<dense_random_access_iterator_tag, 2074 iterator2, value_type> { 2075 public: 2076 typedef typename fixed_matrix::value_type value_type; 2077 typedef typename fixed_matrix::difference_type difference_type; 2078 typedef typename fixed_matrix::reference reference; 2079 typedef typename fixed_matrix::pointer pointer; 2080 2081 typedef iterator1 dual_iterator_type; 2082 typedef reverse_iterator1 dual_reverse_iterator_type; 2083 2084 // Construction and destruction 2085 BOOST_UBLAS_INLINE iterator2()2086 iterator2 (): 2087 container_reference<self_type> (), it_ () {} 2088 BOOST_UBLAS_INLINE iterator2(self_type & m,const subiterator_type & it)2089 iterator2 (self_type &m, const subiterator_type &it): 2090 container_reference<self_type> (m), it_ (it) {} 2091 2092 // Arithmetic 2093 BOOST_UBLAS_INLINE operator ++()2094 iterator2 &operator ++ () { 2095 layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ()); 2096 return *this; 2097 } 2098 BOOST_UBLAS_INLINE operator --()2099 iterator2 &operator -- () { 2100 layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ()); 2101 return *this; 2102 } 2103 BOOST_UBLAS_INLINE operator +=(difference_type n)2104 iterator2 &operator += (difference_type n) { 2105 layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 2106 return *this; 2107 } 2108 BOOST_UBLAS_INLINE operator -=(difference_type n)2109 iterator2 &operator -= (difference_type n) { 2110 layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ()); 2111 return *this; 2112 } 2113 BOOST_UBLAS_INLINE operator -(const iterator2 & it) const2114 difference_type operator - (const iterator2 &it) const { 2115 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2116 return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ()); 2117 } 2118 2119 // Dereference 2120 BOOST_UBLAS_INLINE operator *() const2121 reference operator * () const { 2122 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 2123 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 2124 return *it_; 2125 } 2126 BOOST_UBLAS_INLINE operator [](difference_type n) const2127 reference operator [] (difference_type n) const { 2128 return *(*this + n); 2129 } 2130 2131 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 2132 BOOST_UBLAS_INLINE 2133 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2134 typename self_type:: 2135 #endif begin() const2136 iterator1 begin () const { 2137 self_type &m = (*this) (); 2138 return m.find1 (1, 0, index2 ()); 2139 } 2140 BOOST_UBLAS_INLINE 2141 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2142 typename self_type:: 2143 #endif end() const2144 iterator1 end () const { 2145 self_type &m = (*this) (); 2146 return m.find1 (1, m.size1 (), index2 ()); 2147 } 2148 BOOST_UBLAS_INLINE 2149 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2150 typename self_type:: 2151 #endif rbegin() const2152 reverse_iterator1 rbegin () const { 2153 return reverse_iterator1 (end ()); 2154 } 2155 BOOST_UBLAS_INLINE 2156 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2157 typename self_type:: 2158 #endif rend() const2159 reverse_iterator1 rend () const { 2160 return reverse_iterator1 (begin ()); 2161 } 2162 #endif 2163 2164 // Indices 2165 BOOST_UBLAS_INLINE index1() const2166 size_type index1 () const { 2167 self_type &m = (*this) (); 2168 return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ()); 2169 } 2170 BOOST_UBLAS_INLINE index2() const2171 size_type index2 () const { 2172 self_type &m = (*this) (); 2173 return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ()); 2174 } 2175 2176 // Assignment 2177 BOOST_UBLAS_INLINE operator =(const iterator2 & it)2178 iterator2 &operator = (const iterator2 &it) { 2179 container_reference<self_type>::assign (&it ()); 2180 it_ = it.it_; 2181 return *this; 2182 } 2183 2184 // Comparison 2185 BOOST_UBLAS_INLINE operator ==(const iterator2 & it) const2186 bool operator == (const iterator2 &it) const { 2187 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2188 return it_ == it.it_; 2189 } 2190 BOOST_UBLAS_INLINE operator <(const iterator2 & it) const2191 bool operator < (const iterator2 &it) const { 2192 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2193 return it_ < it.it_; 2194 } 2195 2196 private: 2197 subiterator_type it_; 2198 2199 friend class const_iterator2; 2200 }; 2201 #endif 2202 2203 BOOST_UBLAS_INLINE begin2()2204 iterator2 begin2 () { 2205 return find2 (0, 0, 0); 2206 } 2207 BOOST_UBLAS_INLINE end2()2208 iterator2 end2 () { 2209 return find2 (0, 0, N); 2210 } 2211 2212 // Reverse iterators 2213 2214 BOOST_UBLAS_INLINE rbegin1() const2215 const_reverse_iterator1 rbegin1 () const { 2216 return const_reverse_iterator1 (end1 ()); 2217 } 2218 BOOST_UBLAS_INLINE crbegin1() const2219 const_reverse_iterator1 crbegin1 () const { 2220 return rbegin1 (); 2221 } 2222 BOOST_UBLAS_INLINE rend1() const2223 const_reverse_iterator1 rend1 () const { 2224 return const_reverse_iterator1 (begin1 ()); 2225 } 2226 BOOST_UBLAS_INLINE crend1() const2227 const_reverse_iterator1 crend1 () const { 2228 return rend1 (); 2229 } 2230 2231 BOOST_UBLAS_INLINE rbegin1()2232 reverse_iterator1 rbegin1 () { 2233 return reverse_iterator1 (end1 ()); 2234 } 2235 BOOST_UBLAS_INLINE rend1()2236 reverse_iterator1 rend1 () { 2237 return reverse_iterator1 (begin1 ()); 2238 } 2239 2240 BOOST_UBLAS_INLINE rbegin2() const2241 const_reverse_iterator2 rbegin2 () const { 2242 return const_reverse_iterator2 (end2 ()); 2243 } 2244 BOOST_UBLAS_INLINE crbegin2() const2245 const_reverse_iterator2 crbegin2 () const { 2246 return rbegin2 (); 2247 } 2248 BOOST_UBLAS_INLINE rend2() const2249 const_reverse_iterator2 rend2 () const { 2250 return const_reverse_iterator2 (begin2 ()); 2251 } 2252 BOOST_UBLAS_INLINE crend2() const2253 const_reverse_iterator2 crend2 () const { 2254 return rend2 (); 2255 } 2256 2257 BOOST_UBLAS_INLINE rbegin2()2258 reverse_iterator2 rbegin2 () { 2259 return reverse_iterator2 (end2 ()); 2260 } 2261 BOOST_UBLAS_INLINE rend2()2262 reverse_iterator2 rend2 () { 2263 return reverse_iterator2 (begin2 ()); 2264 } 2265 2266 // Serialization 2267 template<class Archive> serialize(Archive & ar,const unsigned int)2268 void serialize(Archive & ar, const unsigned int /* file_version */){ 2269 ar & serialization::make_nvp("data",data_); 2270 } 2271 2272 private: 2273 array_type data_; 2274 }; 2275 2276 #endif // BOOST_UBLAS_CPP_GE_2011 2277 2278 /** \brief A dense matrix of values of type \c T with a variable size bounded to a maximum of \f$M\f$ by \f$N\f$. 2279 * 2280 * 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 2281 * 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 2282 * of the container for column major orientation. Finally in a dense matrix all elements are represented in memory 2283 * in a contiguous chunk of memory. 2284 * 2285 * Orientation can be specified. Default is \c row_major 2286 * The default constructor creates the matrix with size \f$M\f$ by \f$N\f$. Elements are constructed by the storage 2287 * type \c bounded_array, which need not initialise their value. 2288 * 2289 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...) 2290 * \tparam M maximum and default number of rows (if not specified at construction) 2291 * \tparam N maximum and default number of columns (if not specified at construction) 2292 * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major 2293 */ 2294 template<class T, std::size_t M, std::size_t N, class L> 2295 class bounded_matrix: 2296 public matrix<T, L, bounded_array<T, M * N> > { 2297 2298 typedef matrix<T, L, bounded_array<T, M * N> > matrix_type; 2299 public: 2300 typedef typename matrix_type::size_type size_type; 2301 static const size_type max_size1 = M; 2302 static const size_type max_size2 = N; 2303 2304 // Construction and destruction 2305 BOOST_UBLAS_INLINE bounded_matrix()2306 bounded_matrix (): 2307 matrix_type (M, N) {} 2308 BOOST_UBLAS_INLINE bounded_matrix(size_type size1,size_type size2)2309 bounded_matrix (size_type size1, size_type size2): 2310 matrix_type (size1, size2) {} 2311 BOOST_UBLAS_INLINE bounded_matrix(const bounded_matrix & m)2312 bounded_matrix (const bounded_matrix &m): 2313 matrix_type (m) {} 2314 template<class A2> // Allow matrix<T, L, bounded_array<M,N> > construction 2315 BOOST_UBLAS_INLINE bounded_matrix(const matrix<T,L,A2> & m)2316 bounded_matrix (const matrix<T, L, A2> &m): 2317 matrix_type (m) {} 2318 template<class AE> 2319 BOOST_UBLAS_INLINE bounded_matrix(const matrix_expression<AE> & ae)2320 bounded_matrix (const matrix_expression<AE> &ae): 2321 matrix_type (ae) {} 2322 BOOST_UBLAS_INLINE ~bounded_matrix()2323 ~bounded_matrix () {} 2324 2325 // Assignment 2326 #ifdef BOOST_UBLAS_MOVE_SEMANTICS 2327 2328 /*! @note "pass by value" the key idea to enable move semantics */ 2329 BOOST_UBLAS_INLINE operator =(bounded_matrix m)2330 bounded_matrix &operator = (bounded_matrix m) { 2331 matrix_type::operator = (m); 2332 return *this; 2333 } 2334 #else 2335 BOOST_UBLAS_INLINE operator =(const bounded_matrix & m)2336 bounded_matrix &operator = (const bounded_matrix &m) { 2337 matrix_type::operator = (m); 2338 return *this; 2339 } 2340 #endif 2341 template<class L2, class A2> // Generic matrix assignment 2342 BOOST_UBLAS_INLINE operator =(const matrix<T,L2,A2> & m)2343 bounded_matrix &operator = (const matrix<T, L2, A2> &m) { 2344 matrix_type::operator = (m); 2345 return *this; 2346 } 2347 template<class C> // Container assignment without temporary 2348 BOOST_UBLAS_INLINE operator =(const matrix_container<C> & m)2349 bounded_matrix &operator = (const matrix_container<C> &m) { 2350 matrix_type::operator = (m); 2351 return *this; 2352 } 2353 template<class AE> 2354 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)2355 bounded_matrix &operator = (const matrix_expression<AE> &ae) { 2356 matrix_type::operator = (ae); 2357 return *this; 2358 } 2359 }; 2360 2361 2362 /** \brief A dense matrix of values of type \c T stored as a vector of vectors. 2363 * 2364 * Rows or columns are not stored into contiguous chunks of memory but data inside rows (or columns) are. 2365 * Orientation and storage can also be specified, otherwise a row major and unbounded arrays are used. 2366 * The data is stored as a vector of vectors, meaning that rows or columns might not be stored into contiguous chunks 2367 * of memory. Orientation and storage can also be specified, otherwise a row major and unbounded arrays are used. 2368 * The storage type defaults to \c unbounded_array<unbounded_array<T>> and orientation is \c row_major. It is \b not 2369 * required by the storage to initialize elements of the matrix. For a \f$(m \times n)\f$-dimensional matrix and 2370 * \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 2371 * container for row major orientation or the \f$(i + j.m)\f$-th element of the container for column major orientation. 2372 * 2373 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...) 2374 * \tparam L the storage organization. It can be either \c row_major or \c column_major. By default it is \c row_major 2375 * \tparam A the type of Storage array. By default, it is an \unbounded_array<unbounder_array<T>> 2376 */ 2377 template<class T, class L, class A> 2378 class vector_of_vector: 2379 public matrix_container<vector_of_vector<T, L, A> > { 2380 2381 typedef T *pointer; 2382 typedef L layout_type; 2383 typedef vector_of_vector<T, L, A> self_type; 2384 public: 2385 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 2386 using matrix_container<self_type>::operator (); 2387 #endif 2388 typedef typename A::size_type size_type; 2389 typedef typename A::difference_type difference_type; 2390 typedef T value_type; 2391 typedef const T &const_reference; 2392 typedef T &reference; 2393 typedef A array_type; 2394 typedef const matrix_reference<const self_type> const_closure_type; 2395 typedef matrix_reference<self_type> closure_type; 2396 typedef vector<T, typename A::value_type> vector_temporary_type; 2397 typedef self_type matrix_temporary_type; 2398 typedef dense_tag storage_category; 2399 // This could be better for performance, 2400 // typedef typename unknown_orientation_tag orientation_category; 2401 // but others depend on the orientation information... 2402 typedef typename L::orientation_category orientation_category; 2403 2404 // Construction and destruction 2405 BOOST_UBLAS_INLINE vector_of_vector()2406 vector_of_vector (): 2407 matrix_container<self_type> (), 2408 size1_ (0), size2_ (0), data_ (1) {} 2409 BOOST_UBLAS_INLINE vector_of_vector(size_type size1,size_type size2)2410 vector_of_vector (size_type size1, size_type size2): 2411 matrix_container<self_type> (), 2412 size1_ (size1), size2_ (size2), data_ (1) { 2413 resize (size1, size2, true); 2414 } 2415 BOOST_UBLAS_INLINE vector_of_vector(const vector_of_vector & m)2416 vector_of_vector (const vector_of_vector &m): 2417 matrix_container<self_type> (), 2418 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {} 2419 template<class AE> 2420 BOOST_UBLAS_INLINE vector_of_vector(const matrix_expression<AE> & ae)2421 vector_of_vector (const matrix_expression<AE> &ae): 2422 matrix_container<self_type> (), 2423 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) { 2424 for (size_type k = 0; k < layout_type::size_M (size1_, size2_); ++ k) 2425 data ()[k].resize (layout_type::size_m (size1_, size2_)); 2426 matrix_assign<scalar_assign> (*this, ae); 2427 } 2428 2429 // Accessors 2430 BOOST_UBLAS_INLINE size1() const2431 size_type size1 () const { 2432 return size1_; 2433 } 2434 BOOST_UBLAS_INLINE size2() const2435 size_type size2 () const { 2436 return size2_; 2437 } 2438 2439 // Storage accessors 2440 BOOST_UBLAS_INLINE data() const2441 const array_type &data () const { 2442 return data_; 2443 } 2444 BOOST_UBLAS_INLINE data()2445 array_type &data () { 2446 return data_; 2447 } 2448 2449 // Resizing 2450 BOOST_UBLAS_INLINE resize(size_type size1,size_type size2,bool preserve=true)2451 void resize (size_type size1, size_type size2, bool preserve = true) { 2452 size1_ = size1; 2453 size2_ = size2; 2454 if (preserve) 2455 data ().resize (layout_type::size_M (size1, size2) + 1, typename array_type::value_type ()); 2456 else 2457 data ().resize (layout_type::size_M (size1, size2) + 1); 2458 for (size_type k = 0; k < layout_type::size_M (size1, size2); ++ k) { 2459 if (preserve) 2460 data () [k].resize (layout_type::size_m (size1, size2), value_type ()); 2461 else 2462 data () [k].resize (layout_type::size_m (size1, size2)); 2463 } 2464 } 2465 2466 // Element access 2467 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const2468 const_reference operator () (size_type i, size_type j) const { 2469 return data () [layout_type::index_M (i, j)] [layout_type::index_m (i, j)]; 2470 } 2471 BOOST_UBLAS_INLINE at_element(size_type i,size_type j)2472 reference at_element (size_type i, size_type j) { 2473 return data () [layout_type::index_M (i, j)] [layout_type::index_m (i, j)]; 2474 } 2475 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j)2476 reference operator () (size_type i, size_type j) { 2477 return at_element (i, j); 2478 } 2479 2480 // Element assignment 2481 BOOST_UBLAS_INLINE insert_element(size_type i,size_type j,const_reference t)2482 reference insert_element (size_type i, size_type j, const_reference t) { 2483 return (at_element (i, j) = t); 2484 } 2485 BOOST_UBLAS_INLINE erase_element(size_type i,size_type j)2486 void erase_element (size_type i, size_type j) { 2487 at_element (i, j) = value_type/*zero*/(); 2488 } 2489 2490 // Zeroing 2491 BOOST_UBLAS_INLINE clear()2492 void clear () { 2493 for (size_type k = 0; k < layout_type::size_M (size1_, size2_); ++ k) 2494 std::fill (data () [k].begin (), data () [k].end (), value_type/*zero*/()); 2495 } 2496 2497 // Assignment 2498 BOOST_UBLAS_INLINE operator =(const vector_of_vector & m)2499 vector_of_vector &operator = (const vector_of_vector &m) { 2500 size1_ = m.size1_; 2501 size2_ = m.size2_; 2502 data () = m.data (); 2503 return *this; 2504 } 2505 BOOST_UBLAS_INLINE assign_temporary(vector_of_vector & m)2506 vector_of_vector &assign_temporary (vector_of_vector &m) { 2507 swap (m); 2508 return *this; 2509 } 2510 template<class AE> 2511 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)2512 vector_of_vector &operator = (const matrix_expression<AE> &ae) { 2513 self_type temporary (ae); 2514 return assign_temporary (temporary); 2515 } 2516 template<class C> // Container assignment without temporary 2517 BOOST_UBLAS_INLINE operator =(const matrix_container<C> & m)2518 vector_of_vector &operator = (const matrix_container<C> &m) { 2519 resize (m ().size1 (), m ().size2 (), false); 2520 assign (m); 2521 return *this; 2522 } 2523 template<class AE> 2524 BOOST_UBLAS_INLINE assign(const matrix_expression<AE> & ae)2525 vector_of_vector &assign (const matrix_expression<AE> &ae) { 2526 matrix_assign<scalar_assign> (*this, ae); 2527 return *this; 2528 } 2529 template<class AE> 2530 BOOST_UBLAS_INLINE operator +=(const matrix_expression<AE> & ae)2531 vector_of_vector& operator += (const matrix_expression<AE> &ae) { 2532 self_type temporary (*this + ae); 2533 return assign_temporary (temporary); 2534 } 2535 template<class C> // Container assignment without temporary 2536 BOOST_UBLAS_INLINE operator +=(const matrix_container<C> & m)2537 vector_of_vector &operator += (const matrix_container<C> &m) { 2538 plus_assign (m); 2539 return *this; 2540 } 2541 template<class AE> 2542 BOOST_UBLAS_INLINE plus_assign(const matrix_expression<AE> & ae)2543 vector_of_vector &plus_assign (const matrix_expression<AE> &ae) { 2544 matrix_assign<scalar_plus_assign> (*this, ae); 2545 return *this; 2546 } 2547 template<class AE> 2548 BOOST_UBLAS_INLINE operator -=(const matrix_expression<AE> & ae)2549 vector_of_vector& operator -= (const matrix_expression<AE> &ae) { 2550 self_type temporary (*this - ae); 2551 return assign_temporary (temporary); 2552 } 2553 template<class C> // Container assignment without temporary 2554 BOOST_UBLAS_INLINE operator -=(const matrix_container<C> & m)2555 vector_of_vector &operator -= (const matrix_container<C> &m) { 2556 minus_assign (m); 2557 return *this; 2558 } 2559 template<class AE> 2560 BOOST_UBLAS_INLINE minus_assign(const matrix_expression<AE> & ae)2561 vector_of_vector &minus_assign (const matrix_expression<AE> &ae) { 2562 matrix_assign<scalar_minus_assign> (*this, ae); 2563 return *this; 2564 } 2565 template<class AT> 2566 BOOST_UBLAS_INLINE operator *=(const AT & at)2567 vector_of_vector& operator *= (const AT &at) { 2568 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 2569 return *this; 2570 } 2571 template<class AT> 2572 BOOST_UBLAS_INLINE operator /=(const AT & at)2573 vector_of_vector& operator /= (const AT &at) { 2574 matrix_assign_scalar<scalar_divides_assign> (*this, at); 2575 return *this; 2576 } 2577 2578 // Swapping 2579 BOOST_UBLAS_INLINE swap(vector_of_vector & m)2580 void swap (vector_of_vector &m) { 2581 if (this != &m) { 2582 std::swap (size1_, m.size1_); 2583 std::swap (size2_, m.size2_); 2584 data ().swap (m.data ()); 2585 } 2586 } 2587 BOOST_UBLAS_INLINE swap(vector_of_vector & m1,vector_of_vector & m2)2588 friend void swap (vector_of_vector &m1, vector_of_vector &m2) { 2589 m1.swap (m2); 2590 } 2591 2592 // Iterator types 2593 private: 2594 // Use the vector iterator 2595 typedef typename A::value_type::const_iterator const_subiterator_type; 2596 typedef typename A::value_type::iterator subiterator_type; 2597 public: 2598 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 2599 typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1; 2600 typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2; 2601 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1; 2602 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2; 2603 #else 2604 class const_iterator1; 2605 class iterator1; 2606 class const_iterator2; 2607 class iterator2; 2608 #endif 2609 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 2610 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 2611 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 2612 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 2613 2614 // Element lookup 2615 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j) const2616 const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const { 2617 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 2618 return const_iterator1 (*this, i, j); 2619 #else 2620 return const_iterator1 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j)); 2621 #endif 2622 } 2623 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j)2624 iterator1 find1 (int /*rank*/, size_type i, size_type j) { 2625 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 2626 return iterator1 (*this, i, j); 2627 #else 2628 return iterator1 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j)); 2629 #endif 2630 } 2631 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j) const2632 const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const { 2633 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 2634 return const_iterator2 (*this, i, j); 2635 #else 2636 return const_iterator2 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j)); 2637 #endif 2638 } 2639 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j)2640 iterator2 find2 (int /*rank*/, size_type i, size_type j) { 2641 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 2642 return iterator2 (*this, i, j); 2643 #else 2644 return iterator2 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j)); 2645 #endif 2646 } 2647 2648 2649 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 2650 class const_iterator1: 2651 public container_const_reference<vector_of_vector>, 2652 public random_access_iterator_base<dense_random_access_iterator_tag, 2653 const_iterator1, value_type> { 2654 public: 2655 typedef typename vector_of_vector::value_type value_type; 2656 typedef typename vector_of_vector::difference_type difference_type; 2657 typedef typename vector_of_vector::const_reference reference; 2658 typedef const typename vector_of_vector::pointer pointer; 2659 2660 typedef const_iterator2 dual_iterator_type; 2661 typedef const_reverse_iterator2 dual_reverse_iterator_type; 2662 2663 // Construction and destruction 2664 BOOST_UBLAS_INLINE const_iterator1()2665 const_iterator1 (): 2666 container_const_reference<self_type> (), i_ (), j_ (), it_ () {} 2667 BOOST_UBLAS_INLINE const_iterator1(const self_type & m,size_type i,size_type j,const const_subiterator_type & it)2668 const_iterator1 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it): 2669 container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {} 2670 BOOST_UBLAS_INLINE const_iterator1(const iterator1 & it)2671 const_iterator1 (const iterator1 &it): 2672 container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {} 2673 2674 // Arithmetic 2675 BOOST_UBLAS_INLINE operator ++()2676 const_iterator1 &operator ++ () { 2677 ++ i_; 2678 const self_type &m = (*this) (); 2679 if (layout_type::fast_i ()) 2680 ++ it_; 2681 else 2682 it_ = m.find1 (1, i_, j_).it_; 2683 return *this; 2684 } 2685 BOOST_UBLAS_INLINE operator --()2686 const_iterator1 &operator -- () { 2687 -- i_; 2688 const self_type &m = (*this) (); 2689 if (layout_type::fast_i ()) 2690 -- it_; 2691 else 2692 it_ = m.find1 (1, i_, j_).it_; 2693 return *this; 2694 } 2695 BOOST_UBLAS_INLINE operator +=(difference_type n)2696 const_iterator1 &operator += (difference_type n) { 2697 i_ += n; 2698 const self_type &m = (*this) (); 2699 it_ = m.find1 (1, i_, j_).it_; 2700 return *this; 2701 } 2702 BOOST_UBLAS_INLINE operator -=(difference_type n)2703 const_iterator1 &operator -= (difference_type n) { 2704 i_ -= n; 2705 const self_type &m = (*this) (); 2706 it_ = m.find1 (1, i_, j_).it_; 2707 return *this; 2708 } 2709 BOOST_UBLAS_INLINE operator -(const const_iterator1 & it) const2710 difference_type operator - (const const_iterator1 &it) const { 2711 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2712 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ()); 2713 return index1 () - it.index1 (); 2714 } 2715 2716 // Dereference 2717 BOOST_UBLAS_INLINE operator *() const2718 const_reference operator * () const { 2719 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 2720 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 2721 return *it_; 2722 } 2723 BOOST_UBLAS_INLINE operator [](difference_type n) const2724 const_reference operator [] (difference_type n) const { 2725 return *(*this + n); 2726 } 2727 2728 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 2729 BOOST_UBLAS_INLINE 2730 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2731 typename self_type:: 2732 #endif begin() const2733 const_iterator2 begin () const { 2734 const self_type &m = (*this) (); 2735 return m.find2 (1, index1 (), 0); 2736 } 2737 BOOST_UBLAS_INLINE 2738 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2739 typename self_type:: 2740 #endif cbegin() const2741 const_iterator2 cbegin () const { 2742 return begin (); 2743 } 2744 BOOST_UBLAS_INLINE 2745 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2746 typename self_type:: 2747 #endif end() const2748 const_iterator2 end () const { 2749 const self_type &m = (*this) (); 2750 return m.find2 (1, index1 (), m.size2 ()); 2751 } 2752 BOOST_UBLAS_INLINE 2753 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2754 typename self_type:: 2755 #endif cend() const2756 const_iterator2 cend () const { 2757 return end (); 2758 } 2759 BOOST_UBLAS_INLINE 2760 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2761 typename self_type:: 2762 #endif rbegin() const2763 const_reverse_iterator2 rbegin () const { 2764 return const_reverse_iterator2 (end ()); 2765 } 2766 BOOST_UBLAS_INLINE 2767 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2768 typename self_type:: 2769 #endif crbegin() const2770 const_reverse_iterator2 crbegin () const { 2771 return rbegin (); 2772 } 2773 BOOST_UBLAS_INLINE 2774 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2775 typename self_type:: 2776 #endif rend() const2777 const_reverse_iterator2 rend () const { 2778 return const_reverse_iterator2 (begin ()); 2779 } 2780 BOOST_UBLAS_INLINE 2781 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2782 typename self_type:: 2783 #endif crend() const2784 const_reverse_iterator2 crend () const { 2785 return rend (); 2786 } 2787 #endif 2788 2789 // Indices 2790 BOOST_UBLAS_INLINE index1() const2791 size_type index1 () const { 2792 return i_; 2793 } 2794 BOOST_UBLAS_INLINE index2() const2795 size_type index2 () const { 2796 return j_; 2797 } 2798 2799 // Assignment 2800 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)2801 const_iterator1 &operator = (const const_iterator1 &it) { 2802 container_const_reference<self_type>::assign (&it ()); 2803 it_ = it.it_; 2804 return *this; 2805 } 2806 2807 // Comparison 2808 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const2809 bool operator == (const const_iterator1 &it) const { 2810 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2811 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ()); 2812 return it_ == it.it_; 2813 } 2814 BOOST_UBLAS_INLINE operator <(const const_iterator1 & it) const2815 bool operator < (const const_iterator1 &it) const { 2816 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2817 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ()); 2818 return it_ < it.it_; 2819 } 2820 2821 private: 2822 size_type i_; 2823 size_type j_; 2824 const_subiterator_type it_; 2825 2826 friend class iterator1; 2827 }; 2828 #endif 2829 2830 BOOST_UBLAS_INLINE begin1() const2831 const_iterator1 begin1 () const { 2832 return find1 (0, 0, 0); 2833 } 2834 BOOST_UBLAS_INLINE cbegin1() const2835 const_iterator1 cbegin1 () const { 2836 return begin1 (); 2837 } 2838 BOOST_UBLAS_INLINE end1() const2839 const_iterator1 end1 () const { 2840 return find1 (0, size1_, 0); 2841 } 2842 BOOST_UBLAS_INLINE cend1() const2843 const_iterator1 cend1 () const { 2844 return end1 (); 2845 } 2846 2847 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 2848 class iterator1: 2849 public container_reference<vector_of_vector>, 2850 public random_access_iterator_base<dense_random_access_iterator_tag, 2851 iterator1, value_type> { 2852 public: 2853 typedef typename vector_of_vector::value_type value_type; 2854 typedef typename vector_of_vector::difference_type difference_type; 2855 typedef typename vector_of_vector::reference reference; 2856 typedef typename vector_of_vector::pointer pointer; 2857 2858 typedef iterator2 dual_iterator_type; 2859 typedef reverse_iterator2 dual_reverse_iterator_type; 2860 2861 // Construction and destruction 2862 BOOST_UBLAS_INLINE iterator1()2863 iterator1 (): 2864 container_reference<self_type> (), i_ (), j_ (), it_ () {} 2865 BOOST_UBLAS_INLINE iterator1(self_type & m,size_type i,size_type j,const subiterator_type & it)2866 iterator1 (self_type &m, size_type i, size_type j, const subiterator_type &it): 2867 container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {} 2868 2869 // Arithmetic 2870 BOOST_UBLAS_INLINE operator ++()2871 iterator1 &operator ++ () { 2872 ++ i_; 2873 self_type &m = (*this) (); 2874 if (layout_type::fast_i ()) 2875 ++ it_; 2876 else 2877 it_ = m.find1 (1, i_, j_).it_; 2878 return *this; 2879 } 2880 BOOST_UBLAS_INLINE operator --()2881 iterator1 &operator -- () { 2882 -- i_; 2883 self_type &m = (*this) (); 2884 if (layout_type::fast_i ()) 2885 -- it_; 2886 else 2887 it_ = m.find1 (1, i_, j_).it_; 2888 return *this; 2889 } 2890 BOOST_UBLAS_INLINE operator +=(difference_type n)2891 iterator1 &operator += (difference_type n) { 2892 i_ += n; 2893 self_type &m = (*this) (); 2894 it_ = m.find1 (1, i_, j_).it_; 2895 return *this; 2896 } 2897 BOOST_UBLAS_INLINE operator -=(difference_type n)2898 iterator1 &operator -= (difference_type n) { 2899 i_ -= n; 2900 self_type &m = (*this) (); 2901 it_ = m.find1 (1, i_, j_).it_; 2902 return *this; 2903 } 2904 BOOST_UBLAS_INLINE operator -(const iterator1 & it) const2905 difference_type operator - (const iterator1 &it) const { 2906 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2907 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ()); 2908 return index1 () - it.index1 (); 2909 } 2910 2911 // Dereference 2912 BOOST_UBLAS_INLINE operator *() const2913 reference operator * () const { 2914 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 2915 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 2916 return *it_; 2917 } 2918 BOOST_UBLAS_INLINE operator [](difference_type n) const2919 reference operator [] (difference_type n) const { 2920 return *(*this + n); 2921 } 2922 2923 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 2924 BOOST_UBLAS_INLINE 2925 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2926 typename self_type:: 2927 #endif begin() const2928 iterator2 begin () const { 2929 self_type &m = (*this) (); 2930 return m.find2 (1, index1 (), 0); 2931 } 2932 BOOST_UBLAS_INLINE 2933 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2934 typename self_type:: 2935 #endif end() const2936 iterator2 end () const { 2937 self_type &m = (*this) (); 2938 return m.find2 (1, index1 (), m.size2 ()); 2939 } 2940 BOOST_UBLAS_INLINE 2941 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2942 typename self_type:: 2943 #endif rbegin() const2944 reverse_iterator2 rbegin () const { 2945 return reverse_iterator2 (end ()); 2946 } 2947 BOOST_UBLAS_INLINE 2948 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2949 typename self_type:: 2950 #endif rend() const2951 reverse_iterator2 rend () const { 2952 return reverse_iterator2 (begin ()); 2953 } 2954 #endif 2955 2956 // Indices 2957 BOOST_UBLAS_INLINE index1() const2958 size_type index1 () const { 2959 return i_; 2960 } 2961 BOOST_UBLAS_INLINE index2() const2962 size_type index2 () const { 2963 return j_; 2964 } 2965 2966 // Assignment 2967 BOOST_UBLAS_INLINE operator =(const iterator1 & it)2968 iterator1 &operator = (const iterator1 &it) { 2969 container_reference<self_type>::assign (&it ()); 2970 it_ = it.it_; 2971 return *this; 2972 } 2973 2974 // Comparison 2975 BOOST_UBLAS_INLINE operator ==(const iterator1 & it) const2976 bool operator == (const iterator1 &it) const { 2977 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2978 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ()); 2979 return it_ == it.it_; 2980 } 2981 BOOST_UBLAS_INLINE operator <(const iterator1 & it) const2982 bool operator < (const iterator1 &it) const { 2983 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2984 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ()); 2985 return it_ < it.it_; 2986 } 2987 2988 private: 2989 size_type i_; 2990 size_type j_; 2991 subiterator_type it_; 2992 2993 friend class const_iterator1; 2994 }; 2995 #endif 2996 2997 BOOST_UBLAS_INLINE begin1()2998 iterator1 begin1 () { 2999 return find1 (0, 0, 0); 3000 } 3001 BOOST_UBLAS_INLINE end1()3002 iterator1 end1 () { 3003 return find1 (0, size1_, 0); 3004 } 3005 3006 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 3007 class const_iterator2: 3008 public container_const_reference<vector_of_vector>, 3009 public random_access_iterator_base<dense_random_access_iterator_tag, 3010 const_iterator2, value_type> { 3011 public: 3012 typedef typename vector_of_vector::value_type value_type; 3013 typedef typename vector_of_vector::difference_type difference_type; 3014 typedef typename vector_of_vector::const_reference reference; 3015 typedef const typename vector_of_vector::pointer pointer; 3016 3017 typedef const_iterator1 dual_iterator_type; 3018 typedef const_reverse_iterator1 dual_reverse_iterator_type; 3019 3020 // Construction and destruction 3021 BOOST_UBLAS_INLINE const_iterator2()3022 const_iterator2 (): 3023 container_const_reference<self_type> (), i_ (), j_ (), it_ () {} 3024 BOOST_UBLAS_INLINE const_iterator2(const self_type & m,size_type i,size_type j,const const_subiterator_type & it)3025 const_iterator2 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it): 3026 container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {} 3027 BOOST_UBLAS_INLINE const_iterator2(const iterator2 & it)3028 const_iterator2 (const iterator2 &it): 3029 container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {} 3030 3031 // Arithmetic 3032 BOOST_UBLAS_INLINE operator ++()3033 const_iterator2 &operator ++ () { 3034 ++ j_; 3035 const self_type &m = (*this) (); 3036 if (layout_type::fast_j ()) 3037 ++ it_; 3038 else 3039 it_ = m.find2 (1, i_, j_).it_; 3040 return *this; 3041 } 3042 BOOST_UBLAS_INLINE operator --()3043 const_iterator2 &operator -- () { 3044 -- j_; 3045 const self_type &m = (*this) (); 3046 if (layout_type::fast_j ()) 3047 -- it_; 3048 else 3049 it_ = m.find2 (1, i_, j_).it_; 3050 return *this; 3051 } 3052 BOOST_UBLAS_INLINE operator +=(difference_type n)3053 const_iterator2 &operator += (difference_type n) { 3054 j_ += n; 3055 const self_type &m = (*this) (); 3056 it_ = m.find2 (1, i_, j_).it_; 3057 return *this; 3058 } 3059 BOOST_UBLAS_INLINE operator -=(difference_type n)3060 const_iterator2 &operator -= (difference_type n) { 3061 j_ -= n; 3062 const self_type &m = (*this) (); 3063 it_ = m.find2 (1, i_, j_).it_; 3064 return *this; 3065 } 3066 BOOST_UBLAS_INLINE operator -(const const_iterator2 & it) const3067 difference_type operator - (const const_iterator2 &it) const { 3068 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 3069 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ()); 3070 return index2 () - it.index2 (); 3071 } 3072 3073 // Dereference 3074 BOOST_UBLAS_INLINE operator *() const3075 const_reference operator * () const { 3076 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 3077 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 3078 return *it_; 3079 } 3080 BOOST_UBLAS_INLINE operator [](difference_type n) const3081 const_reference operator [] (difference_type n) const { 3082 return *(*this + n); 3083 } 3084 3085 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 3086 BOOST_UBLAS_INLINE 3087 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3088 typename self_type:: 3089 #endif begin() const3090 const_iterator1 begin () const { 3091 const self_type &m = (*this) (); 3092 return m.find1 (1, 0, index2 ()); 3093 } 3094 BOOST_UBLAS_INLINE 3095 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3096 typename self_type:: 3097 #endif cbegin() const3098 const_iterator1 cbegin () const { 3099 return begin (); 3100 } 3101 BOOST_UBLAS_INLINE 3102 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3103 typename self_type:: 3104 #endif end() const3105 const_iterator1 end () const { 3106 const self_type &m = (*this) (); 3107 return m.find1 (1, m.size1 (), index2 ()); 3108 } 3109 BOOST_UBLAS_INLINE 3110 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3111 typename self_type:: 3112 #endif cend() const3113 const_iterator1 cend () const { 3114 return end (); 3115 } 3116 BOOST_UBLAS_INLINE 3117 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3118 typename self_type:: 3119 #endif rbegin() const3120 const_reverse_iterator1 rbegin () const { 3121 return const_reverse_iterator1 (end ()); 3122 } 3123 BOOST_UBLAS_INLINE 3124 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3125 typename self_type:: 3126 #endif crbegin() const3127 const_reverse_iterator1 crbegin () const { 3128 return rbegin (); 3129 } 3130 BOOST_UBLAS_INLINE 3131 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3132 typename self_type:: 3133 #endif rend() const3134 const_reverse_iterator1 rend () const { 3135 return const_reverse_iterator1 (begin ()); 3136 } 3137 BOOST_UBLAS_INLINE 3138 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3139 typename self_type:: 3140 #endif crend() const3141 const_reverse_iterator2 crend () const { 3142 return rend (); 3143 } 3144 #endif 3145 3146 // Indices 3147 BOOST_UBLAS_INLINE index1() const3148 size_type index1 () const { 3149 return i_; 3150 } 3151 BOOST_UBLAS_INLINE index2() const3152 size_type index2 () const { 3153 return j_; 3154 } 3155 3156 // Assignment 3157 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)3158 const_iterator2 &operator = (const const_iterator2 &it) { 3159 container_const_reference<self_type>::assign (&it ()); 3160 it_ = it.it_; 3161 return *this; 3162 } 3163 3164 // Comparison 3165 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const3166 bool operator == (const const_iterator2 &it) const { 3167 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 3168 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ()); 3169 return it_ == it.it_; 3170 } 3171 BOOST_UBLAS_INLINE operator <(const const_iterator2 & it) const3172 bool operator < (const const_iterator2 &it) const { 3173 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 3174 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ()); 3175 return it_ < it.it_; 3176 } 3177 3178 private: 3179 size_type i_; 3180 size_type j_; 3181 const_subiterator_type it_; 3182 3183 friend class iterator2; 3184 }; 3185 #endif 3186 3187 BOOST_UBLAS_INLINE begin2() const3188 const_iterator2 begin2 () const { 3189 return find2 (0, 0, 0); 3190 } 3191 BOOST_UBLAS_INLINE cbegin2() const3192 const_iterator2 cbegin2 () const { 3193 return begin2 (); 3194 } 3195 BOOST_UBLAS_INLINE end2() const3196 const_iterator2 end2 () const { 3197 return find2 (0, 0, size2_); 3198 } 3199 BOOST_UBLAS_INLINE cend2() const3200 const_iterator2 cend2 () const { 3201 return end2 (); 3202 } 3203 3204 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 3205 class iterator2: 3206 public container_reference<vector_of_vector>, 3207 public random_access_iterator_base<dense_random_access_iterator_tag, 3208 iterator2, value_type> { 3209 public: 3210 typedef typename vector_of_vector::value_type value_type; 3211 typedef typename vector_of_vector::difference_type difference_type; 3212 typedef typename vector_of_vector::reference reference; 3213 typedef typename vector_of_vector::pointer pointer; 3214 3215 typedef iterator1 dual_iterator_type; 3216 typedef reverse_iterator1 dual_reverse_iterator_type; 3217 3218 // Construction and destruction 3219 BOOST_UBLAS_INLINE iterator2()3220 iterator2 (): 3221 container_reference<self_type> (), i_ (), j_ (), it_ () {} 3222 BOOST_UBLAS_INLINE iterator2(self_type & m,size_type i,size_type j,const subiterator_type & it)3223 iterator2 (self_type &m, size_type i, size_type j, const subiterator_type &it): 3224 container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {} 3225 3226 // Arithmetic 3227 BOOST_UBLAS_INLINE operator ++()3228 iterator2 &operator ++ () { 3229 ++ j_; 3230 self_type &m = (*this) (); 3231 if (layout_type::fast_j ()) 3232 ++ it_; 3233 else 3234 it_ = m.find2 (1, i_, j_).it_; 3235 return *this; 3236 } 3237 BOOST_UBLAS_INLINE operator --()3238 iterator2 &operator -- () { 3239 -- j_; 3240 self_type &m = (*this) (); 3241 if (layout_type::fast_j ()) 3242 -- it_; 3243 else 3244 it_ = m.find2 (1, i_, j_).it_; 3245 return *this; 3246 } 3247 BOOST_UBLAS_INLINE operator +=(difference_type n)3248 iterator2 &operator += (difference_type n) { 3249 j_ += n; 3250 self_type &m = (*this) (); 3251 it_ = m.find2 (1, i_, j_).it_; 3252 return *this; 3253 } 3254 BOOST_UBLAS_INLINE operator -=(difference_type n)3255 iterator2 &operator -= (difference_type n) { 3256 j_ -= n; 3257 self_type &m = (*this) (); 3258 it_ = m.find2 (1, i_, j_).it_; 3259 return *this; 3260 } 3261 BOOST_UBLAS_INLINE operator -(const iterator2 & it) const3262 difference_type operator - (const iterator2 &it) const { 3263 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 3264 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ()); 3265 return index2 () - it.index2 (); 3266 } 3267 3268 // Dereference 3269 BOOST_UBLAS_INLINE operator *() const3270 reference operator * () const { 3271 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 3272 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 3273 return *it_; 3274 } 3275 BOOST_UBLAS_INLINE operator [](difference_type n) const3276 reference operator [] (difference_type n) const { 3277 return *(*this + n); 3278 } 3279 3280 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 3281 BOOST_UBLAS_INLINE 3282 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3283 typename self_type:: 3284 #endif begin() const3285 iterator1 begin () const { 3286 self_type &m = (*this) (); 3287 return m.find1 (1, 0, index2 ()); 3288 } 3289 BOOST_UBLAS_INLINE 3290 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3291 typename self_type:: 3292 #endif end() const3293 iterator1 end () const { 3294 self_type &m = (*this) (); 3295 return m.find1 (1, m.size1 (), index2 ()); 3296 } 3297 BOOST_UBLAS_INLINE 3298 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3299 typename self_type:: 3300 #endif rbegin() const3301 reverse_iterator1 rbegin () const { 3302 return reverse_iterator1 (end ()); 3303 } 3304 BOOST_UBLAS_INLINE 3305 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3306 typename self_type:: 3307 #endif rend() const3308 reverse_iterator1 rend () const { 3309 return reverse_iterator1 (begin ()); 3310 } 3311 #endif 3312 3313 // Indices 3314 BOOST_UBLAS_INLINE index1() const3315 size_type index1 () const { 3316 return i_; 3317 } 3318 BOOST_UBLAS_INLINE index2() const3319 size_type index2 () const { 3320 return j_; 3321 } 3322 3323 // Assignment 3324 BOOST_UBLAS_INLINE operator =(const iterator2 & it)3325 iterator2 &operator = (const iterator2 &it) { 3326 container_reference<self_type>::assign (&it ()); 3327 it_ = it.it_; 3328 return *this; 3329 } 3330 3331 // Comparison 3332 BOOST_UBLAS_INLINE operator ==(const iterator2 & it) const3333 bool operator == (const iterator2 &it) const { 3334 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 3335 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ()); 3336 return it_ == it.it_; 3337 } 3338 BOOST_UBLAS_INLINE operator <(const iterator2 & it) const3339 bool operator < (const iterator2 &it) const { 3340 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 3341 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ()); 3342 return it_ < it.it_; 3343 } 3344 3345 private: 3346 size_type i_; 3347 size_type j_; 3348 subiterator_type it_; 3349 3350 friend class const_iterator2; 3351 }; 3352 #endif 3353 3354 BOOST_UBLAS_INLINE begin2()3355 iterator2 begin2 () { 3356 return find2 (0, 0, 0); 3357 } 3358 BOOST_UBLAS_INLINE end2()3359 iterator2 end2 () { 3360 return find2 (0, 0, size2_); 3361 } 3362 3363 // Reverse iterators 3364 3365 BOOST_UBLAS_INLINE rbegin1() const3366 const_reverse_iterator1 rbegin1 () const { 3367 return const_reverse_iterator1 (end1 ()); 3368 } 3369 BOOST_UBLAS_INLINE crbegin1() const3370 const_reverse_iterator1 crbegin1 () const { 3371 return rbegin1 (); 3372 } 3373 BOOST_UBLAS_INLINE rend1() const3374 const_reverse_iterator1 rend1 () const { 3375 return const_reverse_iterator1 (begin1 ()); 3376 } 3377 BOOST_UBLAS_INLINE crend1() const3378 const_reverse_iterator1 crend1 () const { 3379 return rend1 (); 3380 } 3381 3382 BOOST_UBLAS_INLINE rbegin1()3383 reverse_iterator1 rbegin1 () { 3384 return reverse_iterator1 (end1 ()); 3385 } 3386 BOOST_UBLAS_INLINE rend1()3387 reverse_iterator1 rend1 () { 3388 return reverse_iterator1 (begin1 ()); 3389 } 3390 3391 BOOST_UBLAS_INLINE rbegin2() const3392 const_reverse_iterator2 rbegin2 () const { 3393 return const_reverse_iterator2 (end2 ()); 3394 } 3395 BOOST_UBLAS_INLINE crbegin2() const3396 const_reverse_iterator2 crbegin2 () const { 3397 return rbegin2 (); 3398 } 3399 BOOST_UBLAS_INLINE rend2() const3400 const_reverse_iterator2 rend2 () const { 3401 return const_reverse_iterator2 (begin2 ()); 3402 } 3403 BOOST_UBLAS_INLINE crend2() const3404 const_reverse_iterator2 crend2 () const { 3405 return rend2 (); 3406 } 3407 3408 BOOST_UBLAS_INLINE rbegin2()3409 reverse_iterator2 rbegin2 () { 3410 return reverse_iterator2 (end2 ()); 3411 } 3412 BOOST_UBLAS_INLINE rend2()3413 reverse_iterator2 rend2 () { 3414 return reverse_iterator2 (begin2 ()); 3415 } 3416 3417 // Serialization 3418 template<class Archive> serialize(Archive & ar,const unsigned int)3419 void serialize(Archive & ar, const unsigned int /* file_version */){ 3420 3421 // we need to copy to a collection_size_type to get a portable 3422 // and efficient serialization 3423 serialization::collection_size_type s1 (size1_); 3424 serialization::collection_size_type s2 (size2_); 3425 3426 // serialize the sizes 3427 ar & serialization::make_nvp("size1",s1) 3428 & serialization::make_nvp("size2",s2); 3429 3430 // copy the values back if loading 3431 if (Archive::is_loading::value) { 3432 size1_ = s1; 3433 size2_ = s2; 3434 } 3435 ar & serialization::make_nvp("data",data_); 3436 } 3437 3438 private: 3439 size_type size1_; 3440 size_type size2_; 3441 array_type data_; 3442 }; 3443 3444 3445 /** \brief A matrix with all values of type \c T equal to zero 3446 * 3447 * Changing values does not affect the matrix, however assigning it to a normal matrix will put zero 3448 * everywhere in the target matrix. All accesses are constant time, due to the trivial value. 3449 * 3450 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...) 3451 * \tparam ALLOC an allocator for storing the zero element. By default, a standar allocator is used. 3452 */ 3453 template<class T, class ALLOC> 3454 class zero_matrix: 3455 public matrix_container<zero_matrix<T, ALLOC> > { 3456 3457 typedef const T *const_pointer; 3458 typedef zero_matrix<T, ALLOC> self_type; 3459 public: 3460 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 3461 using matrix_container<self_type>::operator (); 3462 #endif 3463 typedef typename ALLOC::size_type size_type; 3464 typedef typename ALLOC::difference_type difference_type; 3465 typedef T value_type; 3466 typedef const T &const_reference; 3467 typedef T &reference; 3468 typedef const matrix_reference<const self_type> const_closure_type; 3469 typedef matrix_reference<self_type> closure_type; 3470 typedef sparse_tag storage_category; 3471 typedef unknown_orientation_tag orientation_category; 3472 3473 // Construction and destruction 3474 BOOST_UBLAS_INLINE zero_matrix()3475 zero_matrix (): 3476 matrix_container<self_type> (), 3477 size1_ (0), size2_ (0) {} 3478 BOOST_UBLAS_INLINE zero_matrix(size_type size)3479 zero_matrix (size_type size): 3480 matrix_container<self_type> (), 3481 size1_ (size), size2_ (size) {} 3482 BOOST_UBLAS_INLINE zero_matrix(size_type size1,size_type size2)3483 zero_matrix (size_type size1, size_type size2): 3484 matrix_container<self_type> (), 3485 size1_ (size1), size2_ (size2) {} 3486 BOOST_UBLAS_INLINE zero_matrix(const zero_matrix & m)3487 zero_matrix (const zero_matrix &m): 3488 matrix_container<self_type> (), 3489 size1_ (m.size1_), size2_ (m.size2_) {} 3490 3491 // Accessors 3492 BOOST_UBLAS_INLINE size1() const3493 size_type size1 () const { 3494 return size1_; 3495 } 3496 BOOST_UBLAS_INLINE size2() const3497 size_type size2 () const { 3498 return size2_; 3499 } 3500 3501 // Resizing 3502 BOOST_UBLAS_INLINE resize(size_type size,bool=true)3503 void resize (size_type size, bool /*preserve*/ = true) { 3504 size1_ = size; 3505 size2_ = size; 3506 } 3507 BOOST_UBLAS_INLINE resize(size_type size1,size_type size2,bool=true)3508 void resize (size_type size1, size_type size2, bool /*preserve*/ = true) { 3509 size1_ = size1; 3510 size2_ = size2; 3511 } 3512 3513 // Element access 3514 BOOST_UBLAS_INLINE operator ()(size_type,size_type) const3515 const_reference operator () (size_type /* i */, size_type /* j */) const { 3516 return zero_; 3517 } 3518 3519 // Assignment 3520 BOOST_UBLAS_INLINE operator =(const zero_matrix & m)3521 zero_matrix &operator = (const zero_matrix &m) { 3522 size1_ = m.size1_; 3523 size2_ = m.size2_; 3524 return *this; 3525 } 3526 BOOST_UBLAS_INLINE assign_temporary(zero_matrix & m)3527 zero_matrix &assign_temporary (zero_matrix &m) { 3528 swap (m); 3529 return *this; 3530 } 3531 3532 // Swapping 3533 BOOST_UBLAS_INLINE swap(zero_matrix & m)3534 void swap (zero_matrix &m) { 3535 if (this != &m) { 3536 std::swap (size1_, m.size1_); 3537 std::swap (size2_, m.size2_); 3538 } 3539 } 3540 BOOST_UBLAS_INLINE swap(zero_matrix & m1,zero_matrix & m2)3541 friend void swap (zero_matrix &m1, zero_matrix &m2) { 3542 m1.swap (m2); 3543 } 3544 3545 // Iterator types 3546 public: 3547 class const_iterator1; 3548 class const_iterator2; 3549 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 3550 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 3551 3552 // Element lookup 3553 BOOST_UBLAS_INLINE find1(int,size_type,size_type) const3554 const_iterator1 find1 (int /*rank*/, size_type /*i*/, size_type /*j*/) const { 3555 return const_iterator1 (*this); 3556 } 3557 BOOST_UBLAS_INLINE find2(int,size_type,size_type) const3558 const_iterator2 find2 (int /*rank*/, size_type /*i*/, size_type /*j*/) const { 3559 return const_iterator2 (*this); 3560 } 3561 3562 class const_iterator1: 3563 public container_const_reference<zero_matrix>, 3564 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 3565 const_iterator1, value_type> { 3566 public: 3567 typedef typename zero_matrix::value_type value_type; 3568 typedef typename zero_matrix::difference_type difference_type; 3569 typedef typename zero_matrix::const_reference reference; 3570 typedef typename zero_matrix::const_pointer pointer; 3571 3572 typedef const_iterator2 dual_iterator_type; 3573 typedef const_reverse_iterator2 dual_reverse_iterator_type; 3574 3575 // Construction and destruction 3576 BOOST_UBLAS_INLINE const_iterator1()3577 const_iterator1 (): 3578 container_const_reference<self_type> () {} 3579 BOOST_UBLAS_INLINE const_iterator1(const self_type & m)3580 const_iterator1 (const self_type &m): 3581 container_const_reference<self_type> (m) {} 3582 3583 // Arithmetic 3584 BOOST_UBLAS_INLINE operator ++()3585 const_iterator1 &operator ++ () { 3586 BOOST_UBLAS_CHECK_FALSE (bad_index ()); 3587 return *this; 3588 } 3589 BOOST_UBLAS_INLINE operator --()3590 const_iterator1 &operator -- () { 3591 BOOST_UBLAS_CHECK_FALSE (bad_index ()); 3592 return *this; 3593 } 3594 3595 // Dereference 3596 BOOST_UBLAS_INLINE operator *() const3597 const_reference operator * () const { 3598 BOOST_UBLAS_CHECK_FALSE (bad_index ()); 3599 return zero_; // arbitary return value 3600 } 3601 3602 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 3603 BOOST_UBLAS_INLINE 3604 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3605 typename self_type:: 3606 #endif begin() const3607 const_iterator2 begin () const { 3608 return const_iterator2 ((*this) ()); 3609 } 3610 BOOST_UBLAS_INLINE 3611 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3612 typename self_type:: 3613 #endif cbegin() const3614 const_iterator2 cbegin () const { 3615 return begin (); 3616 } 3617 BOOST_UBLAS_INLINE 3618 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3619 typename self_type:: 3620 #endif end() const3621 const_iterator2 end () const { 3622 return const_iterator2 ((*this) ()); 3623 } 3624 BOOST_UBLAS_INLINE 3625 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3626 typename self_type:: 3627 #endif cend() const3628 const_iterator2 cend () const { 3629 return end (); 3630 } 3631 BOOST_UBLAS_INLINE 3632 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3633 typename self_type:: 3634 #endif rbegin() const3635 const_reverse_iterator2 rbegin () const { 3636 return const_reverse_iterator2 (end ()); 3637 } 3638 BOOST_UBLAS_INLINE 3639 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3640 typename self_type:: 3641 #endif crbegin() const3642 const_reverse_iterator2 crbegin () const { 3643 return rbegin (); 3644 } 3645 BOOST_UBLAS_INLINE 3646 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3647 typename self_type:: 3648 #endif rend() const3649 const_reverse_iterator2 rend () const { 3650 return const_reverse_iterator2 (begin ()); 3651 } 3652 BOOST_UBLAS_INLINE 3653 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3654 typename self_type:: 3655 #endif crend() const3656 const_reverse_iterator2 crend () const { 3657 return rend (); 3658 } 3659 #endif 3660 3661 // Indices 3662 BOOST_UBLAS_INLINE index1() const3663 size_type index1 () const { 3664 BOOST_UBLAS_CHECK_FALSE (bad_index ()); 3665 return 0; // arbitary return value 3666 } 3667 BOOST_UBLAS_INLINE index2() const3668 size_type index2 () const { 3669 BOOST_UBLAS_CHECK_FALSE (bad_index ()); 3670 return 0; // arbitary return value 3671 } 3672 3673 // Assignment 3674 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)3675 const_iterator1 &operator = (const const_iterator1 &it) { 3676 container_const_reference<self_type>::assign (&it ()); 3677 return *this; 3678 } 3679 3680 // Comparison 3681 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const3682 bool operator == (const const_iterator1 &it) const { 3683 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 3684 detail::ignore_unused_variable_warning(it); 3685 return true; 3686 } 3687 }; 3688 3689 typedef const_iterator1 iterator1; 3690 3691 BOOST_UBLAS_INLINE begin1() const3692 const_iterator1 begin1 () const { 3693 return const_iterator1 (*this); 3694 } 3695 BOOST_UBLAS_INLINE cbegin1() const3696 const_iterator1 cbegin1 () const { 3697 return begin1 (); 3698 } 3699 BOOST_UBLAS_INLINE end1() const3700 const_iterator1 end1 () const { 3701 return const_iterator1 (*this); 3702 } 3703 BOOST_UBLAS_INLINE cend1() const3704 const_iterator1 cend1 () const { 3705 return end1 (); 3706 } 3707 3708 class const_iterator2: 3709 public container_const_reference<zero_matrix>, 3710 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 3711 const_iterator2, value_type> { 3712 public: 3713 typedef typename zero_matrix::value_type value_type; 3714 typedef typename zero_matrix::difference_type difference_type; 3715 typedef typename zero_matrix::const_reference reference; 3716 typedef typename zero_matrix::const_pointer pointer; 3717 3718 typedef const_iterator1 dual_iterator_type; 3719 typedef const_reverse_iterator1 dual_reverse_iterator_type; 3720 3721 // Construction and destruction 3722 BOOST_UBLAS_INLINE const_iterator2()3723 const_iterator2 (): 3724 container_const_reference<self_type> () {} 3725 BOOST_UBLAS_INLINE const_iterator2(const self_type & m)3726 const_iterator2 (const self_type &m): 3727 container_const_reference<self_type> (m) {} 3728 3729 // Arithmetic 3730 BOOST_UBLAS_INLINE operator ++()3731 const_iterator2 &operator ++ () { 3732 BOOST_UBLAS_CHECK_FALSE (bad_index ()); 3733 return *this; 3734 } 3735 BOOST_UBLAS_INLINE operator --()3736 const_iterator2 &operator -- () { 3737 BOOST_UBLAS_CHECK_FALSE (bad_index ()); 3738 return *this; 3739 } 3740 3741 // Dereference 3742 BOOST_UBLAS_INLINE operator *() const3743 const_reference operator * () const { 3744 BOOST_UBLAS_CHECK_FALSE (bad_index ()); 3745 return zero_; // arbitary return value 3746 } 3747 3748 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 3749 BOOST_UBLAS_INLINE 3750 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3751 typename self_type:: 3752 #endif begin() const3753 const_iterator1 begin () const { 3754 return const_iterator1 ((*this) ()); 3755 } 3756 BOOST_UBLAS_INLINE 3757 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3758 typename self_type:: 3759 #endif cbegin() const3760 const_iterator1 cbegin () const { 3761 return begin (); 3762 } 3763 BOOST_UBLAS_INLINE 3764 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3765 typename self_type:: 3766 #endif end() const3767 const_iterator1 end () const { 3768 return const_iterator1 ((*this) ()); 3769 } 3770 BOOST_UBLAS_INLINE 3771 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3772 typename self_type:: 3773 #endif cend() const3774 const_iterator1 cend () const { 3775 return end (); 3776 } 3777 BOOST_UBLAS_INLINE 3778 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3779 typename self_type:: 3780 #endif rbegin() const3781 const_reverse_iterator1 rbegin () const { 3782 return const_reverse_iterator1 (end ()); 3783 } 3784 BOOST_UBLAS_INLINE 3785 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3786 typename self_type:: 3787 #endif crbegin() const3788 const_reverse_iterator1 crbegin () const { 3789 return rbegin (); 3790 } 3791 BOOST_UBLAS_INLINE 3792 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3793 typename self_type:: 3794 #endif rend() const3795 const_reverse_iterator1 rend () const { 3796 return const_reverse_iterator1 (begin ()); 3797 } 3798 BOOST_UBLAS_INLINE 3799 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3800 typename self_type:: 3801 #endif crend() const3802 const_reverse_iterator1 crend () const { 3803 return rend (); 3804 } 3805 #endif 3806 3807 // Indices 3808 BOOST_UBLAS_INLINE index1() const3809 size_type index1 () const { 3810 BOOST_UBLAS_CHECK_FALSE (bad_index ()); 3811 return 0; // arbitary return value 3812 } 3813 BOOST_UBLAS_INLINE index2() const3814 size_type index2 () const { 3815 BOOST_UBLAS_CHECK_FALSE (bad_index ()); 3816 return 0; // arbitary return value 3817 } 3818 3819 // Assignment 3820 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)3821 const_iterator2 &operator = (const const_iterator2 &it) { 3822 container_const_reference<self_type>::assign (&it ()); 3823 return *this; 3824 } 3825 3826 // Comparison 3827 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const3828 bool operator == (const const_iterator2 &it) const { 3829 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 3830 detail::ignore_unused_variable_warning(it); 3831 return true; 3832 } 3833 }; 3834 3835 typedef const_iterator2 iterator2; 3836 3837 BOOST_UBLAS_INLINE begin2() const3838 const_iterator2 begin2 () const { 3839 return find2 (0, 0, 0); 3840 } 3841 BOOST_UBLAS_INLINE cbegin2() const3842 const_iterator2 cbegin2 () const { 3843 return begin2 (); 3844 } 3845 BOOST_UBLAS_INLINE end2() const3846 const_iterator2 end2 () const { 3847 return find2 (0, 0, size2_); 3848 } 3849 BOOST_UBLAS_INLINE cend2() const3850 const_iterator2 cend2 () const { 3851 return end2 (); 3852 } 3853 3854 // Reverse iterators 3855 3856 BOOST_UBLAS_INLINE rbegin1() const3857 const_reverse_iterator1 rbegin1 () const { 3858 return const_reverse_iterator1 (end1 ()); 3859 } 3860 BOOST_UBLAS_INLINE crbegin1() const3861 const_reverse_iterator1 crbegin1 () const { 3862 return rbegin1 (); 3863 } 3864 BOOST_UBLAS_INLINE rend1() const3865 const_reverse_iterator1 rend1 () const { 3866 return const_reverse_iterator1 (begin1 ()); 3867 } 3868 BOOST_UBLAS_INLINE crend1() const3869 const_reverse_iterator1 crend1 () const { 3870 return rend1 (); 3871 } 3872 3873 BOOST_UBLAS_INLINE rbegin2() const3874 const_reverse_iterator2 rbegin2 () const { 3875 return const_reverse_iterator2 (end2 ()); 3876 } 3877 BOOST_UBLAS_INLINE crbegin2() const3878 const_reverse_iterator2 crbegin2 () const { 3879 return rbegin2 (); 3880 } 3881 BOOST_UBLAS_INLINE rend2() const3882 const_reverse_iterator2 rend2 () const { 3883 return const_reverse_iterator2 (begin2 ()); 3884 } 3885 BOOST_UBLAS_INLINE crend2() const3886 const_reverse_iterator2 crend2 () const { 3887 return rend2 (); 3888 } 3889 3890 // Serialization 3891 template<class Archive> serialize(Archive & ar,const unsigned int)3892 void serialize(Archive & ar, const unsigned int /* file_version */){ 3893 3894 // we need to copy to a collection_size_type to get a portable 3895 // and efficient serialization 3896 serialization::collection_size_type s1 (size1_); 3897 serialization::collection_size_type s2 (size2_); 3898 3899 // serialize the sizes 3900 ar & serialization::make_nvp("size1",s1) 3901 & serialization::make_nvp("size2",s2); 3902 3903 // copy the values back if loading 3904 if (Archive::is_loading::value) { 3905 size1_ = s1; 3906 size2_ = s2; 3907 } 3908 } 3909 3910 private: 3911 size_type size1_; 3912 size_type size2_; 3913 static const value_type zero_; 3914 }; 3915 3916 template<class T, class ALLOC> 3917 const typename zero_matrix<T, ALLOC>::value_type zero_matrix<T, ALLOC>::zero_ = T(/*zero*/); 3918 3919 /** \brief An identity matrix with values of type \c T 3920 * 3921 * Elements or cordinates \f$(i,i)\f$ are equal to 1 (one) and all others to 0 (zero). 3922 * Changing values does not affect the matrix, however assigning it to a normal matrix will 3923 * make the matrix equal to an identity matrix. All accesses are constant du to the trivial values. 3924 * 3925 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...) 3926 * \tparam ALLOC an allocator for storing the zeros and one elements. By default, a standar allocator is used. 3927 */ 3928 template<class T, class ALLOC> 3929 class identity_matrix: 3930 public matrix_container<identity_matrix<T, ALLOC> > { 3931 3932 typedef const T *const_pointer; 3933 typedef identity_matrix<T, ALLOC> self_type; 3934 public: 3935 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 3936 using matrix_container<self_type>::operator (); 3937 #endif 3938 typedef typename ALLOC::size_type size_type; 3939 typedef typename ALLOC::difference_type difference_type; 3940 typedef T value_type; 3941 typedef const T &const_reference; 3942 typedef T &reference; 3943 typedef const matrix_reference<const self_type> const_closure_type; 3944 typedef matrix_reference<self_type> closure_type; 3945 typedef sparse_tag storage_category; 3946 typedef unknown_orientation_tag orientation_category; 3947 3948 // Construction and destruction 3949 BOOST_UBLAS_INLINE identity_matrix()3950 identity_matrix (): 3951 matrix_container<self_type> (), 3952 size1_ (0), size2_ (0), size_common_ (0) {} 3953 BOOST_UBLAS_INLINE identity_matrix(size_type size)3954 identity_matrix (size_type size): 3955 matrix_container<self_type> (), 3956 size1_ (size), size2_ (size), size_common_ ((std::min) (size1_, size2_)) {} 3957 BOOST_UBLAS_INLINE identity_matrix(size_type size1,size_type size2)3958 identity_matrix (size_type size1, size_type size2): 3959 matrix_container<self_type> (), 3960 size1_ (size1), size2_ (size2), size_common_ ((std::min) (size1_, size2_)) {} 3961 BOOST_UBLAS_INLINE identity_matrix(const identity_matrix & m)3962 identity_matrix (const identity_matrix &m): 3963 matrix_container<self_type> (), 3964 size1_ (m.size1_), size2_ (m.size2_), size_common_ ((std::min) (size1_, size2_)) {} 3965 3966 // Accessors 3967 BOOST_UBLAS_INLINE size1() const3968 size_type size1 () const { 3969 return size1_; 3970 } 3971 BOOST_UBLAS_INLINE size2() const3972 size_type size2 () const { 3973 return size2_; 3974 } 3975 3976 // Resizing 3977 BOOST_UBLAS_INLINE resize(size_type size,bool=true)3978 void resize (size_type size, bool /*preserve*/ = true) { 3979 size1_ = size; 3980 size2_ = size; 3981 size_common_ = ((std::min)(size1_, size2_)); 3982 } 3983 BOOST_UBLAS_INLINE resize(size_type size1,size_type size2,bool=true)3984 void resize (size_type size1, size_type size2, bool /*preserve*/ = true) { 3985 size1_ = size1; 3986 size2_ = size2; 3987 size_common_ = ((std::min)(size1_, size2_)); 3988 } 3989 3990 // Element access 3991 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const3992 const_reference operator () (size_type i, size_type j) const { 3993 if (i == j) 3994 return one_; 3995 else 3996 return zero_; 3997 } 3998 3999 // Assignment 4000 BOOST_UBLAS_INLINE operator =(const identity_matrix & m)4001 identity_matrix &operator = (const identity_matrix &m) { 4002 size1_ = m.size1_; 4003 size2_ = m.size2_; 4004 size_common_ = m.size_common_; 4005 return *this; 4006 } 4007 BOOST_UBLAS_INLINE assign_temporary(identity_matrix & m)4008 identity_matrix &assign_temporary (identity_matrix &m) { 4009 swap (m); 4010 return *this; 4011 } 4012 4013 // Swapping 4014 BOOST_UBLAS_INLINE swap(identity_matrix & m)4015 void swap (identity_matrix &m) { 4016 if (this != &m) { 4017 std::swap (size1_, m.size1_); 4018 std::swap (size2_, m.size2_); 4019 std::swap (size_common_, m.size_common_); 4020 } 4021 } 4022 BOOST_UBLAS_INLINE swap(identity_matrix & m1,identity_matrix & m2)4023 friend void swap (identity_matrix &m1, identity_matrix &m2) { 4024 m1.swap (m2); 4025 } 4026 4027 // Iterator types 4028 private: 4029 // Use an index 4030 typedef size_type const_subiterator_type; 4031 4032 public: 4033 class const_iterator1; 4034 class const_iterator2; 4035 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 4036 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 4037 4038 // Element lookup 4039 BOOST_UBLAS_INLINE find1(int rank,size_type i,size_type j) const4040 const_iterator1 find1 (int rank, size_type i, size_type j) const { 4041 if (rank == 1) { 4042 i = (std::max) (i, j); 4043 i = (std::min) (i, j + 1); 4044 } 4045 return const_iterator1 (*this, i); 4046 } 4047 BOOST_UBLAS_INLINE find2(int rank,size_type i,size_type j) const4048 const_iterator2 find2 (int rank, size_type i, size_type j) const { 4049 if (rank == 1) { 4050 j = (std::max) (j, i); 4051 j = (std::min) (j, i + 1); 4052 } 4053 return const_iterator2 (*this, j); 4054 } 4055 4056 4057 class const_iterator1: 4058 public container_const_reference<identity_matrix>, 4059 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 4060 const_iterator1, value_type> { 4061 public: 4062 typedef typename identity_matrix::value_type value_type; 4063 typedef typename identity_matrix::difference_type difference_type; 4064 typedef typename identity_matrix::const_reference reference; 4065 typedef typename identity_matrix::const_pointer pointer; 4066 4067 typedef const_iterator2 dual_iterator_type; 4068 typedef const_reverse_iterator2 dual_reverse_iterator_type; 4069 4070 // Construction and destruction 4071 BOOST_UBLAS_INLINE const_iterator1()4072 const_iterator1 (): 4073 container_const_reference<self_type> (), it_ () {} 4074 BOOST_UBLAS_INLINE const_iterator1(const self_type & m,const const_subiterator_type & it)4075 const_iterator1 (const self_type &m, const const_subiterator_type &it): 4076 container_const_reference<self_type> (m), it_ (it) {} 4077 4078 // Arithmetic 4079 BOOST_UBLAS_INLINE operator ++()4080 const_iterator1 &operator ++ () { 4081 BOOST_UBLAS_CHECK (it_ < (*this) ().size1 (), bad_index ()); 4082 ++it_; 4083 return *this; 4084 } 4085 BOOST_UBLAS_INLINE operator --()4086 const_iterator1 &operator -- () { 4087 BOOST_UBLAS_CHECK (it_ > 0, bad_index ()); 4088 --it_; 4089 return *this; 4090 } 4091 4092 // Dereference 4093 BOOST_UBLAS_INLINE operator *() const4094 const_reference operator * () const { 4095 return one_; 4096 } 4097 4098 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 4099 BOOST_UBLAS_INLINE 4100 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4101 typename self_type:: 4102 #endif begin() const4103 const_iterator2 begin () const { 4104 return const_iterator2 ((*this) (), it_); 4105 } 4106 BOOST_UBLAS_INLINE 4107 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4108 typename self_type:: 4109 #endif cbegin() const4110 const_iterator2 cbegin () const { 4111 return begin (); 4112 } 4113 BOOST_UBLAS_INLINE 4114 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4115 typename self_type:: 4116 #endif end() const4117 const_iterator2 end () const { 4118 return const_iterator2 ((*this) (), it_ + 1); 4119 } 4120 BOOST_UBLAS_INLINE 4121 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4122 typename self_type:: 4123 #endif cend() const4124 const_iterator2 cend () const { 4125 return end (); 4126 } 4127 BOOST_UBLAS_INLINE 4128 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4129 typename self_type:: 4130 #endif rbegin() const4131 const_reverse_iterator2 rbegin () const { 4132 return const_reverse_iterator2 (end ()); 4133 } 4134 BOOST_UBLAS_INLINE 4135 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4136 typename self_type:: 4137 #endif crbegin() const4138 const_reverse_iterator2 crbegin () const { 4139 return rbegin (); 4140 } 4141 BOOST_UBLAS_INLINE 4142 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4143 typename self_type:: 4144 #endif rend() const4145 const_reverse_iterator2 rend () const { 4146 return const_reverse_iterator2 (begin ()); 4147 } 4148 BOOST_UBLAS_INLINE 4149 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4150 typename self_type:: 4151 #endif crend() const4152 const_reverse_iterator2 crend () const { 4153 return rend (); 4154 } 4155 #endif 4156 4157 // Indices 4158 BOOST_UBLAS_INLINE index1() const4159 size_type index1 () const { 4160 return it_; 4161 } 4162 BOOST_UBLAS_INLINE index2() const4163 size_type index2 () const { 4164 return it_; 4165 } 4166 4167 // Assignment 4168 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)4169 const_iterator1 &operator = (const const_iterator1 &it) { 4170 container_const_reference<self_type>::assign (&it ()); 4171 it_ = it.it_; 4172 return *this; 4173 } 4174 4175 // Comparison 4176 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const4177 bool operator == (const const_iterator1 &it) const { 4178 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 4179 return it_ == it.it_; 4180 } 4181 4182 private: 4183 const_subiterator_type it_; 4184 }; 4185 4186 typedef const_iterator1 iterator1; 4187 4188 BOOST_UBLAS_INLINE begin1() const4189 const_iterator1 begin1 () const { 4190 return const_iterator1 (*this, 0); 4191 } 4192 BOOST_UBLAS_INLINE cbegin1() const4193 const_iterator1 cbegin1 () const { 4194 return begin1 (); 4195 } 4196 BOOST_UBLAS_INLINE end1() const4197 const_iterator1 end1 () const { 4198 return const_iterator1 (*this, size_common_); 4199 } 4200 BOOST_UBLAS_INLINE cend1() const4201 const_iterator1 cend1 () const { 4202 return end1 (); 4203 } 4204 4205 class const_iterator2: 4206 public container_const_reference<identity_matrix>, 4207 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag, 4208 const_iterator2, value_type> { 4209 public: 4210 typedef typename identity_matrix::value_type value_type; 4211 typedef typename identity_matrix::difference_type difference_type; 4212 typedef typename identity_matrix::const_reference reference; 4213 typedef typename identity_matrix::const_pointer pointer; 4214 4215 typedef const_iterator1 dual_iterator_type; 4216 typedef const_reverse_iterator1 dual_reverse_iterator_type; 4217 4218 // Construction and destruction 4219 BOOST_UBLAS_INLINE const_iterator2()4220 const_iterator2 (): 4221 container_const_reference<self_type> (), it_ () {} 4222 BOOST_UBLAS_INLINE const_iterator2(const self_type & m,const const_subiterator_type & it)4223 const_iterator2 (const self_type &m, const const_subiterator_type &it): 4224 container_const_reference<self_type> (m), it_ (it) {} 4225 4226 // Arithmetic 4227 BOOST_UBLAS_INLINE operator ++()4228 const_iterator2 &operator ++ () { 4229 BOOST_UBLAS_CHECK (it_ < (*this) ().size_common_, bad_index ()); 4230 ++it_; 4231 return *this; 4232 } 4233 BOOST_UBLAS_INLINE operator --()4234 const_iterator2 &operator -- () { 4235 BOOST_UBLAS_CHECK (it_ > 0, bad_index ()); 4236 --it_; 4237 return *this; 4238 } 4239 4240 // Dereference 4241 BOOST_UBLAS_INLINE operator *() const4242 const_reference operator * () const { 4243 return one_; 4244 } 4245 4246 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 4247 BOOST_UBLAS_INLINE 4248 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4249 typename self_type:: 4250 #endif begin() const4251 const_iterator1 begin () const { 4252 return const_iterator1 ((*this) (), it_); 4253 } 4254 BOOST_UBLAS_INLINE 4255 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4256 typename self_type:: 4257 #endif cbegin() const4258 const_iterator1 cbegin () const { 4259 return begin (); 4260 } 4261 BOOST_UBLAS_INLINE 4262 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4263 typename self_type:: 4264 #endif end() const4265 const_iterator1 end () const { 4266 return const_iterator1 ((*this) (), it_ + 1); 4267 } 4268 BOOST_UBLAS_INLINE 4269 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4270 typename self_type:: 4271 #endif cend() const4272 const_iterator1 cend () const { 4273 return end (); 4274 } 4275 BOOST_UBLAS_INLINE 4276 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4277 typename self_type:: 4278 #endif rbegin() const4279 const_reverse_iterator1 rbegin () const { 4280 return const_reverse_iterator1 (end ()); 4281 } 4282 BOOST_UBLAS_INLINE 4283 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4284 typename self_type:: 4285 #endif crbegin() const4286 const_reverse_iterator1 crbegin () const { 4287 return rbegin (); 4288 } 4289 BOOST_UBLAS_INLINE 4290 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4291 typename self_type:: 4292 #endif rend() const4293 const_reverse_iterator1 rend () const { 4294 return const_reverse_iterator1 (begin ()); 4295 } 4296 BOOST_UBLAS_INLINE 4297 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4298 typename self_type:: 4299 #endif crend() const4300 const_reverse_iterator1 crend () const { 4301 return rend (); 4302 } 4303 #endif 4304 4305 // Indices 4306 BOOST_UBLAS_INLINE index1() const4307 size_type index1 () const { 4308 return it_; 4309 } 4310 BOOST_UBLAS_INLINE index2() const4311 size_type index2 () const { 4312 return it_; 4313 } 4314 4315 // Assignment 4316 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)4317 const_iterator2 &operator = (const const_iterator2 &it) { 4318 container_const_reference<self_type>::assign (&it ()); 4319 it_ = it.it_; 4320 return *this; 4321 } 4322 4323 // Comparison 4324 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const4325 bool operator == (const const_iterator2 &it) const { 4326 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 4327 return it_ == it.it_; 4328 } 4329 4330 private: 4331 const_subiterator_type it_; 4332 }; 4333 4334 typedef const_iterator2 iterator2; 4335 4336 BOOST_UBLAS_INLINE begin2() const4337 const_iterator2 begin2 () const { 4338 return const_iterator2 (*this, 0); 4339 } 4340 BOOST_UBLAS_INLINE cbegin2() const4341 const_iterator2 cbegin2 () const { 4342 return begin2 (); 4343 } 4344 BOOST_UBLAS_INLINE end2() const4345 const_iterator2 end2 () const { 4346 return const_iterator2 (*this, size_common_); 4347 } 4348 BOOST_UBLAS_INLINE cend2() const4349 const_iterator2 cend2 () const { 4350 return end2 (); 4351 } 4352 4353 // Reverse iterators 4354 4355 BOOST_UBLAS_INLINE rbegin1() const4356 const_reverse_iterator1 rbegin1 () const { 4357 return const_reverse_iterator1 (end1 ()); 4358 } 4359 BOOST_UBLAS_INLINE crbegin1() const4360 const_reverse_iterator1 crbegin1 () const { 4361 return rbegin1 (); 4362 } 4363 BOOST_UBLAS_INLINE rend1() const4364 const_reverse_iterator1 rend1 () const { 4365 return const_reverse_iterator1 (begin1 ()); 4366 } 4367 BOOST_UBLAS_INLINE crend1() const4368 const_reverse_iterator1 crend1 () const { 4369 return rend1 (); 4370 } 4371 4372 BOOST_UBLAS_INLINE rbegin2() const4373 const_reverse_iterator2 rbegin2 () const { 4374 return const_reverse_iterator2 (end2 ()); 4375 } 4376 BOOST_UBLAS_INLINE crbegin2() const4377 const_reverse_iterator2 crbegin2 () const { 4378 return rbegin2 (); 4379 } 4380 BOOST_UBLAS_INLINE rend2() const4381 const_reverse_iterator2 rend2 () const { 4382 return const_reverse_iterator2 (begin2 ()); 4383 } 4384 BOOST_UBLAS_INLINE crend2() const4385 const_reverse_iterator2 crend2 () const { 4386 return rend2 (); 4387 } 4388 4389 // Serialization 4390 template<class Archive> serialize(Archive & ar,const unsigned int)4391 void serialize(Archive & ar, const unsigned int /* file_version */){ 4392 4393 // we need to copy to a collection_size_type to get a portable 4394 // and efficient serialization 4395 serialization::collection_size_type s1 (size1_); 4396 serialization::collection_size_type s2 (size2_); 4397 4398 // serialize the sizes 4399 ar & serialization::make_nvp("size1",s1) 4400 & serialization::make_nvp("size2",s2); 4401 4402 // copy the values back if loading 4403 if (Archive::is_loading::value) { 4404 size1_ = s1; 4405 size2_ = s2; 4406 size_common_ = ((std::min)(size1_, size2_)); 4407 } 4408 } 4409 4410 private: 4411 size_type size1_; 4412 size_type size2_; 4413 size_type size_common_; 4414 static const value_type zero_; 4415 static const value_type one_; 4416 }; 4417 4418 template<class T, class ALLOC> 4419 const typename identity_matrix<T, ALLOC>::value_type identity_matrix<T, ALLOC>::zero_ = T(/*zero*/); 4420 template<class T, class ALLOC> 4421 const typename identity_matrix<T, ALLOC>::value_type identity_matrix<T, ALLOC>::one_ (1); // ISSUE: need 'one'-traits here 4422 4423 4424 /** \brief A matrix with all values of type \c T equal to the same value 4425 * 4426 * Changing one value has the effect of changing all the values. Assigning it to a normal matrix will copy 4427 * the same value everywhere in this matrix. All accesses are constant time, due to the trivial value. 4428 * 4429 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...) 4430 * \tparam ALLOC an allocator for storing the unique value. By default, a standar allocator is used. 4431 */ 4432 template<class T, class ALLOC> 4433 class scalar_matrix: 4434 public matrix_container<scalar_matrix<T, ALLOC> > { 4435 4436 typedef const T *const_pointer; 4437 typedef scalar_matrix<T, ALLOC> self_type; 4438 public: 4439 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 4440 using matrix_container<self_type>::operator (); 4441 #endif 4442 typedef std::size_t size_type; 4443 typedef std::ptrdiff_t difference_type; 4444 typedef T value_type; 4445 typedef const T &const_reference; 4446 typedef T &reference; 4447 typedef const matrix_reference<const self_type> const_closure_type; 4448 typedef matrix_reference<self_type> closure_type; 4449 typedef dense_tag storage_category; 4450 typedef unknown_orientation_tag orientation_category; 4451 4452 // Construction and destruction 4453 BOOST_UBLAS_INLINE scalar_matrix()4454 scalar_matrix (): 4455 matrix_container<self_type> (), 4456 size1_ (0), size2_ (0), value_ () {} 4457 BOOST_UBLAS_INLINE scalar_matrix(size_type size1,size_type size2,const value_type & value=value_type (1))4458 scalar_matrix (size_type size1, size_type size2, const value_type &value = value_type(1)): 4459 matrix_container<self_type> (), 4460 size1_ (size1), size2_ (size2), value_ (value) {} 4461 BOOST_UBLAS_INLINE scalar_matrix(const scalar_matrix & m)4462 scalar_matrix (const scalar_matrix &m): 4463 matrix_container<self_type> (), 4464 size1_ (m.size1_), size2_ (m.size2_), value_ (m.value_) {} 4465 4466 // Accessors 4467 BOOST_UBLAS_INLINE size1() const4468 size_type size1 () const { 4469 return size1_; 4470 } 4471 BOOST_UBLAS_INLINE size2() const4472 size_type size2 () const { 4473 return size2_; 4474 } 4475 4476 // Resizing 4477 BOOST_UBLAS_INLINE resize(size_type size1,size_type size2,bool=true)4478 void resize (size_type size1, size_type size2, bool /*preserve*/ = true) { 4479 size1_ = size1; 4480 size2_ = size2; 4481 } 4482 4483 // Element access 4484 BOOST_UBLAS_INLINE operator ()(size_type,size_type) const4485 const_reference operator () (size_type /*i*/, size_type /*j*/) const { 4486 return value_; 4487 } 4488 4489 // Assignment 4490 BOOST_UBLAS_INLINE operator =(const scalar_matrix & m)4491 scalar_matrix &operator = (const scalar_matrix &m) { 4492 size1_ = m.size1_; 4493 size2_ = m.size2_; 4494 value_ = m.value_; 4495 return *this; 4496 } 4497 BOOST_UBLAS_INLINE assign_temporary(scalar_matrix & m)4498 scalar_matrix &assign_temporary (scalar_matrix &m) { 4499 swap (m); 4500 return *this; 4501 } 4502 4503 // Swapping 4504 BOOST_UBLAS_INLINE swap(scalar_matrix & m)4505 void swap (scalar_matrix &m) { 4506 if (this != &m) { 4507 std::swap (size1_, m.size1_); 4508 std::swap (size2_, m.size2_); 4509 std::swap (value_, m.value_); 4510 } 4511 } 4512 BOOST_UBLAS_INLINE swap(scalar_matrix & m1,scalar_matrix & m2)4513 friend void swap (scalar_matrix &m1, scalar_matrix &m2) { 4514 m1.swap (m2); 4515 } 4516 4517 // Iterator types 4518 private: 4519 // Use an index 4520 typedef size_type const_subiterator_type; 4521 4522 public: 4523 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 4524 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> iterator1; 4525 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> iterator2; 4526 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1; 4527 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2; 4528 #else 4529 class const_iterator1; 4530 class const_iterator2; 4531 #endif 4532 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 4533 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 4534 4535 // Element lookup 4536 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j) const4537 const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const { 4538 return const_iterator1 (*this, i, j); 4539 } 4540 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j) const4541 const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const { 4542 return const_iterator2 (*this, i, j); 4543 } 4544 4545 4546 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 4547 class const_iterator1: 4548 public container_const_reference<scalar_matrix>, 4549 public random_access_iterator_base<dense_random_access_iterator_tag, 4550 const_iterator1, value_type> { 4551 public: 4552 typedef typename scalar_matrix::value_type value_type; 4553 typedef typename scalar_matrix::difference_type difference_type; 4554 typedef typename scalar_matrix::const_reference reference; 4555 typedef typename scalar_matrix::const_pointer pointer; 4556 4557 typedef const_iterator2 dual_iterator_type; 4558 typedef const_reverse_iterator2 dual_reverse_iterator_type; 4559 4560 // Construction and destruction 4561 BOOST_UBLAS_INLINE const_iterator1()4562 const_iterator1 (): 4563 container_const_reference<scalar_matrix> (), it1_ (), it2_ () {} 4564 BOOST_UBLAS_INLINE const_iterator1(const scalar_matrix & m,const const_subiterator_type & it1,const const_subiterator_type & it2)4565 const_iterator1 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2): 4566 container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {} 4567 4568 // Arithmetic 4569 BOOST_UBLAS_INLINE operator ++()4570 const_iterator1 &operator ++ () { 4571 ++ it1_; 4572 return *this; 4573 } 4574 BOOST_UBLAS_INLINE operator --()4575 const_iterator1 &operator -- () { 4576 -- it1_; 4577 return *this; 4578 } 4579 BOOST_UBLAS_INLINE operator +=(difference_type n)4580 const_iterator1 &operator += (difference_type n) { 4581 it1_ += n; 4582 return *this; 4583 } 4584 BOOST_UBLAS_INLINE operator -=(difference_type n)4585 const_iterator1 &operator -= (difference_type n) { 4586 it1_ -= n; 4587 return *this; 4588 } 4589 BOOST_UBLAS_INLINE operator -(const const_iterator1 & it) const4590 difference_type operator - (const const_iterator1 &it) const { 4591 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 4592 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 4593 return it1_ - it.it1_; 4594 } 4595 4596 // Dereference 4597 BOOST_UBLAS_INLINE operator *() const4598 const_reference operator * () const { 4599 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 4600 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 4601 return (*this) () (index1 (), index2 ()); 4602 } 4603 BOOST_UBLAS_INLINE operator [](difference_type n) const4604 const_reference operator [] (difference_type n) const { 4605 return *(*this + n); 4606 } 4607 4608 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 4609 BOOST_UBLAS_INLINE 4610 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4611 typename self_type:: 4612 #endif begin() const4613 const_iterator2 begin () const { 4614 const scalar_matrix &m = (*this) (); 4615 return m.find2 (1, index1 (), 0); 4616 } 4617 BOOST_UBLAS_INLINE 4618 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4619 typename self_type:: 4620 #endif cbegin() const4621 const_iterator2 cbegin () const { 4622 return begin (); 4623 } 4624 BOOST_UBLAS_INLINE 4625 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4626 typename self_type:: 4627 #endif end() const4628 const_iterator2 end () const { 4629 const scalar_matrix &m = (*this) (); 4630 return m.find2 (1, index1 (), m.size2 ()); 4631 } 4632 BOOST_UBLAS_INLINE 4633 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4634 typename self_type:: 4635 #endif cend() const4636 const_iterator2 cend () const { 4637 return end (); 4638 } 4639 BOOST_UBLAS_INLINE 4640 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4641 typename self_type:: 4642 #endif rbegin() const4643 const_reverse_iterator2 rbegin () const { 4644 return const_reverse_iterator2 (end ()); 4645 } 4646 BOOST_UBLAS_INLINE 4647 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4648 typename self_type:: 4649 #endif crbegin() const4650 const_reverse_iterator2 crbegin () const { 4651 return rbegin (); 4652 } 4653 BOOST_UBLAS_INLINE 4654 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4655 typename self_type:: 4656 #endif rend() const4657 const_reverse_iterator2 rend () const { 4658 return const_reverse_iterator2 (begin ()); 4659 } 4660 BOOST_UBLAS_INLINE 4661 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4662 typename self_type:: 4663 #endif crend() const4664 const_reverse_iterator2 crend () const { 4665 return rend (); 4666 } 4667 #endif 4668 4669 // Indices 4670 BOOST_UBLAS_INLINE index1() const4671 size_type index1 () const { 4672 return it1_; 4673 } 4674 BOOST_UBLAS_INLINE index2() const4675 size_type index2 () const { 4676 return it2_; 4677 } 4678 4679 // Assignment 4680 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)4681 const_iterator1 &operator = (const const_iterator1 &it) { 4682 container_const_reference<scalar_matrix>::assign (&it ()); 4683 it1_ = it.it1_; 4684 it2_ = it.it2_; 4685 return *this; 4686 } 4687 4688 // Comparison 4689 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const4690 bool operator == (const const_iterator1 &it) const { 4691 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 4692 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 4693 return it1_ == it.it1_; 4694 } 4695 BOOST_UBLAS_INLINE operator <(const const_iterator1 & it) const4696 bool operator < (const const_iterator1 &it) const { 4697 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 4698 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 4699 return it1_ < it.it1_; 4700 } 4701 4702 private: 4703 const_subiterator_type it1_; 4704 const_subiterator_type it2_; 4705 }; 4706 4707 typedef const_iterator1 iterator1; 4708 #endif 4709 4710 BOOST_UBLAS_INLINE begin1() const4711 const_iterator1 begin1 () const { 4712 return find1 (0, 0, 0); 4713 } 4714 BOOST_UBLAS_INLINE cbegin1() const4715 const_iterator1 cbegin1 () const { 4716 return begin1 (); 4717 } 4718 BOOST_UBLAS_INLINE end1() const4719 const_iterator1 end1 () const { 4720 return find1 (0, size1_, 0); 4721 } 4722 BOOST_UBLAS_INLINE cend1() const4723 const_iterator1 cend1 () const { 4724 return end1 (); 4725 } 4726 4727 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 4728 class const_iterator2: 4729 public container_const_reference<scalar_matrix>, 4730 public random_access_iterator_base<dense_random_access_iterator_tag, 4731 const_iterator2, value_type> { 4732 public: 4733 typedef typename scalar_matrix::value_type value_type; 4734 typedef typename scalar_matrix::difference_type difference_type; 4735 typedef typename scalar_matrix::const_reference reference; 4736 typedef typename scalar_matrix::const_pointer pointer; 4737 4738 typedef const_iterator1 dual_iterator_type; 4739 typedef const_reverse_iterator1 dual_reverse_iterator_type; 4740 4741 // Construction and destruction 4742 BOOST_UBLAS_INLINE const_iterator2()4743 const_iterator2 (): 4744 container_const_reference<scalar_matrix> (), it1_ (), it2_ () {} 4745 BOOST_UBLAS_INLINE const_iterator2(const scalar_matrix & m,const const_subiterator_type & it1,const const_subiterator_type & it2)4746 const_iterator2 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2): 4747 container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {} 4748 4749 // Arithmetic 4750 BOOST_UBLAS_INLINE operator ++()4751 const_iterator2 &operator ++ () { 4752 ++ it2_; 4753 return *this; 4754 } 4755 BOOST_UBLAS_INLINE operator --()4756 const_iterator2 &operator -- () { 4757 -- it2_; 4758 return *this; 4759 } 4760 BOOST_UBLAS_INLINE operator +=(difference_type n)4761 const_iterator2 &operator += (difference_type n) { 4762 it2_ += n; 4763 return *this; 4764 } 4765 BOOST_UBLAS_INLINE operator -=(difference_type n)4766 const_iterator2 &operator -= (difference_type n) { 4767 it2_ -= n; 4768 return *this; 4769 } 4770 BOOST_UBLAS_INLINE operator -(const const_iterator2 & it) const4771 difference_type operator - (const const_iterator2 &it) const { 4772 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 4773 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 4774 return it2_ - it.it2_; 4775 } 4776 4777 // Dereference 4778 BOOST_UBLAS_INLINE operator *() const4779 const_reference operator * () const { 4780 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 4781 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 4782 return (*this) () (index1 (), index2 ()); 4783 } 4784 BOOST_UBLAS_INLINE operator [](difference_type n) const4785 const_reference operator [] (difference_type n) const { 4786 return *(*this + n); 4787 } 4788 4789 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 4790 BOOST_UBLAS_INLINE 4791 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4792 typename self_type:: 4793 #endif begin() const4794 const_iterator1 begin () const { 4795 const scalar_matrix &m = (*this) (); 4796 return m.find1 (1, 0, index2 ()); 4797 } 4798 BOOST_UBLAS_INLINE 4799 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4800 typename self_type:: 4801 #endif cbegin() const4802 const_iterator1 cbegin () const { 4803 return begin (); 4804 } 4805 BOOST_UBLAS_INLINE 4806 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4807 typename self_type:: 4808 #endif end() const4809 const_iterator1 end () const { 4810 const scalar_matrix &m = (*this) (); 4811 return m.find1 (1, m.size1 (), index2 ()); 4812 } 4813 BOOST_UBLAS_INLINE 4814 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4815 typename self_type:: 4816 #endif cend() const4817 const_iterator1 cend () const { 4818 return end (); 4819 } 4820 BOOST_UBLAS_INLINE 4821 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4822 typename self_type:: 4823 #endif rbegin() const4824 const_reverse_iterator1 rbegin () const { 4825 return const_reverse_iterator1 (end ()); 4826 } 4827 BOOST_UBLAS_INLINE 4828 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4829 typename self_type:: 4830 #endif crbegin() const4831 const_reverse_iterator1 crbegin () const { 4832 return rbegin (); 4833 } 4834 BOOST_UBLAS_INLINE 4835 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4836 typename self_type:: 4837 #endif rend() const4838 const_reverse_iterator1 rend () const { 4839 return const_reverse_iterator1 (begin ()); 4840 } 4841 BOOST_UBLAS_INLINE 4842 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4843 typename self_type:: 4844 #endif crend() const4845 const_reverse_iterator1 crend () const { 4846 return rend (); 4847 } 4848 #endif 4849 4850 // Indices 4851 BOOST_UBLAS_INLINE index1() const4852 size_type index1 () const { 4853 return it1_; 4854 } 4855 BOOST_UBLAS_INLINE index2() const4856 size_type index2 () const { 4857 return it2_; 4858 } 4859 4860 // Assignment 4861 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)4862 const_iterator2 &operator = (const const_iterator2 &it) { 4863 container_const_reference<scalar_matrix>::assign (&it ()); 4864 it1_ = it.it1_; 4865 it2_ = it.it2_; 4866 return *this; 4867 } 4868 4869 // Comparison 4870 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const4871 bool operator == (const const_iterator2 &it) const { 4872 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 4873 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 4874 return it2_ == it.it2_; 4875 } 4876 BOOST_UBLAS_INLINE operator <(const const_iterator2 & it) const4877 bool operator < (const const_iterator2 &it) const { 4878 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 4879 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 4880 return it2_ < it.it2_; 4881 } 4882 4883 private: 4884 const_subiterator_type it1_; 4885 const_subiterator_type it2_; 4886 }; 4887 4888 typedef const_iterator2 iterator2; 4889 #endif 4890 4891 BOOST_UBLAS_INLINE begin2() const4892 const_iterator2 begin2 () const { 4893 return find2 (0, 0, 0); 4894 } 4895 BOOST_UBLAS_INLINE cbegin2() const4896 const_iterator2 cbegin2 () const { 4897 return begin2 (); 4898 } 4899 BOOST_UBLAS_INLINE end2() const4900 const_iterator2 end2 () const { 4901 return find2 (0, 0, size2_); 4902 } 4903 BOOST_UBLAS_INLINE cend2() const4904 const_iterator2 cend2 () const { 4905 return end2 (); 4906 } 4907 4908 // Reverse iterators 4909 4910 BOOST_UBLAS_INLINE rbegin1() const4911 const_reverse_iterator1 rbegin1 () const { 4912 return const_reverse_iterator1 (end1 ()); 4913 } 4914 BOOST_UBLAS_INLINE crbegin1() const4915 const_reverse_iterator1 crbegin1 () const { 4916 return rbegin1 (); 4917 } 4918 BOOST_UBLAS_INLINE rend1() const4919 const_reverse_iterator1 rend1 () const { 4920 return const_reverse_iterator1 (begin1 ()); 4921 } 4922 BOOST_UBLAS_INLINE crend1() const4923 const_reverse_iterator1 crend1 () const { 4924 return rend1 (); 4925 } 4926 4927 BOOST_UBLAS_INLINE rbegin2() const4928 const_reverse_iterator2 rbegin2 () const { 4929 return const_reverse_iterator2 (end2 ()); 4930 } 4931 BOOST_UBLAS_INLINE crbegin2() const4932 const_reverse_iterator2 crbegin2 () const { 4933 return rbegin2 (); 4934 } 4935 BOOST_UBLAS_INLINE rend2() const4936 const_reverse_iterator2 rend2 () const { 4937 return const_reverse_iterator2 (begin2 ()); 4938 } 4939 BOOST_UBLAS_INLINE crend2() const4940 const_reverse_iterator2 crend2 () const { 4941 return rend2 (); 4942 } 4943 4944 // Serialization 4945 template<class Archive> serialize(Archive & ar,const unsigned int)4946 void serialize(Archive & ar, const unsigned int /* file_version */){ 4947 4948 // we need to copy to a collection_size_type to get a portable 4949 // and efficient serialization 4950 serialization::collection_size_type s1 (size1_); 4951 serialization::collection_size_type s2 (size2_); 4952 4953 // serialize the sizes 4954 ar & serialization::make_nvp("size1",s1) 4955 & serialization::make_nvp("size2",s2); 4956 4957 // copy the values back if loading 4958 if (Archive::is_loading::value) { 4959 size1_ = s1; 4960 size2_ = s2; 4961 } 4962 4963 ar & serialization::make_nvp("value", value_); 4964 } 4965 4966 private: 4967 size_type size1_; 4968 size_type size2_; 4969 value_type value_; 4970 }; 4971 4972 4973 /** \brief An array based matrix class which size is defined at type specification or object instanciation 4974 * 4975 * This matrix is directly based on a predefined C-style arry of data, thus providing the fastest 4976 * implementation possible. The constraint is that dimensions of the matrix must be specified at 4977 * the instanciation or the type specification. 4978 * 4979 * For instance, \code typedef c_matrix<double,4,4> my_4by4_matrix \endcode 4980 * defines a 4 by 4 double-precision matrix. You can also instantiate it directly with 4981 * \code c_matrix<int,8,5> my_fast_matrix \endcode. This will make a 8 by 5 integer matrix. The 4982 * price to pay for this speed is that you cannot resize it to a size larger than the one defined 4983 * in the template parameters. In the previous example, a size of 4 by 5 or 3 by 2 is acceptable, 4984 * but a new size of 9 by 5 or even 10 by 10 will raise a bad_size() exception. 4985 * 4986 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...) 4987 * \tparam N the default maximum number of rows 4988 * \tparam M the default maximum number of columns 4989 */ 4990 template<class T, std::size_t N, std::size_t M> 4991 class c_matrix: 4992 public matrix_container<c_matrix<T, N, M> > { 4993 4994 typedef c_matrix<T, N, M> self_type; 4995 public: 4996 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 4997 using matrix_container<self_type>::operator (); 4998 #endif 4999 typedef std::size_t size_type; 5000 typedef std::ptrdiff_t difference_type; 5001 typedef T value_type; 5002 typedef const T &const_reference; 5003 typedef T &reference; 5004 typedef const T *const_pointer; 5005 typedef T *pointer; 5006 typedef const matrix_reference<const self_type> const_closure_type; 5007 typedef matrix_reference<self_type> closure_type; 5008 typedef c_vector<T, N * M> vector_temporary_type; // vector able to store all elements of c_matrix 5009 typedef self_type matrix_temporary_type; 5010 typedef dense_tag storage_category; 5011 // This could be better for performance, 5012 // typedef typename unknown_orientation_tag orientation_category; 5013 // but others depend on the orientation information... 5014 typedef row_major_tag orientation_category; 5015 5016 // Construction and destruction 5017 BOOST_UBLAS_INLINE c_matrix()5018 c_matrix (): 5019 size1_ (N), size2_ (M) /* , data_ () */ { 5020 } 5021 BOOST_UBLAS_INLINE c_matrix(size_type size1,size_type size2)5022 c_matrix (size_type size1, size_type size2): 5023 size1_ (size1), size2_ (size2) /* , data_ () */ { 5024 if (size1_ > N || size2_ > M) 5025 bad_size ().raise (); 5026 } 5027 BOOST_UBLAS_INLINE c_matrix(const c_matrix & m)5028 c_matrix (const c_matrix &m): 5029 size1_ (m.size1_), size2_ (m.size2_) /* , data_ () */ { 5030 if (size1_ > N || size2_ > M) 5031 bad_size ().raise (); 5032 assign(m); 5033 } 5034 template<class AE> 5035 BOOST_UBLAS_INLINE c_matrix(const matrix_expression<AE> & ae)5036 c_matrix (const matrix_expression<AE> &ae): 5037 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()) /* , data_ () */ { 5038 if (size1_ > N || size2_ > M) 5039 bad_size ().raise (); 5040 matrix_assign<scalar_assign> (*this, ae); 5041 } 5042 5043 // Accessors 5044 BOOST_UBLAS_INLINE size1() const5045 size_type size1 () const { 5046 return size1_; 5047 } 5048 BOOST_UBLAS_INLINE size2() const5049 size_type size2 () const { 5050 return size2_; 5051 } 5052 BOOST_UBLAS_INLINE data() const5053 const_pointer data () const { 5054 return reinterpret_cast<const_pointer> (data_); 5055 } 5056 BOOST_UBLAS_INLINE data()5057 pointer data () { 5058 return reinterpret_cast<pointer> (data_); 5059 } 5060 5061 // Resizing 5062 BOOST_UBLAS_INLINE resize(size_type size1,size_type size2,bool preserve=true)5063 void resize (size_type size1, size_type size2, bool preserve = true) { 5064 if (size1 > N || size2 > M) 5065 bad_size ().raise (); 5066 if (preserve) { 5067 self_type temporary (size1, size2); 5068 // Common elements to preserve 5069 const size_type size1_min = (std::min) (size1, size1_); 5070 const size_type size2_min = (std::min) (size2, size2_); 5071 for (size_type i = 0; i != size1_min; ++i) { // indexing copy over major 5072 for (size_type j = 0; j != size2_min; ++j) { 5073 temporary.data_[i][j] = data_[i][j]; 5074 } 5075 } 5076 assign_temporary (temporary); 5077 } 5078 else { 5079 size1_ = size1; 5080 size2_ = size2; 5081 } 5082 } 5083 5084 // Element access 5085 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const5086 const_reference operator () (size_type i, size_type j) const { 5087 BOOST_UBLAS_CHECK (i < size1_, bad_index ()); 5088 BOOST_UBLAS_CHECK (j < size2_, bad_index ()); 5089 return data_ [i] [j]; 5090 } 5091 BOOST_UBLAS_INLINE at_element(size_type i,size_type j)5092 reference at_element (size_type i, size_type j) { 5093 BOOST_UBLAS_CHECK (i < size1_, bad_index ()); 5094 BOOST_UBLAS_CHECK (j < size2_, bad_index ()); 5095 return data_ [i] [j]; 5096 } 5097 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j)5098 reference operator () (size_type i, size_type j) { 5099 return at_element (i, j); 5100 } 5101 5102 // Element assignment 5103 BOOST_UBLAS_INLINE insert_element(size_type i,size_type j,const_reference t)5104 reference insert_element (size_type i, size_type j, const_reference t) { 5105 return (at_element (i, j) = t); 5106 } 5107 5108 // Zeroing 5109 BOOST_UBLAS_INLINE clear()5110 void clear () { 5111 for (size_type i = 0; i < size1_; ++ i) 5112 std::fill (data_ [i], data_ [i] + size2_, value_type/*zero*/()); 5113 } 5114 5115 // Assignment 5116 #ifdef BOOST_UBLAS_MOVE_SEMANTICS 5117 5118 /*! @note "pass by value" the key idea to enable move semantics */ 5119 BOOST_UBLAS_INLINE operator =(c_matrix m)5120 c_matrix &operator = (c_matrix m) { 5121 assign_temporary(m); 5122 return *this; 5123 } 5124 #else 5125 BOOST_UBLAS_INLINE operator =(const c_matrix & m)5126 c_matrix &operator = (const c_matrix &m) { 5127 size1_ = m.size1_; 5128 size2_ = m.size2_; 5129 for (size_type i = 0; i < m.size1_; ++ i) 5130 std::copy (m.data_ [i], m.data_ [i] + m.size2_, data_ [i]); 5131 return *this; 5132 } 5133 #endif 5134 template<class C> // Container assignment without temporary 5135 BOOST_UBLAS_INLINE operator =(const matrix_container<C> & m)5136 c_matrix &operator = (const matrix_container<C> &m) { 5137 resize (m ().size1 (), m ().size2 (), false); 5138 assign (m); 5139 return *this; 5140 } 5141 BOOST_UBLAS_INLINE assign_temporary(c_matrix & m)5142 c_matrix &assign_temporary (c_matrix &m) { 5143 swap (m); 5144 return *this; 5145 } 5146 template<class AE> 5147 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)5148 c_matrix &operator = (const matrix_expression<AE> &ae) { 5149 self_type temporary (ae); 5150 return assign_temporary (temporary); 5151 } 5152 template<class AE> 5153 BOOST_UBLAS_INLINE assign(const matrix_expression<AE> & ae)5154 c_matrix &assign (const matrix_expression<AE> &ae) { 5155 matrix_assign<scalar_assign> (*this, ae); 5156 return *this; 5157 } 5158 template<class AE> 5159 BOOST_UBLAS_INLINE operator +=(const matrix_expression<AE> & ae)5160 c_matrix& operator += (const matrix_expression<AE> &ae) { 5161 self_type temporary (*this + ae); 5162 return assign_temporary (temporary); 5163 } 5164 template<class C> // Container assignment without temporary 5165 BOOST_UBLAS_INLINE operator +=(const matrix_container<C> & m)5166 c_matrix &operator += (const matrix_container<C> &m) { 5167 plus_assign (m); 5168 return *this; 5169 } 5170 template<class AE> 5171 BOOST_UBLAS_INLINE plus_assign(const matrix_expression<AE> & ae)5172 c_matrix &plus_assign (const matrix_expression<AE> &ae) { 5173 matrix_assign<scalar_plus_assign> (*this, ae); 5174 return *this; 5175 } 5176 template<class AE> 5177 BOOST_UBLAS_INLINE operator -=(const matrix_expression<AE> & ae)5178 c_matrix& operator -= (const matrix_expression<AE> &ae) { 5179 self_type temporary (*this - ae); 5180 return assign_temporary (temporary); 5181 } 5182 template<class C> // Container assignment without temporary 5183 BOOST_UBLAS_INLINE operator -=(const matrix_container<C> & m)5184 c_matrix &operator -= (const matrix_container<C> &m) { 5185 minus_assign (m); 5186 return *this; 5187 } 5188 template<class AE> 5189 BOOST_UBLAS_INLINE minus_assign(const matrix_expression<AE> & ae)5190 c_matrix &minus_assign (const matrix_expression<AE> &ae) { 5191 matrix_assign<scalar_minus_assign> (*this, ae); 5192 return *this; 5193 } 5194 template<class AT> 5195 BOOST_UBLAS_INLINE operator *=(const AT & at)5196 c_matrix& operator *= (const AT &at) { 5197 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 5198 return *this; 5199 } 5200 template<class AT> 5201 BOOST_UBLAS_INLINE operator /=(const AT & at)5202 c_matrix& operator /= (const AT &at) { 5203 matrix_assign_scalar<scalar_divides_assign> (*this, at); 5204 return *this; 5205 } 5206 5207 // Swapping 5208 BOOST_UBLAS_INLINE swap(c_matrix & m)5209 void swap (c_matrix &m) { 5210 if (this != &m) { 5211 BOOST_UBLAS_CHECK (size1_ == m.size1_, bad_size ()); 5212 BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ()); 5213 std::swap (size1_, m.size1_); 5214 std::swap (size2_, m.size2_); 5215 for (size_type i = 0; i < size1_; ++ i) 5216 std::swap_ranges (data_ [i], data_ [i] + size2_, m.data_ [i]); 5217 } 5218 } 5219 BOOST_UBLAS_INLINE swap(c_matrix & m1,c_matrix & m2)5220 friend void swap (c_matrix &m1, c_matrix &m2) { 5221 m1.swap (m2); 5222 } 5223 5224 // Iterator types 5225 private: 5226 // Use pointers for iterator 5227 typedef const_pointer const_subiterator_type; 5228 typedef pointer subiterator_type; 5229 5230 public: 5231 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 5232 typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1; 5233 typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2; 5234 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1; 5235 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2; 5236 #else 5237 class const_iterator1; 5238 class iterator1; 5239 class const_iterator2; 5240 class iterator2; 5241 #endif 5242 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 5243 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 5244 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 5245 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 5246 5247 // Element lookup 5248 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j) const5249 const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const { 5250 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 5251 return const_iterator1 (*this, i, j); 5252 #else 5253 return const_iterator1 (*this, &data_ [i] [j]); 5254 #endif 5255 } 5256 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j)5257 iterator1 find1 (int /*rank*/, size_type i, size_type j) { 5258 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 5259 return iterator1 (*this, i, j); 5260 #else 5261 return iterator1 (*this, &data_ [i] [j]); 5262 #endif 5263 } 5264 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j) const5265 const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const { 5266 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 5267 return const_iterator2 (*this, i, j); 5268 #else 5269 return const_iterator2 (*this, &data_ [i] [j]); 5270 #endif 5271 } 5272 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j)5273 iterator2 find2 (int /*rank*/, size_type i, size_type j) { 5274 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 5275 return iterator2 (*this, i, j); 5276 #else 5277 return iterator2 (*this, &data_ [i] [j]); 5278 #endif 5279 } 5280 5281 5282 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 5283 class const_iterator1: 5284 public container_const_reference<c_matrix>, 5285 public random_access_iterator_base<dense_random_access_iterator_tag, 5286 const_iterator1, value_type> { 5287 public: 5288 typedef typename c_matrix::difference_type difference_type; 5289 typedef typename c_matrix::value_type value_type; 5290 typedef typename c_matrix::const_reference reference; 5291 typedef typename c_matrix::const_pointer pointer; 5292 5293 typedef const_iterator2 dual_iterator_type; 5294 typedef const_reverse_iterator2 dual_reverse_iterator_type; 5295 5296 // Construction and destruction 5297 BOOST_UBLAS_INLINE const_iterator1()5298 const_iterator1 (): 5299 container_const_reference<self_type> (), it_ () {} 5300 BOOST_UBLAS_INLINE const_iterator1(const self_type & m,const const_subiterator_type & it)5301 const_iterator1 (const self_type &m, const const_subiterator_type &it): 5302 container_const_reference<self_type> (m), it_ (it) {} 5303 BOOST_UBLAS_INLINE const_iterator1(const iterator1 & it)5304 const_iterator1 (const iterator1 &it): 5305 container_const_reference<self_type> (it ()), it_ (it.it_) {} 5306 5307 // Arithmetic 5308 BOOST_UBLAS_INLINE operator ++()5309 const_iterator1 &operator ++ () { 5310 it_ += M; 5311 return *this; 5312 } 5313 BOOST_UBLAS_INLINE operator --()5314 const_iterator1 &operator -- () { 5315 it_ -= M; 5316 return *this; 5317 } 5318 BOOST_UBLAS_INLINE operator +=(difference_type n)5319 const_iterator1 &operator += (difference_type n) { 5320 it_ += n * M; 5321 return *this; 5322 } 5323 BOOST_UBLAS_INLINE operator -=(difference_type n)5324 const_iterator1 &operator -= (difference_type n) { 5325 it_ -= n * M; 5326 return *this; 5327 } 5328 BOOST_UBLAS_INLINE operator -(const const_iterator1 & it) const5329 difference_type operator - (const const_iterator1 &it) const { 5330 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5331 return (it_ - it.it_) / M; 5332 } 5333 5334 // Dereference 5335 BOOST_UBLAS_INLINE operator *() const5336 const_reference operator * () const { 5337 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 5338 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 5339 return *it_; 5340 } 5341 BOOST_UBLAS_INLINE operator [](difference_type n) const5342 const_reference operator [] (difference_type n) const { 5343 return *(*this + n); 5344 } 5345 5346 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 5347 BOOST_UBLAS_INLINE 5348 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5349 typename self_type:: 5350 #endif begin() const5351 const_iterator2 begin () const { 5352 const self_type &m = (*this) (); 5353 return m.find2 (1, index1 (), 0); 5354 } 5355 BOOST_UBLAS_INLINE 5356 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5357 typename self_type:: 5358 #endif cbegin() const5359 const_iterator2 cbegin () const { 5360 return begin (); 5361 } 5362 BOOST_UBLAS_INLINE 5363 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5364 typename self_type:: 5365 #endif end() const5366 const_iterator2 end () const { 5367 const self_type &m = (*this) (); 5368 return m.find2 (1, index1 (), m.size2 ()); 5369 } 5370 BOOST_UBLAS_INLINE 5371 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5372 typename self_type:: 5373 #endif cend() const5374 const_iterator2 cend () const { 5375 return end (); 5376 } 5377 BOOST_UBLAS_INLINE 5378 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5379 typename self_type:: 5380 #endif rbegin() const5381 const_reverse_iterator2 rbegin () const { 5382 return const_reverse_iterator2 (end ()); 5383 } 5384 BOOST_UBLAS_INLINE 5385 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5386 typename self_type:: 5387 #endif crbegin() const5388 const_reverse_iterator2 crbegin () const { 5389 return rbegin (); 5390 } 5391 BOOST_UBLAS_INLINE 5392 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5393 typename self_type:: 5394 #endif rend() const5395 const_reverse_iterator2 rend () const { 5396 return const_reverse_iterator2 (begin ()); 5397 } 5398 BOOST_UBLAS_INLINE 5399 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5400 typename self_type:: 5401 #endif crend() const5402 const_reverse_iterator2 crend () const { 5403 return rend (); 5404 } 5405 #endif 5406 5407 // Indices 5408 BOOST_UBLAS_INLINE index1() const5409 size_type index1 () const { 5410 const self_type &m = (*this) (); 5411 return (it_ - m.begin1 ().it_) / M; 5412 } 5413 BOOST_UBLAS_INLINE index2() const5414 size_type index2 () const { 5415 const self_type &m = (*this) (); 5416 return (it_ - m.begin1 ().it_) % M; 5417 } 5418 5419 // Assignment 5420 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)5421 const_iterator1 &operator = (const const_iterator1 &it) { 5422 container_const_reference<self_type>::assign (&it ()); 5423 it_ = it.it_; 5424 return *this; 5425 } 5426 5427 // Comparison 5428 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const5429 bool operator == (const const_iterator1 &it) const { 5430 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5431 return it_ == it.it_; 5432 } 5433 BOOST_UBLAS_INLINE operator <(const const_iterator1 & it) const5434 bool operator < (const const_iterator1 &it) const { 5435 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5436 return it_ < it.it_; 5437 } 5438 5439 private: 5440 const_subiterator_type it_; 5441 5442 friend class iterator1; 5443 }; 5444 #endif 5445 5446 BOOST_UBLAS_INLINE begin1() const5447 const_iterator1 begin1 () const { 5448 return find1 (0, 0, 0); 5449 } 5450 BOOST_UBLAS_INLINE cbegin1() const5451 const_iterator1 cbegin1 () const { 5452 return begin1 (); 5453 } 5454 BOOST_UBLAS_INLINE end1() const5455 const_iterator1 end1 () const { 5456 return find1 (0, size1_, 0); 5457 } 5458 BOOST_UBLAS_INLINE cend1() const5459 const_iterator1 cend1 () const { 5460 return end1 (); 5461 } 5462 5463 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 5464 class iterator1: 5465 public container_reference<c_matrix>, 5466 public random_access_iterator_base<dense_random_access_iterator_tag, 5467 iterator1, value_type> { 5468 public: 5469 5470 typedef typename c_matrix::difference_type difference_type; 5471 typedef typename c_matrix::value_type value_type; 5472 typedef typename c_matrix::reference reference; 5473 typedef typename c_matrix::pointer pointer; 5474 5475 typedef iterator2 dual_iterator_type; 5476 typedef reverse_iterator2 dual_reverse_iterator_type; 5477 5478 // Construction and destruction 5479 BOOST_UBLAS_INLINE iterator1()5480 iterator1 (): 5481 container_reference<self_type> (), it_ () {} 5482 BOOST_UBLAS_INLINE iterator1(self_type & m,const subiterator_type & it)5483 iterator1 (self_type &m, const subiterator_type &it): 5484 container_reference<self_type> (m), it_ (it) {} 5485 5486 // Arithmetic 5487 BOOST_UBLAS_INLINE operator ++()5488 iterator1 &operator ++ () { 5489 it_ += M; 5490 return *this; 5491 } 5492 BOOST_UBLAS_INLINE operator --()5493 iterator1 &operator -- () { 5494 it_ -= M; 5495 return *this; 5496 } 5497 BOOST_UBLAS_INLINE operator +=(difference_type n)5498 iterator1 &operator += (difference_type n) { 5499 it_ += n * M; 5500 return *this; 5501 } 5502 BOOST_UBLAS_INLINE operator -=(difference_type n)5503 iterator1 &operator -= (difference_type n) { 5504 it_ -= n * M; 5505 return *this; 5506 } 5507 BOOST_UBLAS_INLINE operator -(const iterator1 & it) const5508 difference_type operator - (const iterator1 &it) const { 5509 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5510 return (it_ - it.it_) / M; 5511 } 5512 5513 // Dereference 5514 BOOST_UBLAS_INLINE operator *() const5515 reference operator * () const { 5516 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 5517 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 5518 return *it_; 5519 } 5520 BOOST_UBLAS_INLINE operator [](difference_type n) const5521 reference operator [] (difference_type n) const { 5522 return *(*this + n); 5523 } 5524 5525 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 5526 BOOST_UBLAS_INLINE 5527 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5528 typename self_type:: 5529 #endif begin() const5530 iterator2 begin () const { 5531 self_type &m = (*this) (); 5532 return m.find2 (1, index1 (), 0); 5533 } 5534 BOOST_UBLAS_INLINE 5535 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5536 typename self_type:: 5537 #endif end() const5538 iterator2 end () const { 5539 self_type &m = (*this) (); 5540 return m.find2 (1, index1 (), m.size2 ()); 5541 } 5542 BOOST_UBLAS_INLINE 5543 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5544 typename self_type:: 5545 #endif rbegin() const5546 reverse_iterator2 rbegin () const { 5547 return reverse_iterator2 (end ()); 5548 } 5549 BOOST_UBLAS_INLINE 5550 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5551 typename self_type:: 5552 #endif rend() const5553 reverse_iterator2 rend () const { 5554 return reverse_iterator2 (begin ()); 5555 } 5556 #endif 5557 5558 // Indices 5559 BOOST_UBLAS_INLINE index1() const5560 size_type index1 () const { 5561 const self_type &m = (*this) (); 5562 return (it_ - m.begin1 ().it_) / M; 5563 } 5564 BOOST_UBLAS_INLINE index2() const5565 size_type index2 () const { 5566 const self_type &m = (*this) (); 5567 return (it_ - m.begin1 ().it_) % M; 5568 } 5569 5570 // Assignment 5571 BOOST_UBLAS_INLINE operator =(const iterator1 & it)5572 iterator1 &operator = (const iterator1 &it) { 5573 container_reference<self_type>::assign (&it ()); 5574 it_ = it.it_; 5575 return *this; 5576 } 5577 5578 // Comparison 5579 BOOST_UBLAS_INLINE operator ==(const iterator1 & it) const5580 bool operator == (const iterator1 &it) const { 5581 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5582 return it_ == it.it_; 5583 } 5584 BOOST_UBLAS_INLINE operator <(const iterator1 & it) const5585 bool operator < (const iterator1 &it) const { 5586 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5587 return it_ < it.it_; 5588 } 5589 5590 private: 5591 subiterator_type it_; 5592 5593 friend class const_iterator1; 5594 }; 5595 #endif 5596 5597 BOOST_UBLAS_INLINE begin1()5598 iterator1 begin1 () { 5599 return find1 (0, 0, 0); 5600 } 5601 BOOST_UBLAS_INLINE end1()5602 iterator1 end1 () { 5603 return find1 (0, size1_, 0); 5604 } 5605 5606 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 5607 class const_iterator2: 5608 public container_const_reference<c_matrix>, 5609 public random_access_iterator_base<dense_random_access_iterator_tag, 5610 const_iterator2, value_type> { 5611 public: 5612 typedef typename c_matrix::difference_type difference_type; 5613 typedef typename c_matrix::value_type value_type; 5614 typedef typename c_matrix::const_reference reference; 5615 typedef typename c_matrix::const_reference pointer; 5616 5617 typedef const_iterator1 dual_iterator_type; 5618 typedef const_reverse_iterator1 dual_reverse_iterator_type; 5619 5620 // Construction and destruction 5621 BOOST_UBLAS_INLINE const_iterator2()5622 const_iterator2 (): 5623 container_const_reference<self_type> (), it_ () {} 5624 BOOST_UBLAS_INLINE const_iterator2(const self_type & m,const const_subiterator_type & it)5625 const_iterator2 (const self_type &m, const const_subiterator_type &it): 5626 container_const_reference<self_type> (m), it_ (it) {} 5627 BOOST_UBLAS_INLINE const_iterator2(const iterator2 & it)5628 const_iterator2 (const iterator2 &it): 5629 container_const_reference<self_type> (it ()), it_ (it.it_) {} 5630 5631 // Arithmetic 5632 BOOST_UBLAS_INLINE operator ++()5633 const_iterator2 &operator ++ () { 5634 ++ it_; 5635 return *this; 5636 } 5637 BOOST_UBLAS_INLINE operator --()5638 const_iterator2 &operator -- () { 5639 -- it_; 5640 return *this; 5641 } 5642 BOOST_UBLAS_INLINE operator +=(difference_type n)5643 const_iterator2 &operator += (difference_type n) { 5644 it_ += n; 5645 return *this; 5646 } 5647 BOOST_UBLAS_INLINE operator -=(difference_type n)5648 const_iterator2 &operator -= (difference_type n) { 5649 it_ -= n; 5650 return *this; 5651 } 5652 BOOST_UBLAS_INLINE operator -(const const_iterator2 & it) const5653 difference_type operator - (const const_iterator2 &it) const { 5654 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5655 return it_ - it.it_; 5656 } 5657 5658 // Dereference 5659 BOOST_UBLAS_INLINE operator *() const5660 const_reference operator * () const { 5661 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 5662 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 5663 return *it_; 5664 } 5665 BOOST_UBLAS_INLINE operator [](difference_type n) const5666 const_reference operator [] (difference_type n) const { 5667 return *(*this + n); 5668 } 5669 5670 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 5671 BOOST_UBLAS_INLINE 5672 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5673 typename self_type:: 5674 #endif begin() const5675 const_iterator1 begin () const { 5676 const self_type &m = (*this) (); 5677 return m.find1 (1, 0, index2 ()); 5678 } 5679 BOOST_UBLAS_INLINE 5680 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5681 typename self_type:: 5682 #endif cbegin() const5683 const_iterator1 cbegin () const { 5684 return begin (); 5685 } 5686 BOOST_UBLAS_INLINE 5687 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5688 typename self_type:: 5689 #endif end() const5690 const_iterator1 end () const { 5691 const self_type &m = (*this) (); 5692 return m.find1 (1, m.size1 (), index2 ()); 5693 } 5694 BOOST_UBLAS_INLINE 5695 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5696 typename self_type:: 5697 #endif cend() const5698 const_iterator1 cend () const { 5699 return end (); 5700 } 5701 BOOST_UBLAS_INLINE 5702 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5703 typename self_type:: 5704 #endif rbegin() const5705 const_reverse_iterator1 rbegin () const { 5706 return const_reverse_iterator1 (end ()); 5707 } 5708 BOOST_UBLAS_INLINE 5709 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5710 typename self_type:: 5711 #endif crbegin() const5712 const_reverse_iterator1 crbegin () const { 5713 return rbegin (); 5714 } 5715 BOOST_UBLAS_INLINE 5716 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5717 typename self_type:: 5718 #endif rend() const5719 const_reverse_iterator1 rend () const { 5720 return const_reverse_iterator1 (begin ()); 5721 } 5722 BOOST_UBLAS_INLINE 5723 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5724 typename self_type:: 5725 #endif crend() const5726 const_reverse_iterator1 crend () const { 5727 return rend (); 5728 } 5729 #endif 5730 5731 // Indices 5732 BOOST_UBLAS_INLINE index1() const5733 size_type index1 () const { 5734 const self_type &m = (*this) (); 5735 return (it_ - m.begin2 ().it_) / M; 5736 } 5737 BOOST_UBLAS_INLINE index2() const5738 size_type index2 () const { 5739 const self_type &m = (*this) (); 5740 return (it_ - m.begin2 ().it_) % M; 5741 } 5742 5743 // Assignment 5744 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)5745 const_iterator2 &operator = (const const_iterator2 &it) { 5746 container_const_reference<self_type>::assign (&it ()); 5747 it_ = it.it_; 5748 return *this; 5749 } 5750 5751 // Comparison 5752 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const5753 bool operator == (const const_iterator2 &it) const { 5754 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5755 return it_ == it.it_; 5756 } 5757 BOOST_UBLAS_INLINE operator <(const const_iterator2 & it) const5758 bool operator < (const const_iterator2 &it) const { 5759 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5760 return it_ < it.it_; 5761 } 5762 5763 private: 5764 const_subiterator_type it_; 5765 5766 friend class iterator2; 5767 }; 5768 #endif 5769 5770 BOOST_UBLAS_INLINE begin2() const5771 const_iterator2 begin2 () const { 5772 return find2 (0, 0, 0); 5773 } 5774 BOOST_UBLAS_INLINE cbegin2() const5775 const_iterator2 cbegin2 () const { 5776 return begin2 (); 5777 } 5778 BOOST_UBLAS_INLINE end2() const5779 const_iterator2 end2 () const { 5780 return find2 (0, 0, size2_); 5781 } 5782 BOOST_UBLAS_INLINE cend2() const5783 const_iterator2 cend2 () const { 5784 return end2 (); 5785 } 5786 5787 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 5788 class iterator2: 5789 public container_reference<c_matrix>, 5790 public random_access_iterator_base<dense_random_access_iterator_tag, 5791 iterator2, value_type> { 5792 public: 5793 typedef typename c_matrix::difference_type difference_type; 5794 typedef typename c_matrix::value_type value_type; 5795 typedef typename c_matrix::reference reference; 5796 typedef typename c_matrix::pointer pointer; 5797 5798 typedef iterator1 dual_iterator_type; 5799 typedef reverse_iterator1 dual_reverse_iterator_type; 5800 5801 // Construction and destruction 5802 BOOST_UBLAS_INLINE iterator2()5803 iterator2 (): 5804 container_reference<self_type> (), it_ () {} 5805 BOOST_UBLAS_INLINE iterator2(self_type & m,const subiterator_type & it)5806 iterator2 (self_type &m, const subiterator_type &it): 5807 container_reference<self_type> (m), it_ (it) {} 5808 5809 // Arithmetic 5810 BOOST_UBLAS_INLINE operator ++()5811 iterator2 &operator ++ () { 5812 ++ it_; 5813 return *this; 5814 } 5815 BOOST_UBLAS_INLINE operator --()5816 iterator2 &operator -- () { 5817 -- it_; 5818 return *this; 5819 } 5820 BOOST_UBLAS_INLINE operator +=(difference_type n)5821 iterator2 &operator += (difference_type n) { 5822 it_ += n; 5823 return *this; 5824 } 5825 BOOST_UBLAS_INLINE operator -=(difference_type n)5826 iterator2 &operator -= (difference_type n) { 5827 it_ -= n; 5828 return *this; 5829 } 5830 BOOST_UBLAS_INLINE operator -(const iterator2 & it) const5831 difference_type operator - (const iterator2 &it) const { 5832 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5833 return it_ - it.it_; 5834 } 5835 5836 // Dereference 5837 BOOST_UBLAS_INLINE operator *() const5838 reference operator * () const { 5839 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 5840 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 5841 return *it_; 5842 } 5843 BOOST_UBLAS_INLINE operator [](difference_type n) const5844 reference operator [] (difference_type n) const { 5845 return *(*this + n); 5846 } 5847 5848 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 5849 BOOST_UBLAS_INLINE 5850 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5851 typename self_type:: 5852 #endif begin() const5853 iterator1 begin () const { 5854 self_type &m = (*this) (); 5855 return m.find1 (1, 0, index2 ()); 5856 } 5857 BOOST_UBLAS_INLINE 5858 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5859 typename self_type:: 5860 #endif end() const5861 iterator1 end () const { 5862 self_type &m = (*this) (); 5863 return m.find1 (1, m.size1 (), index2 ()); 5864 } 5865 BOOST_UBLAS_INLINE 5866 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5867 typename self_type:: 5868 #endif rbegin() const5869 reverse_iterator1 rbegin () const { 5870 return reverse_iterator1 (end ()); 5871 } 5872 BOOST_UBLAS_INLINE 5873 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5874 typename self_type:: 5875 #endif rend() const5876 reverse_iterator1 rend () const { 5877 return reverse_iterator1 (begin ()); 5878 } 5879 #endif 5880 5881 // Indices 5882 BOOST_UBLAS_INLINE index1() const5883 size_type index1 () const { 5884 const self_type &m = (*this) (); 5885 return (it_ - m.begin2 ().it_) / M; 5886 } 5887 BOOST_UBLAS_INLINE index2() const5888 size_type index2 () const { 5889 const self_type &m = (*this) (); 5890 return (it_ - m.begin2 ().it_) % M; 5891 } 5892 5893 // Assignment 5894 BOOST_UBLAS_INLINE operator =(const iterator2 & it)5895 iterator2 &operator = (const iterator2 &it) { 5896 container_reference<self_type>::assign (&it ()); 5897 it_ = it.it_; 5898 return *this; 5899 } 5900 5901 // Comparison 5902 BOOST_UBLAS_INLINE operator ==(const iterator2 & it) const5903 bool operator == (const iterator2 &it) const { 5904 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5905 return it_ == it.it_; 5906 } 5907 BOOST_UBLAS_INLINE operator <(const iterator2 & it) const5908 bool operator < (const iterator2 &it) const { 5909 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 5910 return it_ < it.it_; 5911 } 5912 5913 private: 5914 subiterator_type it_; 5915 5916 friend class const_iterator2; 5917 }; 5918 #endif 5919 5920 BOOST_UBLAS_INLINE begin2()5921 iterator2 begin2 () { 5922 return find2 (0, 0, 0); 5923 } 5924 BOOST_UBLAS_INLINE end2()5925 iterator2 end2 () { 5926 return find2 (0, 0, size2_); 5927 } 5928 5929 // Reverse iterators 5930 5931 BOOST_UBLAS_INLINE rbegin1() const5932 const_reverse_iterator1 rbegin1 () const { 5933 return const_reverse_iterator1 (end1 ()); 5934 } 5935 BOOST_UBLAS_INLINE crbegin1() const5936 const_reverse_iterator1 crbegin1 () const { 5937 return rbegin1 (); 5938 } 5939 BOOST_UBLAS_INLINE rend1() const5940 const_reverse_iterator1 rend1 () const { 5941 return const_reverse_iterator1 (begin1 ()); 5942 } 5943 BOOST_UBLAS_INLINE crend1() const5944 const_reverse_iterator1 crend1 () const { 5945 return rend1 (); 5946 } 5947 5948 BOOST_UBLAS_INLINE rbegin1()5949 reverse_iterator1 rbegin1 () { 5950 return reverse_iterator1 (end1 ()); 5951 } 5952 BOOST_UBLAS_INLINE rend1()5953 reverse_iterator1 rend1 () { 5954 return reverse_iterator1 (begin1 ()); 5955 } 5956 5957 BOOST_UBLAS_INLINE rbegin2() const5958 const_reverse_iterator2 rbegin2 () const { 5959 return const_reverse_iterator2 (end2 ()); 5960 } 5961 BOOST_UBLAS_INLINE crbegin2() const5962 const_reverse_iterator2 crbegin2 () const { 5963 return rbegin2 (); 5964 } 5965 BOOST_UBLAS_INLINE rend2() const5966 const_reverse_iterator2 rend2 () const { 5967 return const_reverse_iterator2 (begin2 ()); 5968 } 5969 BOOST_UBLAS_INLINE crend2() const5970 const_reverse_iterator2 crend2 () const { 5971 return rend2 (); 5972 } 5973 5974 BOOST_UBLAS_INLINE rbegin2()5975 reverse_iterator2 rbegin2 () { 5976 return reverse_iterator2 (end2 ()); 5977 } 5978 BOOST_UBLAS_INLINE rend2()5979 reverse_iterator2 rend2 () { 5980 return reverse_iterator2 (begin2 ()); 5981 } 5982 5983 // Serialization 5984 template<class Archive> serialize(Archive & ar,const unsigned int)5985 void serialize(Archive & ar, const unsigned int /* file_version */){ 5986 5987 // we need to copy to a collection_size_type to get a portable 5988 // and efficient serialization 5989 serialization::collection_size_type s1 (size1_); 5990 serialization::collection_size_type s2 (size2_); 5991 5992 // serialize the sizes 5993 ar & serialization::make_nvp("size1",s1) 5994 & serialization::make_nvp("size2",s2); 5995 5996 // copy the values back if loading 5997 if (Archive::is_loading::value) { 5998 size1_ = s1; 5999 size2_ = s2; 6000 } 6001 // could probably use make_array( &(data[0][0]), N*M ) 6002 ar & serialization::make_array(data_, N); 6003 } 6004 6005 private: 6006 size_type size1_; 6007 size_type size2_; 6008 value_type data_ [N] [M]; 6009 }; 6010 6011 }}} 6012 6013 #endif 6014