1 // 2 // Copyright (c) 2000-2002 3 // Joerg Walter, Mathias Koch 4 // 5 // Distributed under the Boost Software License, Version 1.0. (See 6 // accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 // The authors gratefully acknowledge the support of 10 // GeNeSys mbH & Co. KG in producing this work. 11 // 12 13 #ifndef _BOOST_UBLAS_VECTOR_EXPRESSION_ 14 #define _BOOST_UBLAS_VECTOR_EXPRESSION_ 15 16 #include <boost/numeric/ublas/expression_types.hpp> 17 18 19 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish 20 // Iterators based on ideas of Jeremy Siek 21 // 22 // Classes that model the Vector Expression concept 23 24 namespace boost { namespace numeric { namespace ublas { 25 26 template<class E> 27 class vector_reference: 28 public vector_expression<vector_reference<E> > { 29 30 typedef vector_reference<E> self_type; 31 public: 32 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 33 using vector_expression<vector_reference<E> >::operator (); 34 #endif 35 typedef typename E::size_type size_type; 36 typedef typename E::difference_type difference_type; 37 typedef typename E::value_type value_type; 38 typedef typename E::const_reference const_reference; 39 typedef typename boost::mpl::if_<boost::is_const<E>, 40 typename E::const_reference, 41 typename E::reference>::type reference; 42 typedef E referred_type; 43 typedef const self_type const_closure_type; 44 typedef self_type closure_type; 45 typedef typename E::storage_category storage_category; 46 47 // Construction and destruction 48 BOOST_UBLAS_INLINE vector_reference(referred_type & e)49 explicit vector_reference (referred_type &e): 50 e_ (e) {} 51 52 // Accessors 53 BOOST_UBLAS_INLINE size() const54 size_type size () const { 55 return expression ().size (); 56 } 57 58 public: 59 // Expression accessors - const correct 60 BOOST_UBLAS_INLINE expression() const61 const referred_type &expression () const { 62 return e_; 63 } 64 BOOST_UBLAS_INLINE expression()65 referred_type &expression () { 66 return e_; 67 } 68 69 public: 70 // Element access 71 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER 72 BOOST_UBLAS_INLINE operator ()(size_type i) const73 const_reference operator () (size_type i) const { 74 return expression () (i); 75 } 76 BOOST_UBLAS_INLINE operator ()(size_type i)77 reference operator () (size_type i) { 78 return expression () (i); 79 } 80 81 BOOST_UBLAS_INLINE operator [](size_type i) const82 const_reference operator [] (size_type i) const { 83 return expression () [i]; 84 } 85 BOOST_UBLAS_INLINE operator [](size_type i)86 reference operator [] (size_type i) { 87 return expression () [i]; 88 } 89 #else 90 BOOST_UBLAS_INLINE 91 reference operator () (size_type i) const { 92 return expression () (i); 93 } 94 95 BOOST_UBLAS_INLINE 96 reference operator [] (size_type i) const { 97 return expression () [i]; 98 } 99 #endif 100 101 // Assignment 102 BOOST_UBLAS_INLINE operator =(const vector_reference & v)103 vector_reference &operator = (const vector_reference &v) { 104 expression ().operator = (v); 105 return *this; 106 } 107 template<class AE> 108 BOOST_UBLAS_INLINE operator =(const vector_expression<AE> & ae)109 vector_reference &operator = (const vector_expression<AE> &ae) { 110 expression ().operator = (ae); 111 return *this; 112 } 113 template<class AE> 114 BOOST_UBLAS_INLINE assign(const vector_expression<AE> & ae)115 vector_reference &assign (const vector_expression<AE> &ae) { 116 expression ().assign (ae); 117 return *this; 118 } 119 template<class AE> 120 BOOST_UBLAS_INLINE operator +=(const vector_expression<AE> & ae)121 vector_reference &operator += (const vector_expression<AE> &ae) { 122 expression ().operator += (ae); 123 return *this; 124 } 125 template<class AE> 126 BOOST_UBLAS_INLINE plus_assign(const vector_expression<AE> & ae)127 vector_reference &plus_assign (const vector_expression<AE> &ae) { 128 expression ().plus_assign (ae); 129 return *this; 130 } 131 template<class AE> 132 BOOST_UBLAS_INLINE operator -=(const vector_expression<AE> & ae)133 vector_reference &operator -= (const vector_expression<AE> &ae) { 134 expression ().operator -= (ae); 135 return *this; 136 } 137 template<class AE> 138 BOOST_UBLAS_INLINE minus_assign(const vector_expression<AE> & ae)139 vector_reference &minus_assign (const vector_expression<AE> &ae) { 140 expression ().minus_assign (ae); 141 return *this; 142 } 143 template<class AT> 144 BOOST_UBLAS_INLINE operator *=(const AT & at)145 vector_reference &operator *= (const AT &at) { 146 expression ().operator *= (at); 147 return *this; 148 } 149 template<class AT> 150 BOOST_UBLAS_INLINE operator /=(const AT & at)151 vector_reference &operator /= (const AT &at) { 152 expression ().operator /= (at); 153 return *this; 154 } 155 156 // Swapping 157 BOOST_UBLAS_INLINE swap(vector_reference & v)158 void swap (vector_reference &v) { 159 expression ().swap (v.expression ()); 160 } 161 162 // Closure comparison 163 BOOST_UBLAS_INLINE same_closure(const vector_reference & vr) const164 bool same_closure (const vector_reference &vr) const { 165 return &(*this).e_ == &vr.e_; 166 } 167 168 // Iterator types 169 typedef typename E::const_iterator const_iterator; 170 typedef typename boost::mpl::if_<boost::is_const<E>, 171 typename E::const_iterator, 172 typename E::iterator>::type iterator; 173 174 // Element lookup 175 BOOST_UBLAS_INLINE find(size_type i) const176 const_iterator find (size_type i) const { 177 return expression ().find (i); 178 } 179 BOOST_UBLAS_INLINE find(size_type i)180 iterator find (size_type i) { 181 return expression ().find (i); 182 } 183 184 // Iterator is the iterator of the referenced expression. 185 186 BOOST_UBLAS_INLINE begin() const187 const_iterator begin () const { 188 return expression ().begin (); 189 } 190 BOOST_UBLAS_INLINE cbegin() const191 const_iterator cbegin () const { 192 return begin (); 193 } 194 BOOST_UBLAS_INLINE end() const195 const_iterator end () const { 196 return expression ().end (); 197 } 198 BOOST_UBLAS_INLINE cend() const199 const_iterator cend () const { 200 return end (); 201 } 202 203 BOOST_UBLAS_INLINE begin()204 iterator begin () { 205 return expression ().begin (); 206 } 207 BOOST_UBLAS_INLINE end()208 iterator end () { 209 return expression ().end (); 210 } 211 212 // Reverse iterator 213 typedef reverse_iterator_base<const_iterator> const_reverse_iterator; 214 typedef reverse_iterator_base<iterator> reverse_iterator; 215 216 BOOST_UBLAS_INLINE rbegin() const217 const_reverse_iterator rbegin () const { 218 return const_reverse_iterator (end ()); 219 } 220 BOOST_UBLAS_INLINE crbegin() const221 const_reverse_iterator crbegin () const { 222 return rbegin (); 223 } 224 BOOST_UBLAS_INLINE rend() const225 const_reverse_iterator rend () const { 226 return const_reverse_iterator (begin ()); 227 } 228 BOOST_UBLAS_INLINE crend() const229 const_reverse_iterator crend () const { 230 return rend (); 231 } 232 233 BOOST_UBLAS_INLINE rbegin()234 reverse_iterator rbegin () { 235 return reverse_iterator (end ()); 236 } 237 BOOST_UBLAS_INLINE rend()238 reverse_iterator rend () { 239 return reverse_iterator (begin ()); 240 } 241 242 private: 243 referred_type &e_; 244 }; 245 246 247 template<class E, class F> 248 class vector_unary: 249 public vector_expression<vector_unary<E, F> > { 250 251 typedef F functor_type; 252 typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >, 253 E, 254 const E>::type expression_type; 255 typedef typename boost::mpl::if_<boost::is_const<expression_type>, 256 typename E::const_closure_type, 257 typename E::closure_type>::type expression_closure_type; 258 typedef vector_unary<E, F> self_type; 259 public: 260 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 261 using vector_expression<vector_unary<E, F> >::operator (); 262 #endif 263 typedef typename E::size_type size_type; 264 typedef typename E::difference_type difference_type; 265 typedef typename F::result_type value_type; 266 typedef value_type const_reference; 267 typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >, 268 typename E::reference, 269 value_type>::type reference; 270 typedef const self_type const_closure_type; 271 typedef self_type closure_type; 272 typedef unknown_storage_tag storage_category; 273 274 // Construction and destruction 275 BOOST_UBLAS_INLINE 276 // May be used as mutable expression. vector_unary(expression_type & e)277 explicit vector_unary (expression_type &e): 278 e_ (e) {} 279 280 // Accessors 281 BOOST_UBLAS_INLINE size() const282 size_type size () const { 283 return e_.size (); 284 } 285 286 public: 287 // Expression accessors 288 BOOST_UBLAS_INLINE expression() const289 const expression_closure_type &expression () const { 290 return e_; 291 } 292 293 public: 294 // Element access 295 BOOST_UBLAS_INLINE operator ()(size_type i) const296 const_reference operator () (size_type i) const { 297 return functor_type::apply (e_ (i)); 298 } 299 BOOST_UBLAS_INLINE operator ()(size_type i)300 reference operator () (size_type i) { 301 BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value)); 302 return e_ (i); 303 } 304 305 BOOST_UBLAS_INLINE operator [](size_type i) const306 const_reference operator [] (size_type i) const { 307 return functor_type::apply (e_ [i]); 308 } 309 BOOST_UBLAS_INLINE operator [](size_type i)310 reference operator [] (size_type i) { 311 BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value)); 312 return e_ [i]; 313 } 314 315 // Closure comparison 316 BOOST_UBLAS_INLINE same_closure(const vector_unary & vu) const317 bool same_closure (const vector_unary &vu) const { 318 return (*this).expression ().same_closure (vu.expression ()); 319 } 320 321 // Iterator types 322 private: 323 typedef typename E::const_iterator const_subiterator_type; 324 typedef const value_type *const_pointer; 325 326 public: 327 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 328 typedef indexed_const_iterator<const_closure_type, typename const_subiterator_type::iterator_category> const_iterator; 329 typedef const_iterator iterator; 330 #else 331 class const_iterator; 332 typedef const_iterator iterator; 333 #endif 334 335 // Element lookup 336 BOOST_UBLAS_INLINE find(size_type i) const337 const_iterator find (size_type i) const { 338 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 339 const_subiterator_type it (e_.find (i)); 340 return const_iterator (*this, it.index ()); 341 #else 342 return const_iterator (*this, e_.find (i)); 343 #endif 344 } 345 346 // Iterator enhances the iterator of the referenced expression 347 // with the unary functor. 348 349 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 350 class const_iterator: 351 public container_const_reference<vector_unary>, 352 public iterator_base_traits<typename E::const_iterator::iterator_category>::template 353 iterator_base<const_iterator, value_type>::type { 354 public: 355 typedef typename E::const_iterator::iterator_category iterator_category; 356 typedef typename vector_unary::difference_type difference_type; 357 typedef typename vector_unary::value_type value_type; 358 typedef typename vector_unary::const_reference reference; 359 typedef typename vector_unary::const_pointer pointer; 360 361 // Construction and destruction 362 BOOST_UBLAS_INLINE const_iterator()363 const_iterator (): 364 container_const_reference<self_type> (), it_ () {} 365 BOOST_UBLAS_INLINE const_iterator(const self_type & vu,const const_subiterator_type & it)366 const_iterator (const self_type &vu, const const_subiterator_type &it): 367 container_const_reference<self_type> (vu), it_ (it) {} 368 369 // Arithmetic 370 BOOST_UBLAS_INLINE operator ++()371 const_iterator &operator ++ () { 372 ++ it_; 373 return *this; 374 } 375 BOOST_UBLAS_INLINE operator --()376 const_iterator &operator -- () { 377 -- it_; 378 return *this; 379 } 380 BOOST_UBLAS_INLINE operator +=(difference_type n)381 const_iterator &operator += (difference_type n) { 382 it_ += n; 383 return *this; 384 } 385 BOOST_UBLAS_INLINE operator -=(difference_type n)386 const_iterator &operator -= (difference_type n) { 387 it_ -= n; 388 return *this; 389 } 390 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const391 difference_type operator - (const const_iterator &it) const { 392 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 393 return it_ - it.it_; 394 } 395 396 // Dereference 397 BOOST_UBLAS_INLINE operator *() const398 const_reference operator * () const { 399 return functor_type::apply (*it_); 400 } 401 BOOST_UBLAS_INLINE operator [](difference_type n) const402 const_reference operator [] (difference_type n) const { 403 return *(*this + n); 404 } 405 406 // Index 407 BOOST_UBLAS_INLINE index() const408 size_type index () const { 409 return it_.index (); 410 } 411 412 // Assignment 413 BOOST_UBLAS_INLINE operator =(const const_iterator & it)414 const_iterator &operator = (const const_iterator &it) { 415 container_const_reference<self_type>::assign (&it ()); 416 it_ = it.it_; 417 return *this; 418 } 419 420 // Comparison 421 BOOST_UBLAS_INLINE operator ==(const const_iterator & it) const422 bool operator == (const const_iterator &it) const { 423 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 424 return it_ == it.it_; 425 } 426 BOOST_UBLAS_INLINE operator <(const const_iterator & it) const427 bool operator < (const const_iterator &it) const { 428 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 429 return it_ < it.it_; 430 } 431 432 private: 433 const_subiterator_type it_; 434 }; 435 #endif 436 437 BOOST_UBLAS_INLINE begin() const438 const_iterator begin () const { 439 return find (0); 440 } 441 BOOST_UBLAS_INLINE cbegin() const442 const_iterator cbegin () const { 443 return begin (); 444 } 445 BOOST_UBLAS_INLINE end() const446 const_iterator end () const { 447 return find (size ()); 448 } 449 BOOST_UBLAS_INLINE cend() const450 const_iterator cend () const { 451 return end (); 452 } 453 454 // Reverse iterator 455 typedef reverse_iterator_base<const_iterator> const_reverse_iterator; 456 457 BOOST_UBLAS_INLINE rbegin() const458 const_reverse_iterator rbegin () const { 459 return const_reverse_iterator (end ()); 460 } 461 BOOST_UBLAS_INLINE crbegin() const462 const_reverse_iterator crbegin () const { 463 return rbegin (); 464 } 465 BOOST_UBLAS_INLINE rend() const466 const_reverse_iterator rend () const { 467 return const_reverse_iterator (begin ()); 468 } 469 BOOST_UBLAS_INLINE crend() const470 const_reverse_iterator crend () const { 471 return rend (); 472 } 473 474 private: 475 expression_closure_type e_; 476 }; 477 478 template<class E, class F> 479 struct vector_unary_traits { 480 typedef vector_unary<E, F> expression_type; 481 //FIXME 482 // #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG 483 typedef expression_type result_type; 484 // #else 485 // typedef typename E::vector_temporary_type result_type; 486 // #endif 487 }; 488 489 // (- v) [i] = - v [i] 490 template<class E> 491 BOOST_UBLAS_INLINE 492 typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::result_type operator -(const vector_expression<E> & e)493 operator - (const vector_expression<E> &e) { 494 typedef typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type; 495 return expression_type (e ()); 496 } 497 498 // (conj v) [i] = conj (v [i]) 499 template<class E> 500 BOOST_UBLAS_INLINE 501 typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type conj(const vector_expression<E> & e)502 conj (const vector_expression<E> &e) { 503 typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type; 504 return expression_type (e ()); 505 } 506 507 // (real v) [i] = real (v [i]) 508 template<class E> 509 BOOST_UBLAS_INLINE 510 typename vector_unary_traits<E, scalar_real<typename E::value_type> >::result_type real(const vector_expression<E> & e)511 real (const vector_expression<E> &e) { 512 typedef typename vector_unary_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type; 513 return expression_type (e ()); 514 } 515 516 // (imag v) [i] = imag (v [i]) 517 template<class E> 518 BOOST_UBLAS_INLINE 519 typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::result_type imag(const vector_expression<E> & e)520 imag (const vector_expression<E> &e) { 521 typedef typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type; 522 return expression_type (e ()); 523 } 524 525 // (trans v) [i] = v [i] 526 template<class E> 527 BOOST_UBLAS_INLINE 528 typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::result_type trans(const vector_expression<E> & e)529 trans (const vector_expression<E> &e) { 530 typedef typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type; 531 return expression_type (e ()); 532 } 533 template<class E> 534 BOOST_UBLAS_INLINE 535 typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::result_type trans(vector_expression<E> & e)536 trans (vector_expression<E> &e) { 537 typedef typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type; 538 return expression_type (e ()); 539 } 540 541 // (herm v) [i] = conj (v [i]) 542 template<class E> 543 BOOST_UBLAS_INLINE 544 typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type herm(const vector_expression<E> & e)545 herm (const vector_expression<E> &e) { 546 typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type; 547 return expression_type (e ()); 548 } 549 550 template<class E1, class E2, class F> 551 class vector_binary: 552 public vector_expression<vector_binary<E1, E2, F> > { 553 554 typedef E1 expression1_type; 555 typedef E2 expression2_type; 556 typedef F functor_type; 557 typedef typename E1::const_closure_type expression1_closure_type; 558 typedef typename E2::const_closure_type expression2_closure_type; 559 typedef vector_binary<E1, E2, F> self_type; 560 public: 561 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 562 using vector_expression<vector_binary<E1, E2, F> >::operator (); 563 #endif 564 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type; 565 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type; 566 typedef typename F::result_type value_type; 567 typedef value_type const_reference; 568 typedef const_reference reference; 569 typedef const self_type const_closure_type; 570 typedef const_closure_type closure_type; 571 typedef unknown_storage_tag storage_category; 572 573 // Construction and destruction 574 BOOST_UBLAS_INLINE vector_binary(const expression1_type & e1,const expression2_type & e2)575 vector_binary (const expression1_type &e1, const expression2_type &e2): 576 e1_ (e1), e2_ (e2) {} 577 578 // Accessors 579 BOOST_UBLAS_INLINE size() const580 size_type size () const { 581 return BOOST_UBLAS_SAME (e1_.size (), e2_.size ()); 582 } 583 584 private: 585 // Accessors 586 BOOST_UBLAS_INLINE expression1() const587 const expression1_closure_type &expression1 () const { 588 return e1_; 589 } 590 BOOST_UBLAS_INLINE expression2() const591 const expression2_closure_type &expression2 () const { 592 return e2_; 593 } 594 595 public: 596 // Element access 597 BOOST_UBLAS_INLINE operator ()(size_type i) const598 const_reference operator () (size_type i) const { 599 return functor_type::apply (e1_ (i), e2_ (i)); 600 } 601 602 BOOST_UBLAS_INLINE operator [](size_type i) const603 const_reference operator [] (size_type i) const { 604 return functor_type::apply (e1_ [i], e2_ [i]); 605 } 606 607 // Closure comparison 608 BOOST_UBLAS_INLINE same_closure(const vector_binary & vb) const609 bool same_closure (const vector_binary &vb) const { 610 return (*this).expression1 ().same_closure (vb.expression1 ()) && 611 (*this).expression2 ().same_closure (vb.expression2 ()); 612 } 613 614 // Iterator types 615 private: 616 typedef typename E1::const_iterator const_subiterator1_type; 617 typedef typename E2::const_iterator const_subiterator2_type; 618 typedef const value_type *const_pointer; 619 620 public: 621 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 622 typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category, 623 typename const_subiterator2_type::iterator_category>::iterator_category iterator_category; 624 typedef indexed_const_iterator<const_closure_type, iterator_category> const_iterator; 625 typedef const_iterator iterator; 626 #else 627 class const_iterator; 628 typedef const_iterator iterator; 629 #endif 630 631 // Element lookup 632 BOOST_UBLAS_INLINE find(size_type i) const633 const_iterator find (size_type i) const { 634 const_subiterator1_type it1 (e1_.find (i)); 635 const_subiterator1_type it1_end (e1_.find (size ())); 636 const_subiterator2_type it2 (e2_.find (i)); 637 const_subiterator2_type it2_end (e2_.find (size ())); 638 i = (std::min) (it1 != it1_end ? it1.index () : size (), 639 it2 != it2_end ? it2.index () : size ()); 640 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 641 return const_iterator (*this, i); 642 #else 643 return const_iterator (*this, i, it1, it1_end, it2, it2_end); 644 #endif 645 } 646 647 // Iterator merges the iterators of the referenced expressions and 648 // enhances them with the binary functor. 649 650 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 651 class const_iterator: 652 public container_const_reference<vector_binary>, 653 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category, 654 typename E2::const_iterator::iterator_category>::iterator_category>::template 655 iterator_base<const_iterator, value_type>::type { 656 public: 657 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category, 658 typename E2::const_iterator::iterator_category>::iterator_category iterator_category; 659 typedef typename vector_binary::difference_type difference_type; 660 typedef typename vector_binary::value_type value_type; 661 typedef typename vector_binary::const_reference reference; 662 typedef typename vector_binary::const_pointer pointer; 663 664 // Construction and destruction 665 BOOST_UBLAS_INLINE const_iterator()666 const_iterator (): 667 container_const_reference<self_type> (), i_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {} 668 BOOST_UBLAS_INLINE const_iterator(const self_type & vb,size_type i,const const_subiterator1_type & it1,const const_subiterator1_type & it1_end,const const_subiterator2_type & it2,const const_subiterator2_type & it2_end)669 const_iterator (const self_type &vb, size_type i, 670 const const_subiterator1_type &it1, const const_subiterator1_type &it1_end, 671 const const_subiterator2_type &it2, const const_subiterator2_type &it2_end): 672 container_const_reference<self_type> (vb), i_ (i), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {} 673 674 private: 675 // Dense specializations 676 BOOST_UBLAS_INLINE increment(dense_random_access_iterator_tag)677 void increment (dense_random_access_iterator_tag) { 678 ++ i_; ++ it1_; ++ it2_; 679 } 680 BOOST_UBLAS_INLINE decrement(dense_random_access_iterator_tag)681 void decrement (dense_random_access_iterator_tag) { 682 -- i_; -- it1_; -- it2_; 683 } 684 BOOST_UBLAS_INLINE increment(dense_random_access_iterator_tag,difference_type n)685 void increment (dense_random_access_iterator_tag, difference_type n) { 686 i_ += n; it1_ += n; it2_ += n; 687 } 688 BOOST_UBLAS_INLINE decrement(dense_random_access_iterator_tag,difference_type n)689 void decrement (dense_random_access_iterator_tag, difference_type n) { 690 i_ -= n; it1_ -= n; it2_ -= n; 691 } 692 BOOST_UBLAS_INLINE dereference(dense_random_access_iterator_tag) const693 value_type dereference (dense_random_access_iterator_tag) const { 694 return functor_type::apply (*it1_, *it2_); 695 } 696 697 // Packed specializations 698 BOOST_UBLAS_INLINE increment(packed_random_access_iterator_tag)699 void increment (packed_random_access_iterator_tag) { 700 if (it1_ != it1_end_) 701 if (it1_.index () <= i_) 702 ++ it1_; 703 if (it2_ != it2_end_) 704 if (it2_.index () <= i_) 705 ++ it2_; 706 ++ i_; 707 } 708 BOOST_UBLAS_INLINE decrement(packed_random_access_iterator_tag)709 void decrement (packed_random_access_iterator_tag) { 710 if (it1_ != it1_end_) 711 if (i_ <= it1_.index ()) 712 -- it1_; 713 if (it2_ != it2_end_) 714 if (i_ <= it2_.index ()) 715 -- it2_; 716 -- i_; 717 } 718 BOOST_UBLAS_INLINE increment(packed_random_access_iterator_tag,difference_type n)719 void increment (packed_random_access_iterator_tag, difference_type n) { 720 while (n > 0) { 721 increment (packed_random_access_iterator_tag ()); 722 --n; 723 } 724 while (n < 0) { 725 decrement (packed_random_access_iterator_tag ()); 726 ++n; 727 } 728 } 729 BOOST_UBLAS_INLINE decrement(packed_random_access_iterator_tag,difference_type n)730 void decrement (packed_random_access_iterator_tag, difference_type n) { 731 while (n > 0) { 732 decrement (packed_random_access_iterator_tag ()); 733 --n; 734 } 735 while (n < 0) { 736 increment (packed_random_access_iterator_tag ()); 737 ++n; 738 } 739 } 740 BOOST_UBLAS_INLINE dereference(packed_random_access_iterator_tag) const741 value_type dereference (packed_random_access_iterator_tag) const { 742 typename E1::value_type t1 = typename E1::value_type/*zero*/(); 743 if (it1_ != it1_end_) 744 if (it1_.index () == i_) 745 t1 = *it1_; 746 typename E2::value_type t2 = typename E2::value_type/*zero*/(); 747 if (it2_ != it2_end_) 748 if (it2_.index () == i_) 749 t2 = *it2_; 750 return functor_type::apply (t1, t2); 751 } 752 753 // Sparse specializations 754 BOOST_UBLAS_INLINE increment(sparse_bidirectional_iterator_tag)755 void increment (sparse_bidirectional_iterator_tag) { 756 size_type index1 = (*this) ().size (); 757 if (it1_ != it1_end_) { 758 if (it1_.index () <= i_) 759 ++ it1_; 760 if (it1_ != it1_end_) 761 index1 = it1_.index (); 762 } 763 size_type index2 = (*this) ().size (); 764 if (it2_ != it2_end_) { 765 if (it2_.index () <= i_) 766 ++ it2_; 767 if (it2_ != it2_end_) 768 index2 = it2_.index (); 769 } 770 i_ = (std::min) (index1, index2); 771 } 772 BOOST_UBLAS_INLINE decrement(sparse_bidirectional_iterator_tag)773 void decrement (sparse_bidirectional_iterator_tag) { 774 size_type index1 = (*this) ().size (); 775 if (it1_ != it1_end_) { 776 if (i_ <= it1_.index ()) 777 -- it1_; 778 if (it1_ != it1_end_) 779 index1 = it1_.index (); 780 } 781 size_type index2 = (*this) ().size (); 782 if (it2_ != it2_end_) { 783 if (i_ <= it2_.index ()) 784 -- it2_; 785 if (it2_ != it2_end_) 786 index2 = it2_.index (); 787 } 788 i_ = (std::max) (index1, index2); 789 } 790 BOOST_UBLAS_INLINE increment(sparse_bidirectional_iterator_tag,difference_type n)791 void increment (sparse_bidirectional_iterator_tag, difference_type n) { 792 while (n > 0) { 793 increment (sparse_bidirectional_iterator_tag ()); 794 --n; 795 } 796 while (n < 0) { 797 decrement (sparse_bidirectional_iterator_tag ()); 798 ++n; 799 } 800 } 801 BOOST_UBLAS_INLINE decrement(sparse_bidirectional_iterator_tag,difference_type n)802 void decrement (sparse_bidirectional_iterator_tag, difference_type n) { 803 while (n > 0) { 804 decrement (sparse_bidirectional_iterator_tag ()); 805 --n; 806 } 807 while (n < 0) { 808 increment (sparse_bidirectional_iterator_tag ()); 809 ++n; 810 } 811 } 812 BOOST_UBLAS_INLINE dereference(sparse_bidirectional_iterator_tag) const813 value_type dereference (sparse_bidirectional_iterator_tag) const { 814 typename E1::value_type t1 = typename E1::value_type/*zero*/(); 815 if (it1_ != it1_end_) 816 if (it1_.index () == i_) 817 t1 = *it1_; 818 typename E2::value_type t2 = typename E2::value_type/*zero*/(); 819 if (it2_ != it2_end_) 820 if (it2_.index () == i_) 821 t2 = *it2_; 822 return static_cast<value_type>(functor_type::apply (t1, t2)); 823 } 824 825 public: 826 // Arithmetic 827 BOOST_UBLAS_INLINE operator ++()828 const_iterator &operator ++ () { 829 increment (iterator_category ()); 830 return *this; 831 } 832 BOOST_UBLAS_INLINE operator --()833 const_iterator &operator -- () { 834 decrement (iterator_category ()); 835 return *this; 836 } 837 BOOST_UBLAS_INLINE operator +=(difference_type n)838 const_iterator &operator += (difference_type n) { 839 increment (iterator_category (), n); 840 return *this; 841 } 842 BOOST_UBLAS_INLINE operator -=(difference_type n)843 const_iterator &operator -= (difference_type n) { 844 decrement (iterator_category (), n); 845 return *this; 846 } 847 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const848 difference_type operator - (const const_iterator &it) const { 849 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 850 return index () - it.index (); 851 } 852 853 // Dereference 854 BOOST_UBLAS_INLINE operator *() const855 const_reference operator * () const { 856 return dereference (iterator_category ()); 857 } 858 BOOST_UBLAS_INLINE operator [](difference_type n) const859 const_reference operator [] (difference_type n) const { 860 return *(*this + n); 861 } 862 863 // Index 864 BOOST_UBLAS_INLINE index() const865 size_type index () const { 866 return i_; 867 } 868 869 // Assignment 870 BOOST_UBLAS_INLINE operator =(const const_iterator & it)871 const_iterator &operator = (const const_iterator &it) { 872 container_const_reference<self_type>::assign (&it ()); 873 i_ = it.i_; 874 it1_ = it.it1_; 875 it1_end_ = it.it1_end_; 876 it2_ = it.it2_; 877 it2_end_ = it.it2_end_; 878 return *this; 879 } 880 881 // Comparison 882 BOOST_UBLAS_INLINE operator ==(const const_iterator & it) const883 bool operator == (const const_iterator &it) const { 884 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 885 return index () == it.index (); 886 } 887 BOOST_UBLAS_INLINE operator <(const const_iterator & it) const888 bool operator < (const const_iterator &it) const { 889 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 890 return index () < it.index (); 891 } 892 893 private: 894 size_type i_; 895 const_subiterator1_type it1_; 896 const_subiterator1_type it1_end_; 897 const_subiterator2_type it2_; 898 const_subiterator2_type it2_end_; 899 }; 900 #endif 901 902 BOOST_UBLAS_INLINE begin() const903 const_iterator begin () const { 904 return find (0); 905 } 906 BOOST_UBLAS_INLINE cbegin() const907 const_iterator cbegin () const { 908 return begin (); 909 } 910 BOOST_UBLAS_INLINE end() const911 const_iterator end () const { 912 return find (size ()); 913 } 914 BOOST_UBLAS_INLINE cend() const915 const_iterator cend () const { 916 return end (); 917 } 918 919 // Reverse iterator 920 typedef reverse_iterator_base<const_iterator> const_reverse_iterator; 921 922 BOOST_UBLAS_INLINE rbegin() const923 const_reverse_iterator rbegin () const { 924 return const_reverse_iterator (end ()); 925 } 926 BOOST_UBLAS_INLINE crbegin() const927 const_reverse_iterator crbegin () const { 928 return rbegin (); 929 } 930 BOOST_UBLAS_INLINE rend() const931 const_reverse_iterator rend () const { 932 return const_reverse_iterator (begin ()); 933 } 934 BOOST_UBLAS_INLINE crend() const935 const_reverse_iterator crend () const { 936 return rend (); 937 } 938 939 private: 940 expression1_closure_type e1_; 941 expression2_closure_type e2_; 942 }; 943 944 template<class E1, class E2, class F> 945 struct vector_binary_traits { 946 typedef vector_binary<E1, E2, F> expression_type; 947 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG 948 typedef expression_type result_type; 949 #else 950 typedef typename E1::vector_temporary_type result_type; 951 #endif 952 }; 953 954 // (v1 + v2) [i] = v1 [i] + v2 [i] 955 template<class E1, class E2> 956 BOOST_UBLAS_INLINE 957 typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type, 958 typename E2::value_type> >::result_type operator +(const vector_expression<E1> & e1,const vector_expression<E2> & e2)959 operator + (const vector_expression<E1> &e1, 960 const vector_expression<E2> &e2) { 961 typedef typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type, 962 typename E2::value_type> >::expression_type expression_type; 963 return expression_type (e1 (), e2 ()); 964 } 965 966 // (v1 - v2) [i] = v1 [i] - v2 [i] 967 template<class E1, class E2> 968 BOOST_UBLAS_INLINE 969 typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type, 970 typename E2::value_type> >::result_type operator -(const vector_expression<E1> & e1,const vector_expression<E2> & e2)971 operator - (const vector_expression<E1> &e1, 972 const vector_expression<E2> &e2) { 973 typedef typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type, 974 typename E2::value_type> >::expression_type expression_type; 975 return expression_type (e1 (), e2 ()); 976 } 977 978 // (v1 * v2) [i] = v1 [i] * v2 [i] 979 template<class E1, class E2> 980 BOOST_UBLAS_INLINE 981 typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, 982 typename E2::value_type> >::result_type element_prod(const vector_expression<E1> & e1,const vector_expression<E2> & e2)983 element_prod (const vector_expression<E1> &e1, 984 const vector_expression<E2> &e2) { 985 typedef typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, 986 typename E2::value_type> >::expression_type expression_type; 987 return expression_type (e1 (), e2 ()); 988 } 989 990 // (v1 / v2) [i] = v1 [i] / v2 [i] 991 template<class E1, class E2> 992 BOOST_UBLAS_INLINE 993 typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type, 994 typename E2::value_type> >::result_type element_div(const vector_expression<E1> & e1,const vector_expression<E2> & e2)995 element_div (const vector_expression<E1> &e1, 996 const vector_expression<E2> &e2) { 997 typedef typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type, 998 typename E2::value_type> >::expression_type expression_type; 999 return expression_type (e1 (), e2 ()); 1000 } 1001 1002 1003 template<class E1, class E2, class F> 1004 class vector_binary_scalar1: 1005 public vector_expression<vector_binary_scalar1<E1, E2, F> > { 1006 1007 typedef F functor_type; 1008 typedef E1 expression1_type; 1009 typedef E2 expression2_type; 1010 public: 1011 typedef const E1& expression1_closure_type; 1012 typedef typename E2::const_closure_type expression2_closure_type; 1013 private: 1014 typedef vector_binary_scalar1<E1, E2, F> self_type; 1015 public: 1016 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 1017 using vector_expression<vector_binary_scalar1<E1, E2, F> >::operator (); 1018 #endif 1019 typedef typename E2::size_type size_type; 1020 typedef typename E2::difference_type difference_type; 1021 typedef typename F::result_type value_type; 1022 typedef value_type const_reference; 1023 typedef const_reference reference; 1024 typedef const self_type const_closure_type; 1025 typedef const_closure_type closure_type; 1026 typedef unknown_storage_tag storage_category; 1027 1028 // Construction and destruction 1029 BOOST_UBLAS_INLINE vector_binary_scalar1(const expression1_type & e1,const expression2_type & e2)1030 vector_binary_scalar1 (const expression1_type &e1, const expression2_type &e2): 1031 e1_ (e1), e2_ (e2) {} 1032 1033 // Accessors 1034 BOOST_UBLAS_INLINE size() const1035 size_type size () const { 1036 return e2_.size (); 1037 } 1038 1039 public: 1040 // Element access 1041 BOOST_UBLAS_INLINE operator ()(size_type i) const1042 const_reference operator () (size_type i) const { 1043 return functor_type::apply (e1_, e2_ (i)); 1044 } 1045 1046 BOOST_UBLAS_INLINE operator [](size_type i) const1047 const_reference operator [] (size_type i) const { 1048 return functor_type::apply (e1_, e2_ [i]); 1049 } 1050 1051 // Closure comparison 1052 BOOST_UBLAS_INLINE same_closure(const vector_binary_scalar1 & vbs1) const1053 bool same_closure (const vector_binary_scalar1 &vbs1) const { 1054 return &e1_ == &(vbs1.e1_) && 1055 (*this).e2_.same_closure (vbs1.e2_); 1056 } 1057 1058 // Iterator types 1059 private: 1060 typedef expression1_type const_subiterator1_type; 1061 typedef typename expression2_type::const_iterator const_subiterator2_type; 1062 typedef const value_type *const_pointer; 1063 1064 public: 1065 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1066 typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator; 1067 typedef const_iterator iterator; 1068 #else 1069 class const_iterator; 1070 typedef const_iterator iterator; 1071 #endif 1072 1073 // Element lookup 1074 BOOST_UBLAS_INLINE find(size_type i) const1075 const_iterator find (size_type i) const { 1076 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1077 const_subiterator2_type it (e2_.find (i)); 1078 return const_iterator (*this, it.index ()); 1079 #else 1080 return const_iterator (*this, const_subiterator1_type (e1_), e2_.find (i)); 1081 #endif 1082 } 1083 1084 // Iterator enhances the iterator of the referenced vector expression 1085 // with the binary functor. 1086 1087 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 1088 class const_iterator: 1089 public container_const_reference<vector_binary_scalar1>, 1090 public iterator_base_traits<typename E2::const_iterator::iterator_category>::template 1091 iterator_base<const_iterator, value_type>::type { 1092 public: 1093 typedef typename E2::const_iterator::iterator_category iterator_category; 1094 typedef typename vector_binary_scalar1::difference_type difference_type; 1095 typedef typename vector_binary_scalar1::value_type value_type; 1096 typedef typename vector_binary_scalar1::const_reference reference; 1097 typedef typename vector_binary_scalar1::const_pointer pointer; 1098 1099 // Construction and destruction 1100 BOOST_UBLAS_INLINE const_iterator()1101 const_iterator (): 1102 container_const_reference<self_type> (), it1_ (), it2_ () {} 1103 BOOST_UBLAS_INLINE const_iterator(const self_type & vbs,const const_subiterator1_type & it1,const const_subiterator2_type & it2)1104 const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2): 1105 container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {} 1106 1107 // Arithmetic 1108 BOOST_UBLAS_INLINE operator ++()1109 const_iterator &operator ++ () { 1110 ++ it2_; 1111 return *this; 1112 } 1113 BOOST_UBLAS_INLINE operator --()1114 const_iterator &operator -- () { 1115 -- it2_; 1116 return *this; 1117 } 1118 BOOST_UBLAS_INLINE operator +=(difference_type n)1119 const_iterator &operator += (difference_type n) { 1120 it2_ += n; 1121 return *this; 1122 } 1123 BOOST_UBLAS_INLINE operator -=(difference_type n)1124 const_iterator &operator -= (difference_type n) { 1125 it2_ -= n; 1126 return *this; 1127 } 1128 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const1129 difference_type operator - (const const_iterator &it) const { 1130 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1131 // FIXME we shouldn't compare floats 1132 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 1133 return it2_ - it.it2_; 1134 } 1135 1136 // Dereference 1137 BOOST_UBLAS_INLINE operator *() const1138 const_reference operator * () const { 1139 return functor_type::apply (it1_, *it2_); 1140 } 1141 BOOST_UBLAS_INLINE operator [](difference_type n) const1142 const_reference operator [] (difference_type n) const { 1143 return *(*this + n); 1144 } 1145 1146 // Index 1147 BOOST_UBLAS_INLINE index() const1148 size_type index () const { 1149 return it2_.index (); 1150 } 1151 1152 // Assignment 1153 BOOST_UBLAS_INLINE operator =(const const_iterator & it)1154 const_iterator &operator = (const const_iterator &it) { 1155 container_const_reference<self_type>::assign (&it ()); 1156 it1_ = it.it1_; 1157 it2_ = it.it2_; 1158 return *this; 1159 } 1160 1161 // Comparison 1162 BOOST_UBLAS_INLINE operator ==(const const_iterator & it) const1163 bool operator == (const const_iterator &it) const { 1164 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1165 // FIXME we shouldn't compare floats 1166 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 1167 return it2_ == it.it2_; 1168 } 1169 BOOST_UBLAS_INLINE operator <(const const_iterator & it) const1170 bool operator < (const const_iterator &it) const { 1171 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1172 // FIXME we shouldn't compare floats 1173 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 1174 return it2_ < it.it2_; 1175 } 1176 1177 private: 1178 const_subiterator1_type it1_; 1179 const_subiterator2_type it2_; 1180 }; 1181 #endif 1182 1183 BOOST_UBLAS_INLINE begin() const1184 const_iterator begin () const { 1185 return find (0); 1186 } 1187 BOOST_UBLAS_INLINE cbegin() const1188 const_iterator cbegin () const { 1189 return begin (); 1190 } 1191 BOOST_UBLAS_INLINE end() const1192 const_iterator end () const { 1193 return find (size ()); 1194 } 1195 BOOST_UBLAS_INLINE cend() const1196 const_iterator cend () const { 1197 return end (); 1198 } 1199 1200 // Reverse iterator 1201 typedef reverse_iterator_base<const_iterator> const_reverse_iterator; 1202 1203 BOOST_UBLAS_INLINE rbegin() const1204 const_reverse_iterator rbegin () const { 1205 return const_reverse_iterator (end ()); 1206 } 1207 BOOST_UBLAS_INLINE crbegin() const1208 const_reverse_iterator crbegin () const { 1209 return rbegin (); 1210 } 1211 BOOST_UBLAS_INLINE rend() const1212 const_reverse_iterator rend () const { 1213 return const_reverse_iterator (begin ()); 1214 } 1215 BOOST_UBLAS_INLINE crend() const1216 const_reverse_iterator crend () const { 1217 return end (); 1218 } 1219 1220 private: 1221 expression1_closure_type e1_; 1222 expression2_closure_type e2_; 1223 }; 1224 1225 template<class E1, class E2, class F> 1226 struct vector_binary_scalar1_traits { 1227 typedef vector_binary_scalar1<E1, E2, F> expression_type; // allow E1 to be builtin type 1228 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG 1229 typedef expression_type result_type; 1230 #else 1231 typedef typename E2::vector_temporary_type result_type; 1232 #endif 1233 }; 1234 1235 // (t * v) [i] = t * v [i] 1236 template<class T1, class E2> 1237 BOOST_UBLAS_INLINE 1238 typename boost::enable_if< is_convertible<T1, typename E2::value_type >, 1239 typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type 1240 >::type operator *(const T1 & e1,const vector_expression<E2> & e2)1241 operator * (const T1 &e1, 1242 const vector_expression<E2> &e2) { 1243 typedef typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type; 1244 return expression_type (e1, e2 ()); 1245 } 1246 1247 1248 template<class E1, class E2, class F> 1249 class vector_binary_scalar2: 1250 public vector_expression<vector_binary_scalar2<E1, E2, F> > { 1251 1252 typedef F functor_type; 1253 typedef E1 expression1_type; 1254 typedef E2 expression2_type; 1255 typedef typename E1::const_closure_type expression1_closure_type; 1256 typedef const E2& expression2_closure_type; 1257 typedef vector_binary_scalar2<E1, E2, F> self_type; 1258 public: 1259 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 1260 using vector_expression<vector_binary_scalar2<E1, E2, F> >::operator (); 1261 #endif 1262 typedef typename E1::size_type size_type; 1263 typedef typename E1::difference_type difference_type; 1264 typedef typename F::result_type value_type; 1265 typedef value_type const_reference; 1266 typedef const_reference reference; 1267 typedef const self_type const_closure_type; 1268 typedef const_closure_type closure_type; 1269 typedef unknown_storage_tag storage_category; 1270 1271 // Construction and destruction 1272 BOOST_UBLAS_INLINE vector_binary_scalar2(const expression1_type & e1,const expression2_type & e2)1273 vector_binary_scalar2 (const expression1_type &e1, const expression2_type &e2): 1274 e1_ (e1), e2_ (e2) {} 1275 1276 // Accessors 1277 BOOST_UBLAS_INLINE size() const1278 size_type size () const { 1279 return e1_.size (); 1280 } 1281 1282 public: 1283 // Element access 1284 BOOST_UBLAS_INLINE operator ()(size_type i) const1285 const_reference operator () (size_type i) const { 1286 return functor_type::apply (e1_ (i), e2_); 1287 } 1288 1289 BOOST_UBLAS_INLINE operator [](size_type i) const1290 const_reference operator [] (size_type i) const { 1291 return functor_type::apply (e1_ [i], e2_); 1292 } 1293 1294 // Closure comparison 1295 BOOST_UBLAS_INLINE same_closure(const vector_binary_scalar2 & vbs2) const1296 bool same_closure (const vector_binary_scalar2 &vbs2) const { 1297 return (*this).e1_.same_closure (vbs2.e1_) && 1298 &e2_ == &(vbs2.e2_); 1299 } 1300 1301 // Iterator types 1302 private: 1303 typedef typename expression1_type::const_iterator const_subiterator1_type; 1304 typedef expression2_type const_subiterator2_type; 1305 typedef const value_type *const_pointer; 1306 1307 public: 1308 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1309 typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator; 1310 typedef const_iterator iterator; 1311 #else 1312 class const_iterator; 1313 typedef const_iterator iterator; 1314 #endif 1315 1316 // Element lookup 1317 BOOST_UBLAS_INLINE find(size_type i) const1318 const_iterator find (size_type i) const { 1319 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1320 const_subiterator1_type it (e1_.find (i)); 1321 return const_iterator (*this, it.index ()); 1322 #else 1323 return const_iterator (*this, e1_.find (i), const_subiterator2_type (e2_)); 1324 #endif 1325 } 1326 1327 // Iterator enhances the iterator of the referenced vector expression 1328 // with the binary functor. 1329 1330 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 1331 class const_iterator: 1332 public container_const_reference<vector_binary_scalar2>, 1333 public iterator_base_traits<typename E1::const_iterator::iterator_category>::template 1334 iterator_base<const_iterator, value_type>::type { 1335 public: 1336 typedef typename E1::const_iterator::iterator_category iterator_category; 1337 typedef typename vector_binary_scalar2::difference_type difference_type; 1338 typedef typename vector_binary_scalar2::value_type value_type; 1339 typedef typename vector_binary_scalar2::const_reference reference; 1340 typedef typename vector_binary_scalar2::const_pointer pointer; 1341 1342 // Construction and destruction 1343 BOOST_UBLAS_INLINE const_iterator()1344 const_iterator (): 1345 container_const_reference<self_type> (), it1_ (), it2_ () {} 1346 BOOST_UBLAS_INLINE const_iterator(const self_type & vbs,const const_subiterator1_type & it1,const const_subiterator2_type & it2)1347 const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2): 1348 container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {} 1349 1350 // Arithmetic 1351 BOOST_UBLAS_INLINE operator ++()1352 const_iterator &operator ++ () { 1353 ++ it1_; 1354 return *this; 1355 } 1356 BOOST_UBLAS_INLINE operator --()1357 const_iterator &operator -- () { 1358 -- it1_; 1359 return *this; 1360 } 1361 BOOST_UBLAS_INLINE operator +=(difference_type n)1362 const_iterator &operator += (difference_type n) { 1363 it1_ += n; 1364 return *this; 1365 } 1366 BOOST_UBLAS_INLINE operator -=(difference_type n)1367 const_iterator &operator -= (difference_type n) { 1368 it1_ -= n; 1369 return *this; 1370 } 1371 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const1372 difference_type operator - (const const_iterator &it) const { 1373 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1374 // FIXME we shouldn't compare floats 1375 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 1376 return it1_ - it.it1_; 1377 } 1378 1379 // Dereference 1380 BOOST_UBLAS_INLINE operator *() const1381 const_reference operator * () const { 1382 return functor_type::apply (*it1_, it2_); 1383 } 1384 BOOST_UBLAS_INLINE operator [](difference_type n) const1385 const_reference operator [] (difference_type n) const { 1386 return *(*this + n); 1387 } 1388 1389 // Index 1390 BOOST_UBLAS_INLINE index() const1391 size_type index () const { 1392 return it1_.index (); 1393 } 1394 1395 // Assignment 1396 BOOST_UBLAS_INLINE operator =(const const_iterator & it)1397 const_iterator &operator = (const const_iterator &it) { 1398 container_const_reference<self_type>::assign (&it ()); 1399 it1_ = it.it1_; 1400 it2_ = it.it2_; 1401 return *this; 1402 } 1403 1404 // Comparison 1405 BOOST_UBLAS_INLINE operator ==(const const_iterator & it) const1406 bool operator == (const const_iterator &it) const { 1407 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1408 // FIXME we shouldn't compare floats 1409 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 1410 return it1_ == it.it1_; 1411 } 1412 BOOST_UBLAS_INLINE operator <(const const_iterator & it) const1413 bool operator < (const const_iterator &it) const { 1414 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1415 // FIXME we shouldn't compare floats 1416 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 1417 return it1_ < it.it1_; 1418 } 1419 1420 private: 1421 const_subiterator1_type it1_; 1422 const_subiterator2_type it2_; 1423 }; 1424 #endif 1425 1426 BOOST_UBLAS_INLINE begin() const1427 const_iterator begin () const { 1428 return find (0); 1429 } 1430 BOOST_UBLAS_INLINE cbegin() const1431 const_iterator cbegin () const { 1432 return begin (); 1433 } 1434 BOOST_UBLAS_INLINE end() const1435 const_iterator end () const { 1436 return find (size ()); 1437 } 1438 BOOST_UBLAS_INLINE cend() const1439 const_iterator cend () const { 1440 return end (); 1441 } 1442 1443 // Reverse iterator 1444 typedef reverse_iterator_base<const_iterator> const_reverse_iterator; 1445 1446 BOOST_UBLAS_INLINE rbegin() const1447 const_reverse_iterator rbegin () const { 1448 return const_reverse_iterator (end ()); 1449 } 1450 BOOST_UBLAS_INLINE crbegin() const1451 const_reverse_iterator crbegin () const { 1452 return rbegin (); 1453 } 1454 BOOST_UBLAS_INLINE rend() const1455 const_reverse_iterator rend () const { 1456 return const_reverse_iterator (begin ()); 1457 } 1458 BOOST_UBLAS_INLINE crend() const1459 const_reverse_iterator crend () const { 1460 return rend (); 1461 } 1462 1463 private: 1464 expression1_closure_type e1_; 1465 expression2_closure_type e2_; 1466 }; 1467 1468 template<class E1, class E2, class F> 1469 struct vector_binary_scalar2_traits { 1470 typedef vector_binary_scalar2<E1, E2, F> expression_type; // allow E2 to be builtin type 1471 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG 1472 typedef expression_type result_type; 1473 #else 1474 typedef typename E1::vector_temporary_type result_type; 1475 #endif 1476 }; 1477 1478 // (v * t) [i] = v [i] * t 1479 template<class E1, class T2> 1480 BOOST_UBLAS_INLINE 1481 typename boost::enable_if< is_convertible<T2, typename E1::value_type >, 1482 typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type 1483 >::type operator *(const vector_expression<E1> & e1,const T2 & e2)1484 operator * (const vector_expression<E1> &e1, 1485 const T2 &e2) { 1486 typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type; 1487 return expression_type (e1 (), e2); 1488 } 1489 1490 // (v / t) [i] = v [i] / t 1491 template<class E1, class T2> 1492 BOOST_UBLAS_INLINE 1493 typename boost::enable_if< is_convertible<T2, typename E1::value_type >, 1494 typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type 1495 >::type operator /(const vector_expression<E1> & e1,const T2 & e2)1496 operator / (const vector_expression<E1> &e1, 1497 const T2 &e2) { 1498 typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type; 1499 return expression_type (e1 (), e2); 1500 } 1501 1502 1503 template<class E, class F> 1504 class vector_scalar_unary: 1505 public scalar_expression<vector_scalar_unary<E, F> > { 1506 1507 typedef E expression_type; 1508 typedef F functor_type; 1509 typedef typename E::const_closure_type expression_closure_type; 1510 typedef typename E::const_iterator::iterator_category iterator_category; 1511 typedef vector_scalar_unary<E, F> self_type; 1512 public: 1513 typedef typename F::result_type value_type; 1514 typedef typename E::difference_type difference_type; 1515 typedef const self_type const_closure_type; 1516 typedef const_closure_type closure_type; 1517 typedef unknown_storage_tag storage_category; 1518 1519 // Construction and destruction 1520 BOOST_UBLAS_INLINE vector_scalar_unary(const expression_type & e)1521 explicit vector_scalar_unary (const expression_type &e): 1522 e_ (e) {} 1523 1524 private: 1525 // Expression accessors 1526 BOOST_UBLAS_INLINE expression() const1527 const expression_closure_type &expression () const { 1528 return e_; 1529 } 1530 1531 public: 1532 BOOST_UBLAS_INLINE operator value_type() const1533 operator value_type () const { 1534 return evaluate (iterator_category ()); 1535 } 1536 1537 private: 1538 // Dense random access specialization 1539 BOOST_UBLAS_INLINE evaluate(dense_random_access_iterator_tag) const1540 value_type evaluate (dense_random_access_iterator_tag) const { 1541 #ifdef BOOST_UBLAS_USE_INDEXING 1542 return functor_type::apply (e_); 1543 #elif BOOST_UBLAS_USE_ITERATING 1544 difference_type size = e_.size (); 1545 return functor_type::apply (size, e_.begin ()); 1546 #else 1547 difference_type size = e_.size (); 1548 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) 1549 return functor_type::apply (size, e_.begin ()); 1550 else 1551 return functor_type::apply (e_); 1552 #endif 1553 } 1554 1555 // Packed bidirectional specialization 1556 BOOST_UBLAS_INLINE evaluate(packed_random_access_iterator_tag) const1557 value_type evaluate (packed_random_access_iterator_tag) const { 1558 return functor_type::apply (e_.begin (), e_.end ()); 1559 } 1560 1561 // Sparse bidirectional specialization 1562 BOOST_UBLAS_INLINE evaluate(sparse_bidirectional_iterator_tag) const1563 value_type evaluate (sparse_bidirectional_iterator_tag) const { 1564 return functor_type::apply (e_.begin (), e_.end ()); 1565 } 1566 1567 private: 1568 expression_closure_type e_; 1569 }; 1570 1571 template<class E, class F> 1572 struct vector_scalar_unary_traits { 1573 typedef vector_scalar_unary<E, F> expression_type; 1574 #if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET) 1575 // FIXME don't define USE_SCALAR_ET other then for testing 1576 // They do not work for complex types 1577 typedef expression_type result_type; 1578 #else 1579 typedef typename F::result_type result_type; 1580 #endif 1581 }; 1582 1583 // sum v = sum (v [i]) 1584 template<class E> 1585 BOOST_UBLAS_INLINE 1586 typename vector_scalar_unary_traits<E, vector_sum<E> >::result_type sum(const vector_expression<E> & e)1587 sum (const vector_expression<E> &e) { 1588 typedef typename vector_scalar_unary_traits<E, vector_sum<E> >::expression_type expression_type; 1589 return expression_type (e ()); 1590 } 1591 1592 // real: norm_1 v = sum (abs (v [i])) 1593 // complex: norm_1 v = sum (abs (real (v [i])) + abs (imag (v [i]))) 1594 template<class E> 1595 BOOST_UBLAS_INLINE 1596 typename vector_scalar_unary_traits<E, vector_norm_1<E> >::result_type norm_1(const vector_expression<E> & e)1597 norm_1 (const vector_expression<E> &e) { 1598 typedef typename vector_scalar_unary_traits<E, vector_norm_1<E> >::expression_type expression_type; 1599 return expression_type (e ()); 1600 } 1601 1602 // real: norm_2 v = sqrt (sum (v [i] * v [i])) 1603 // complex: norm_2 v = sqrt (sum (v [i] * conj (v [i]))) 1604 template<class E> 1605 BOOST_UBLAS_INLINE 1606 typename vector_scalar_unary_traits<E, vector_norm_2<E> >::result_type norm_2(const vector_expression<E> & e)1607 norm_2 (const vector_expression<E> &e) { 1608 typedef typename vector_scalar_unary_traits<E, vector_norm_2<E> >::expression_type expression_type; 1609 return expression_type (e ()); 1610 } 1611 1612 // real: norm_2_square v = sum(v [i] * v [i]) 1613 // complex: norm_2_square v = sum(v [i] * conj (v [i])) 1614 template<class E> 1615 BOOST_UBLAS_INLINE 1616 typename vector_scalar_unary_traits<E, vector_norm_2_square<E> >::result_type norm_2_square(const vector_expression<E> & e)1617 norm_2_square (const vector_expression<E> &e) { 1618 typedef typename vector_scalar_unary_traits<E, vector_norm_2_square<E> >::expression_type expression_type; 1619 return expression_type (e ()); 1620 } 1621 1622 // real: norm_inf v = maximum (abs (v [i])) 1623 // complex: norm_inf v = maximum (maximum (abs (real (v [i])), abs (imag (v [i])))) 1624 template<class E> 1625 BOOST_UBLAS_INLINE 1626 typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::result_type norm_inf(const vector_expression<E> & e)1627 norm_inf (const vector_expression<E> &e) { 1628 typedef typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::expression_type expression_type; 1629 return expression_type (e ()); 1630 } 1631 1632 // real: index_norm_inf v = minimum (i: abs (v [i]) == maximum (abs (v [i]))) 1633 template<class E> 1634 BOOST_UBLAS_INLINE 1635 typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::result_type index_norm_inf(const vector_expression<E> & e)1636 index_norm_inf (const vector_expression<E> &e) { 1637 typedef typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::expression_type expression_type; 1638 return expression_type (e ()); 1639 } 1640 1641 template<class E1, class E2, class F> 1642 class vector_scalar_binary: 1643 public scalar_expression<vector_scalar_binary<E1, E2, F> > { 1644 1645 typedef E1 expression1_type; 1646 typedef E2 expression2_type; 1647 typedef F functor_type; 1648 typedef typename E1::const_closure_type expression1_closure_type; 1649 typedef typename E2::const_closure_type expression2_closure_type; 1650 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category, 1651 typename E2::const_iterator::iterator_category>::iterator_category iterator_category; 1652 typedef vector_scalar_binary<E1, E2, F> self_type; 1653 public: 1654 static const unsigned complexity = 1; 1655 typedef typename F::result_type value_type; 1656 typedef typename E1::difference_type difference_type; 1657 typedef const self_type const_closure_type; 1658 typedef const_closure_type closure_type; 1659 typedef unknown_storage_tag storage_category; 1660 1661 // Construction and destruction 1662 BOOST_UBLAS_INLINE vector_scalar_binary(const expression1_type & e1,const expression2_type & e2)1663 vector_scalar_binary (const expression1_type &e1, const expression2_type &e2): 1664 e1_ (e1), e2_ (e2) {} 1665 1666 private: 1667 // Accessors 1668 BOOST_UBLAS_INLINE expression1() const1669 const expression1_closure_type &expression1 () const { 1670 return e1_; 1671 } 1672 BOOST_UBLAS_INLINE expression2() const1673 const expression2_closure_type &expression2 () const { 1674 return e2_; 1675 } 1676 1677 public: 1678 BOOST_UBLAS_INLINE operator value_type() const1679 operator value_type () const { 1680 return evaluate (iterator_category ()); 1681 } 1682 1683 private: 1684 // Dense random access specialization 1685 BOOST_UBLAS_INLINE evaluate(dense_random_access_iterator_tag) const1686 value_type evaluate (dense_random_access_iterator_tag) const { 1687 BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic()); 1688 #ifdef BOOST_UBLAS_USE_INDEXING 1689 return functor_type::apply (e1_, e2_); 1690 #elif BOOST_UBLAS_USE_ITERATING 1691 difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ()); 1692 return functor_type::apply (size, e1_.begin (), e2_.begin ()); 1693 #else 1694 difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ()); 1695 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD) 1696 return functor_type::apply (size, e1_.begin (), e2_.begin ()); 1697 else 1698 return functor_type::apply (e1_, e2_); 1699 #endif 1700 } 1701 1702 // Packed bidirectional specialization 1703 BOOST_UBLAS_INLINE evaluate(packed_random_access_iterator_tag) const1704 value_type evaluate (packed_random_access_iterator_tag) const { 1705 BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic()); 1706 return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end ()); 1707 } 1708 1709 // Sparse bidirectional specialization 1710 BOOST_UBLAS_INLINE evaluate(sparse_bidirectional_iterator_tag) const1711 value_type evaluate (sparse_bidirectional_iterator_tag) const { 1712 BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic()); 1713 return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end (), sparse_bidirectional_iterator_tag ()); 1714 } 1715 1716 private: 1717 expression1_closure_type e1_; 1718 expression2_closure_type e2_; 1719 }; 1720 1721 template<class E1, class E2, class F> 1722 struct vector_scalar_binary_traits { 1723 typedef vector_scalar_binary<E1, E2, F> expression_type; 1724 #if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET) 1725 // FIXME don't define USE_SCALAR_ET other then for testing 1726 // They do not work for complex types 1727 typedef expression_type result_type; 1728 #else 1729 typedef typename F::result_type result_type; 1730 #endif 1731 }; 1732 1733 // inner_prod (v1, v2) = sum (v1 [i] * v2 [i]) 1734 template<class E1, class E2> 1735 BOOST_UBLAS_INLINE 1736 typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2, 1737 typename promote_traits<typename E1::value_type, 1738 typename E2::value_type>::promote_type> >::result_type inner_prod(const vector_expression<E1> & e1,const vector_expression<E2> & e2)1739 inner_prod (const vector_expression<E1> &e1, 1740 const vector_expression<E2> &e2) { 1741 typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2, 1742 typename promote_traits<typename E1::value_type, 1743 typename E2::value_type>::promote_type> >::expression_type expression_type; 1744 return expression_type (e1 (), e2 ()); 1745 } 1746 1747 template<class E1, class E2> 1748 BOOST_UBLAS_INLINE 1749 typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2, 1750 typename type_traits<typename promote_traits<typename E1::value_type, 1751 typename E2::value_type>::promote_type>::precision_type> >::result_type prec_inner_prod(const vector_expression<E1> & e1,const vector_expression<E2> & e2)1752 prec_inner_prod (const vector_expression<E1> &e1, 1753 const vector_expression<E2> &e2) { 1754 typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2, 1755 typename type_traits<typename promote_traits<typename E1::value_type, 1756 typename E2::value_type>::promote_type>::precision_type> >::expression_type expression_type; 1757 return expression_type (e1 (), e2 ()); 1758 } 1759 1760 }}} 1761 1762 #endif 1763