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_MATRIX_EXPRESSION_
14#define _BOOST_UBLAS_MATRIX_EXPRESSION_
15
16#include <boost/numeric/ublas/vector_expression.hpp>
17
18// Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
19// Iterators based on ideas of Jeremy Siek
20//
21// Classes that model the Matrix Expression concept
22
23namespace boost { namespace numeric { namespace ublas {
24
25template<class E>
26class matrix_reference:
27 public matrix_expression<matrix_reference<E> > {
28
29 typedef matrix_reference<E> self_type;
30public:
31#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
32 using matrix_expression<self_type>::operator ();
33#endif
34 typedef typename E::size_type size_type;
35 typedef typename E::difference_type difference_type;
36 typedef typename E::value_type value_type;
37 typedef typename E::const_reference const_reference;
38 typedef typename boost::mpl::if_<boost::is_const<E>,
39 typename E::const_reference,
40 typename E::reference>::type reference;
41 typedef E referred_type;
42 typedef const self_type const_closure_type;
43 typedef self_type closure_type;
44 typedef typename E::orientation_category orientation_category;
45 typedef typename E::storage_category storage_category;
46
47 // Construction and destruction
48 BOOST_UBLAS_INLINE
49 explicit matrix_reference (referred_type &e):
50 e_ (e) {}
51
52 // Accessors
53 BOOST_UBLAS_INLINE
54 size_type size1 () const {
55 return e_.size1 ();
56 }
57 BOOST_UBLAS_INLINE
58 size_type size2 () const {
59 return e_.size2 ();
60 }
61
62public:
63 // Expression accessors - const correct
64 BOOST_UBLAS_INLINE
65 const referred_type &expression () const {
66 return e_;
67 }
68 BOOST_UBLAS_INLINE
69 referred_type &expression () {
70 return e_;
71 }
72
73public:
74 // Element access
75#ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
76 BOOST_UBLAS_INLINE
77 const_reference operator () (size_type i, size_type j) const {
78 return expression () (i, j);
79 }
80 BOOST_UBLAS_INLINE
81 reference operator () (size_type i, size_type j) {
82 return expression () (i, j);
83 }
84#else
85 BOOST_UBLAS_INLINE
86 reference operator () (size_type i, size_type j) const {
87 return expression () (i, j);
88 }
89#endif
90
91#ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
92 BOOST_UBLAS_INLINE
93 const_reference operator () (size_type i) const {
94 return expression () (i);
95 }
96 BOOST_UBLAS_INLINE
97 reference operator () (size_type i) {
98 return expression () (i);
99 }
100#else
101 BOOST_UBLAS_INLINE
102 reference operator () (size_type i) const {
103 return expression () (i);
104 }
105#endif
106
107
108 // Assignment
109 BOOST_UBLAS_INLINE
110 matrix_reference &operator = (const matrix_reference &m) {
111 expression ().operator = (m);
112 return *this;
113 }
114 template<class AE>
115 BOOST_UBLAS_INLINE
116 matrix_reference &operator = (const matrix_expression<AE> &ae) {
117 expression ().operator = (ae);
118 return *this;
119 }
120 template<class AE>
121 BOOST_UBLAS_INLINE
122 matrix_reference &assign (const matrix_expression<AE> &ae) {
123 expression ().assign (ae);
124 return *this;
125 }
126 template<class AE>
127 BOOST_UBLAS_INLINE
128 matrix_reference &operator += (const matrix_expression<AE> &ae) {
129 expression ().operator += (ae);
130 return *this;
131 }
132 template<class AE>
133 BOOST_UBLAS_INLINE
134 matrix_reference &plus_assign (const matrix_expression<AE> &ae) {
135 expression ().plus_assign (ae);
136 return *this;
137 }
138 template<class AE>
139 BOOST_UBLAS_INLINE
140 matrix_reference &operator -= (const matrix_expression<AE> &ae) {
141 expression ().operator -= (ae);
142 return *this;
143 }
144 template<class AE>
145 BOOST_UBLAS_INLINE
146 matrix_reference &minus_assign (const matrix_expression<AE> &ae) {
147 expression ().minus_assign (ae);
148 return *this;
149 }
150 template<class AT>
151 BOOST_UBLAS_INLINE
152 matrix_reference &operator *= (const AT &at) {
153 expression ().operator *= (at);
154 return *this;
155 }
156 template<class AT>
157 BOOST_UBLAS_INLINE
158 matrix_reference &operator /= (const AT &at) {
159 expression ().operator /= (at);
160 return *this;
161 }
162
163 // Swapping
164 BOOST_UBLAS_INLINE
165 void swap (matrix_reference &m) {
166 expression ().swap (m.expression ());
167 }
168
169 // Closure comparison
170 BOOST_UBLAS_INLINE
171 bool same_closure (const matrix_reference &mr) const {
172 return &(*this).e_ == &mr.e_;
173 }
174
175 // Iterator types
176 typedef typename E::const_iterator1 const_iterator1;
177 typedef typename boost::mpl::if_<boost::is_const<E>,
178 typename E::const_iterator1,
179 typename E::iterator1>::type iterator1;
180 typedef typename E::const_iterator2 const_iterator2;
181 typedef typename boost::mpl::if_<boost::is_const<E>,
182 typename E::const_iterator2,
183 typename E::iterator2>::type iterator2;
184
185 // Element lookup
186 BOOST_UBLAS_INLINE
187 const_iterator1 find1 (int rank, size_type i, size_type j) const {
188 return expression ().find1 (rank, i, j);
189 }
190 BOOST_UBLAS_INLINE
191 iterator1 find1 (int rank, size_type i, size_type j) {
192 return expression ().find1 (rank, i, j);
193 }
194 BOOST_UBLAS_INLINE
195 const_iterator2 find2 (int rank, size_type i, size_type j) const {
196 return expression ().find2 (rank, i, j);
197 }
198 BOOST_UBLAS_INLINE
199 iterator2 find2 (int rank, size_type i, size_type j) {
200 return expression ().find2 (rank, i, j);
201 }
202
203 // Iterators are the iterators of the referenced expression.
204
205 BOOST_UBLAS_INLINE
206 const_iterator1 begin1 () const {
207 return expression ().begin1 ();
208 }
209 BOOST_UBLAS_INLINE
210 const_iterator1 cbegin1 () const {
211 return begin1 ();
212 }
213 BOOST_UBLAS_INLINE
214 const_iterator1 end1 () const {
215 return expression ().end1 ();
216 }
217 BOOST_UBLAS_INLINE
218 const_iterator1 cend1 () const {
219 return end1 ();
220 }
221
222 BOOST_UBLAS_INLINE
223 iterator1 begin1 () {
224 return expression ().begin1 ();
225 }
226 BOOST_UBLAS_INLINE
227 iterator1 end1 () {
228 return expression ().end1 ();
229 }
230
231 BOOST_UBLAS_INLINE
232 const_iterator2 begin2 () const {
233 return expression ().begin2 ();
234 }
235 BOOST_UBLAS_INLINE
236 const_iterator2 cbegin2 () const {
237 return begin2 ();
238 }
239 BOOST_UBLAS_INLINE
240 const_iterator2 end2 () const {
241 return expression ().end2 ();
242 }
243 BOOST_UBLAS_INLINE
244 const_iterator2 cend2 () const {
245 return end2 ();
246 }
247
248 BOOST_UBLAS_INLINE
249 iterator2 begin2 () {
250 return expression ().begin2 ();
251 }
252 BOOST_UBLAS_INLINE
253 iterator2 end2 () {
254 return expression ().end2 ();
255 }
256
257 // Reverse iterators
258 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
259 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
260
261 BOOST_UBLAS_INLINE
262 const_reverse_iterator1 rbegin1 () const {
263 return const_reverse_iterator1 (end1 ());
264 }
265 BOOST_UBLAS_INLINE
266 const_reverse_iterator1 crbegin1 () const {
267 return rbegin1 ();
268 }
269 BOOST_UBLAS_INLINE
270 const_reverse_iterator1 rend1 () const {
271 return const_reverse_iterator1 (begin1 ());
272 }
273 BOOST_UBLAS_INLINE
274 const_reverse_iterator1 crend1 () const {
275 return rend1 ();
276 }
277
278 BOOST_UBLAS_INLINE
279 reverse_iterator1 rbegin1 () {
280 return reverse_iterator1 (end1 ());
281 }
282 BOOST_UBLAS_INLINE
283 reverse_iterator1 rend1 () {
284 return reverse_iterator1 (begin1 ());
285 }
286
287 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
288 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
289
290 BOOST_UBLAS_INLINE
291 const_reverse_iterator2 rbegin2 () const {
292 return const_reverse_iterator2 (end2 ());
293 }
294 BOOST_UBLAS_INLINE
295 const_reverse_iterator2 crbegin2 () const {
296 return rbegin2 ();
297 }
298 BOOST_UBLAS_INLINE
299 const_reverse_iterator2 rend2 () const {
300 return const_reverse_iterator2 (begin2 ());
301 }
302 BOOST_UBLAS_INLINE
303 const_reverse_iterator2 crend2 () const {
304 return rend2 ();
305 }
306
307 BOOST_UBLAS_INLINE
308 reverse_iterator2 rbegin2 () {
309 return reverse_iterator2 (end2 ());
310 }
311 BOOST_UBLAS_INLINE
312 reverse_iterator2 rend2 () {
313 return reverse_iterator2 (begin2 ());
314 }
315
316private:
317 referred_type &e_;
318};
319
320
321template<class E1, class E2, class F>
322class vector_matrix_binary:
323 public matrix_expression<vector_matrix_binary<E1, E2, F> > {
324
325 typedef E1 expression1_type;
326 typedef E2 expression2_type;
327public:
328 typedef typename E1::const_closure_type expression1_closure_type;
329 typedef typename E2::const_closure_type expression2_closure_type;
330private:
331 typedef vector_matrix_binary<E1, E2, F> self_type;
332public:
333#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
334 using matrix_expression<self_type>::operator ();
335#endif
336 typedef F functor_type;
337 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
338 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
339 typedef typename F::result_type value_type;
340 typedef value_type const_reference;
341 typedef const_reference reference;
342 typedef const self_type const_closure_type;
343 typedef const_closure_type closure_type;
344 typedef unknown_orientation_tag orientation_category;
345 typedef unknown_storage_tag storage_category;
346
347 // Construction and destruction
348 BOOST_UBLAS_INLINE
349 vector_matrix_binary (const expression1_type &e1, const expression2_type &e2):
350 e1_ (e1), e2_ (e2) {}
351
352 // Accessors
353 BOOST_UBLAS_INLINE
354 size_type size1 () const {
355 return e1_.size ();
356 }
357 BOOST_UBLAS_INLINE
358 size_type size2 () const {
359 return e2_.size ();
360 }
361
362public:
363 // Expression accessors
364 BOOST_UBLAS_INLINE
365 const expression1_closure_type &expression1 () const {
366 return e1_;
367 }
368 BOOST_UBLAS_INLINE
369 const expression2_closure_type &expression2 () const {
370 return e2_;
371 }
372
373public:
374 // Element access
375 BOOST_UBLAS_INLINE
376 const_reference operator () (size_type i, size_type j) const {
377 return functor_type::apply (e1_ (i), e2_ (j));
378 }
379
380
381
382 // Closure comparison
383 BOOST_UBLAS_INLINE
384 bool same_closure (const vector_matrix_binary &vmb) const {
385 return (*this).expression1 ().same_closure (vmb.expression1 ()) &&
386 (*this).expression2 ().same_closure (vmb.expression2 ());
387 }
388
389 // Iterator types
390private:
391 typedef typename E1::const_iterator const_subiterator1_type;
392 typedef typename E2::const_iterator const_subiterator2_type;
393 typedef const value_type *const_pointer;
394
395public:
396#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
397 typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
398 typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
399 typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
400 typedef const_iterator1 iterator1;
401 typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
402 typedef const_iterator2 iterator2;
403#else
404 class const_iterator1;
405 typedef const_iterator1 iterator1;
406 class const_iterator2;
407 typedef const_iterator2 iterator2;
408#endif
409 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
410 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
411
412 // Element lookup
413 BOOST_UBLAS_INLINE
414 const_iterator1 find1 (int rank, size_type i, size_type j) const {
415 const_subiterator1_type it1 (e1_.find (i));
416 const_subiterator1_type it1_end (e1_.find (size1 ()));
417 const_subiterator2_type it2 (e2_.find (j));
418 const_subiterator2_type it2_end (e2_.find (size2 ()));
419 if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == typename E2::value_type/*zero*/()))) {
420 it1 = it1_end;
421 it2 = it2_end;
422 }
423#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
424 return const_iterator1 (*this, it1.index (), it2.index ());
425#else
426#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
427 return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : typename E2::value_type/*zero*/());
428#else
429 return const_iterator1 (*this, it1, it2);
430#endif
431#endif
432 }
433 BOOST_UBLAS_INLINE
434 const_iterator2 find2 (int rank, size_type i, size_type j) const {
435 const_subiterator2_type it2 (e2_.find (j));
436 const_subiterator2_type it2_end (e2_.find (size2 ()));
437 const_subiterator1_type it1 (e1_.find (i));
438 const_subiterator1_type it1_end (e1_.find (size1 ()));
439 if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == typename E1::value_type/*zero*/()))) {
440 it2 = it2_end;
441 it1 = it1_end;
442 }
443#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
444 return const_iterator2 (*this, it1.index (), it2.index ());
445#else
446#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
447 return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : typename E1::value_type/*zero*/());
448#else
449 return const_iterator2 (*this, it1, it2);
450#endif
451#endif
452 }
453
454 // Iterators enhance the iterators of the referenced expressions
455 // with the binary functor.
456
457#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
458 class const_iterator1:
459 public container_const_reference<vector_matrix_binary>,
460 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
461 typename E2::const_iterator::iterator_category>::iterator_category>::template
462 iterator_base<const_iterator1, value_type>::type {
463 public:
464 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
465 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
466 typedef typename vector_matrix_binary::difference_type difference_type;
467 typedef typename vector_matrix_binary::value_type value_type;
468 typedef typename vector_matrix_binary::const_reference reference;
469 typedef typename vector_matrix_binary::const_pointer pointer;
470
471 typedef const_iterator2 dual_iterator_type;
472 typedef const_reverse_iterator2 dual_reverse_iterator_type;
473
474 // Construction and destruction
475#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
476 BOOST_UBLAS_INLINE
477 const_iterator1 ():
478 container_const_reference<self_type> (), it1_ (), it2_ (), t2_ () {}
479 BOOST_UBLAS_INLINE
480 const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t2):
481 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t2_ (t2) {}
482#else
483 BOOST_UBLAS_INLINE
484 const_iterator1 ():
485 container_const_reference<self_type> (), it1_ (), it2_ () {}
486 BOOST_UBLAS_INLINE
487 const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
488 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
489#endif
490
491 // Arithmetic
492 BOOST_UBLAS_INLINE
493 const_iterator1 &operator ++ () {
494 ++ it1_;
495 return *this;
496 }
497 BOOST_UBLAS_INLINE
498 const_iterator1 &operator -- () {
499 -- it1_;
500 return *this;
501 }
502 BOOST_UBLAS_INLINE
503 const_iterator1 &operator += (difference_type n) {
504 it1_ += n;
505 return *this;
506 }
507 BOOST_UBLAS_INLINE
508 const_iterator1 &operator -= (difference_type n) {
509 it1_ -= n;
510 return *this;
511 }
512 BOOST_UBLAS_INLINE
513 difference_type operator - (const const_iterator1 &it) const {
514 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
515 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
516 return it1_ - it.it1_;
517 }
518
519 // Dereference
520 BOOST_UBLAS_INLINE
521 const_reference operator * () const {
522#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
523 return functor_type::apply (*it1_, t2_);
524#else
525 return functor_type::apply (*it1_, *it2_);
526#endif
527 }
528 BOOST_UBLAS_INLINE
529 const_reference operator [] (difference_type n) const {
530 return *(*this + n);
531 }
532
533#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
534 BOOST_UBLAS_INLINE
535#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
536 typename self_type::
537#endif
538 const_iterator2 begin () const {
539 return (*this) ().find2 (1, index1 (), 0);
540 }
541 BOOST_UBLAS_INLINE
542#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
543 typename self_type::
544#endif
545 const_iterator2 cbegin () const {
546 return begin ();
547 }
548 BOOST_UBLAS_INLINE
549#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
550 typename self_type::
551#endif
552 const_iterator2 end () const {
553 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
554 }
555 BOOST_UBLAS_INLINE
556#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
557 typename self_type::
558#endif
559 const_iterator2 cend () const {
560 return end ();
561 }
562 BOOST_UBLAS_INLINE
563#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
564 typename self_type::
565#endif
566 const_reverse_iterator2 rbegin () const {
567 return const_reverse_iterator2 (end ());
568 }
569 BOOST_UBLAS_INLINE
570#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
571 typename self_type::
572#endif
573 const_reverse_iterator2 crbegin () const {
574 return rbegin ();
575 }
576 BOOST_UBLAS_INLINE
577#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
578 typename self_type::
579#endif
580 const_reverse_iterator2 rend () const {
581 return const_reverse_iterator2 (begin ());
582 }
583 BOOST_UBLAS_INLINE
584#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
585 typename self_type::
586#endif
587 const_reverse_iterator2 crend () const {
588 return rend ();
589 }
590#endif
591
592 // Indices
593 BOOST_UBLAS_INLINE
594 size_type index1 () const {
595 return it1_.index ();
596 }
597 BOOST_UBLAS_INLINE
598 size_type index2 () const {
599 return it2_.index ();
600 }
601
602 // Assignment
603 BOOST_UBLAS_INLINE
604 const_iterator1 &operator = (const const_iterator1 &it) {
605 container_const_reference<self_type>::assign (&it ());
606 it1_ = it.it1_;
607 it2_ = it.it2_;
608#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
609 t2_ = it.t2_;
610#endif
611 return *this;
612 }
613
614 // Comparison
615 BOOST_UBLAS_INLINE
616 bool operator == (const const_iterator1 &it) const {
617 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
618 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
619 return it1_ == it.it1_;
620 }
621 BOOST_UBLAS_INLINE
622 bool operator < (const const_iterator1 &it) const {
623 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
624 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
625 return it1_ < it.it1_;
626 }
627
628 private:
629#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
630 const_subiterator1_type it1_;
631 // Mutable due to assignment
632 /* const */ const_subiterator2_type it2_;
633 value_type t2_;
634#else
635 const_subiterator1_type it1_;
636 const_subiterator2_type it2_;
637#endif
638 };
639#endif
640
641 BOOST_UBLAS_INLINE
642 const_iterator1 begin1 () const {
643 return find1 (rank: 0, i: 0, j: 0);
644 }
645 BOOST_UBLAS_INLINE
646 const_iterator1 cbegin1 () const {
647 return begin1 ();
648 }
649 BOOST_UBLAS_INLINE
650 const_iterator1 end1 () const {
651 return find1 (rank: 0, i: size1 (), j: 0);
652 }
653 BOOST_UBLAS_INLINE
654 const_iterator1 cend1 () const {
655 return end1 ();
656 }
657
658#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
659 class const_iterator2:
660 public container_const_reference<vector_matrix_binary>,
661 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
662 typename E2::const_iterator::iterator_category>::iterator_category>::template
663 iterator_base<const_iterator2, value_type>::type {
664 public:
665 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
666 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
667 typedef typename vector_matrix_binary::difference_type difference_type;
668 typedef typename vector_matrix_binary::value_type value_type;
669 typedef typename vector_matrix_binary::const_reference reference;
670 typedef typename vector_matrix_binary::const_pointer pointer;
671
672 typedef const_iterator1 dual_iterator_type;
673 typedef const_reverse_iterator1 dual_reverse_iterator_type;
674
675 // Construction and destruction
676#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
677 BOOST_UBLAS_INLINE
678 const_iterator2 ():
679 container_const_reference<self_type> (), it1_ (), it2_ (), t1_ () {}
680 BOOST_UBLAS_INLINE
681 const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t1):
682 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t1_ (t1) {}
683#else
684 BOOST_UBLAS_INLINE
685 const_iterator2 ():
686 container_const_reference<self_type> (), it1_ (), it2_ () {}
687 BOOST_UBLAS_INLINE
688 const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
689 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
690#endif
691
692 // Arithmetic
693 BOOST_UBLAS_INLINE
694 const_iterator2 &operator ++ () {
695 ++ it2_;
696 return *this;
697 }
698 BOOST_UBLAS_INLINE
699 const_iterator2 &operator -- () {
700 -- it2_;
701 return *this;
702 }
703 BOOST_UBLAS_INLINE
704 const_iterator2 &operator += (difference_type n) {
705 it2_ += n;
706 return *this;
707 }
708 BOOST_UBLAS_INLINE
709 const_iterator2 &operator -= (difference_type n) {
710 it2_ -= n;
711 return *this;
712 }
713 BOOST_UBLAS_INLINE
714 difference_type operator - (const const_iterator2 &it) const {
715 BOOST_UBLAS_CHECK ((*this) ().same_closure(it ()), external_logic ());
716 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
717 return it2_ - it.it2_;
718 }
719
720 // Dereference
721 BOOST_UBLAS_INLINE
722 const_reference operator * () const {
723#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
724 return functor_type::apply (t1_, *it2_);
725#else
726 return functor_type::apply (*it1_, *it2_);
727#endif
728 }
729 BOOST_UBLAS_INLINE
730 const_reference operator [] (difference_type n) const {
731 return *(*this + n);
732 }
733
734#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
735 BOOST_UBLAS_INLINE
736#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
737 typename self_type::
738#endif
739 const_iterator1 begin () const {
740 return (*this) ().find1 (1, 0, index2 ());
741 }
742 BOOST_UBLAS_INLINE
743#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
744 typename self_type::
745#endif
746 const_iterator1 cbegin () const {
747 return begin ();
748 }
749 BOOST_UBLAS_INLINE
750#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
751 typename self_type::
752#endif
753 const_iterator1 end () const {
754 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
755 }
756 BOOST_UBLAS_INLINE
757#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
758 typename self_type::
759#endif
760 const_iterator1 cend () const {
761 return end ();
762 }
763 BOOST_UBLAS_INLINE
764#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
765 typename self_type::
766#endif
767 const_reverse_iterator1 rbegin () const {
768 return const_reverse_iterator1 (end ());
769 }
770 BOOST_UBLAS_INLINE
771#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
772 typename self_type::
773#endif
774 const_reverse_iterator1 crbegin () const {
775 return rbegin ();
776 }
777 BOOST_UBLAS_INLINE
778#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
779 typename self_type::
780#endif
781 const_reverse_iterator1 rend () const {
782 return const_reverse_iterator1 (begin ());
783 }
784 BOOST_UBLAS_INLINE
785#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
786 typename self_type::
787#endif
788 const_reverse_iterator1 crend () const {
789 return rend ();
790 }
791#endif
792
793 // Indices
794 BOOST_UBLAS_INLINE
795 size_type index1 () const {
796 return it1_.index ();
797 }
798 BOOST_UBLAS_INLINE
799 size_type index2 () const {
800 return it2_.index ();
801 }
802
803 // Assignment
804 BOOST_UBLAS_INLINE
805 const_iterator2 &operator = (const const_iterator2 &it) {
806 container_const_reference<self_type>::assign (&it ());
807 it1_ = it.it1_;
808 it2_ = it.it2_;
809#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
810 t1_ = it.t1_;
811#endif
812 return *this;
813 }
814
815 // Comparison
816 BOOST_UBLAS_INLINE
817 bool operator == (const const_iterator2 &it) const {
818 BOOST_UBLAS_CHECK ((*this) ().same_closure( it ()), external_logic ());
819 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
820 return it2_ == it.it2_;
821 }
822 BOOST_UBLAS_INLINE
823 bool operator < (const const_iterator2 &it) const {
824 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
825 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
826 return it2_ < it.it2_;
827 }
828
829 private:
830#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
831 // Mutable due to assignment
832 /* const */ const_subiterator1_type it1_;
833 const_subiterator2_type it2_;
834 value_type t1_;
835#else
836 const_subiterator1_type it1_;
837 const_subiterator2_type it2_;
838#endif
839 };
840#endif
841
842 BOOST_UBLAS_INLINE
843 const_iterator2 begin2 () const {
844 return find2 (rank: 0, i: 0, j: 0);
845 }
846 BOOST_UBLAS_INLINE
847 const_iterator2 cbegin2 () const {
848 return begin2 ();
849 }
850 BOOST_UBLAS_INLINE
851 const_iterator2 end2 () const {
852 return find2 (rank: 0, i: 0, j: size2 ());
853 }
854 BOOST_UBLAS_INLINE
855 const_iterator2 cend2 () const {
856 return end2 ();
857 }
858
859 // Reverse iterators
860
861 BOOST_UBLAS_INLINE
862 const_reverse_iterator1 rbegin1 () const {
863 return const_reverse_iterator1 (end1 ());
864 }
865 BOOST_UBLAS_INLINE
866 const_reverse_iterator1 crbegin1 () const {
867 return rbegin1 ();
868 }
869 BOOST_UBLAS_INLINE
870 const_reverse_iterator1 rend1 () const {
871 return const_reverse_iterator1 (begin1 ());
872 }
873 BOOST_UBLAS_INLINE
874 const_reverse_iterator1 crend1 () const {
875 return rend1 ();
876 }
877 BOOST_UBLAS_INLINE
878 const_reverse_iterator2 rbegin2 () const {
879 return const_reverse_iterator2 (end2 ());
880 }
881 BOOST_UBLAS_INLINE
882 const_reverse_iterator2 crbegin2 () const {
883 return rbegin2 ();
884 }
885 BOOST_UBLAS_INLINE
886 const_reverse_iterator2 rend2 () const {
887 return const_reverse_iterator2 (begin2 ());
888 }
889 BOOST_UBLAS_INLINE
890 const_reverse_iterator2 crend2 () const {
891 return rend2 ();
892 }
893
894private:
895 expression1_closure_type e1_;
896 expression2_closure_type e2_;
897};
898
899template<class E1, class E2, class F>
900struct vector_matrix_binary_traits {
901 typedef vector_matrix_binary<E1, E2, F> expression_type;
902#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
903 typedef expression_type result_type;
904#else
905 // ISSUE matrix is arbitary temporary type
906 typedef matrix<typename F::value_type> result_type;
907#endif
908};
909
910// (outer_prod (v1, v2)) [i] [j] = v1 [i] * v2 [j]
911template<class E1, class E2>
912BOOST_UBLAS_INLINE
913typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::result_type
914outer_prod (const vector_expression<E1> &e1,
915 const vector_expression<E2> &e2) {
916 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
917 typedef typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::expression_type expression_type;
918 return expression_type (e1 (), e2 ());
919}
920
921template<class E, class F>
922class matrix_unary1:
923 public matrix_expression<matrix_unary1<E, F> > {
924
925 typedef E expression_type;
926 typedef F functor_type;
927public:
928 typedef typename E::const_closure_type expression_closure_type;
929private:
930 typedef matrix_unary1<E, F> self_type;
931public:
932#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
933 using matrix_expression<self_type>::operator ();
934#endif
935 typedef typename E::size_type size_type;
936 typedef typename E::difference_type difference_type;
937 typedef typename F::result_type value_type;
938 typedef value_type const_reference;
939 typedef const_reference reference;
940 typedef const self_type const_closure_type;
941 typedef const_closure_type closure_type;
942 typedef typename E::orientation_category orientation_category;
943 typedef unknown_storage_tag storage_category;
944
945 // Construction and destruction
946 BOOST_UBLAS_INLINE
947 explicit matrix_unary1 (const expression_type &e):
948 e_ (e) {}
949
950 // Accessors
951 BOOST_UBLAS_INLINE
952 size_type size1 () const {
953 return e_.size1 ();
954 }
955 BOOST_UBLAS_INLINE
956 size_type size2 () const {
957 return e_.size2 ();
958 }
959
960public:
961 // Expression accessors
962 BOOST_UBLAS_INLINE
963 const expression_closure_type &expression () const {
964 return e_;
965 }
966
967public:
968 // Element access
969 BOOST_UBLAS_INLINE
970 const_reference operator () (size_type i, size_type j) const {
971 return functor_type::apply (e_ (i, j));
972 }
973
974 // Element access
975 BOOST_UBLAS_INLINE
976 const_reference operator () (size_type i) const {
977 return functor_type::apply (e_ (i));
978 }
979
980
981 // Closure comparison
982 BOOST_UBLAS_INLINE
983 bool same_closure (const matrix_unary1 &mu1) const {
984 return (*this).expression ().same_closure (mu1.expression ());
985 }
986
987 // Iterator types
988private:
989 typedef typename E::const_iterator1 const_subiterator1_type;
990 typedef typename E::const_iterator2 const_subiterator2_type;
991 typedef const value_type *const_pointer;
992
993public:
994#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
995 typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
996 typedef const_iterator1 iterator1;
997 typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
998 typedef const_iterator2 iterator2;
999#else
1000 class const_iterator1;
1001 typedef const_iterator1 iterator1;
1002 class const_iterator2;
1003 typedef const_iterator2 iterator2;
1004#endif
1005 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1006 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1007
1008 // Element lookup
1009 BOOST_UBLAS_INLINE
1010 const_iterator1 find1 (int rank, size_type i, size_type j) const {
1011 const_subiterator1_type it1 (e_.find1 (rank, i, j));
1012#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1013 return const_iterator1 (*this, it1.index1 (), it1.index2 ());
1014#else
1015 return const_iterator1 (*this, it1);
1016#endif
1017 }
1018 BOOST_UBLAS_INLINE
1019 const_iterator2 find2 (int rank, size_type i, size_type j) const {
1020 const_subiterator2_type it2 (e_.find2 (rank, i, j));
1021#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1022 return const_iterator2 (*this, it2.index1 (), it2.index2 ());
1023#else
1024 return const_iterator2 (*this, it2);
1025#endif
1026 }
1027
1028 // Iterators enhance the iterators of the referenced expression
1029 // with the unary functor.
1030
1031#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1032 class const_iterator1:
1033 public container_const_reference<matrix_unary1>,
1034 public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
1035 iterator_base<const_iterator1, value_type>::type {
1036 public:
1037 typedef typename E::const_iterator1::iterator_category iterator_category;
1038 typedef typename matrix_unary1::difference_type difference_type;
1039 typedef typename matrix_unary1::value_type value_type;
1040 typedef typename matrix_unary1::const_reference reference;
1041 typedef typename matrix_unary1::const_pointer pointer;
1042
1043 typedef const_iterator2 dual_iterator_type;
1044 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1045
1046 // Construction and destruction
1047 BOOST_UBLAS_INLINE
1048 const_iterator1 ():
1049 container_const_reference<self_type> (), it_ () {}
1050 BOOST_UBLAS_INLINE
1051 const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
1052 container_const_reference<self_type> (mu), it_ (it) {}
1053
1054 // Arithmetic
1055 BOOST_UBLAS_INLINE
1056 const_iterator1 &operator ++ () {
1057 ++ it_;
1058 return *this;
1059 }
1060 BOOST_UBLAS_INLINE
1061 const_iterator1 &operator -- () {
1062 -- it_;
1063 return *this;
1064 }
1065 BOOST_UBLAS_INLINE
1066 const_iterator1 &operator += (difference_type n) {
1067 it_ += n;
1068 return *this;
1069 }
1070 BOOST_UBLAS_INLINE
1071 const_iterator1 &operator -= (difference_type n) {
1072 it_ -= n;
1073 return *this;
1074 }
1075 BOOST_UBLAS_INLINE
1076 difference_type operator - (const const_iterator1 &it) const {
1077 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1078 return it_ - it.it_;
1079 }
1080
1081 // Dereference
1082 BOOST_UBLAS_INLINE
1083 const_reference operator * () const {
1084 return functor_type::apply (*it_);
1085 }
1086 BOOST_UBLAS_INLINE
1087 const_reference operator [] (difference_type n) const {
1088 return *(*this + n);
1089 }
1090
1091#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1092 BOOST_UBLAS_INLINE
1093#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1094 typename self_type::
1095#endif
1096 const_iterator2 begin () const {
1097 return (*this) ().find2 (1, index1 (), 0);
1098 }
1099 BOOST_UBLAS_INLINE
1100#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1101 typename self_type::
1102#endif
1103 const_iterator2 cbegin () const {
1104 return begin ();
1105 }
1106 BOOST_UBLAS_INLINE
1107#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1108 typename self_type::
1109#endif
1110 const_iterator2 end () const {
1111 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1112 }
1113 BOOST_UBLAS_INLINE
1114#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1115 typename self_type::
1116#endif
1117 const_iterator2 cend () const {
1118 return end ();
1119 }
1120 BOOST_UBLAS_INLINE
1121#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1122 typename self_type::
1123#endif
1124 const_reverse_iterator2 rbegin () const {
1125 return const_reverse_iterator2 (end ());
1126 }
1127 BOOST_UBLAS_INLINE
1128#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1129 typename self_type::
1130#endif
1131 const_reverse_iterator2 crbegin () const {
1132 return rbegin ();
1133 }
1134 BOOST_UBLAS_INLINE
1135#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1136 typename self_type::
1137#endif
1138 const_reverse_iterator2 rend () const {
1139 return const_reverse_iterator2 (begin ());
1140 }
1141 BOOST_UBLAS_INLINE
1142#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1143 typename self_type::
1144#endif
1145 const_reverse_iterator2 crend () const {
1146 return rend ();
1147 }
1148#endif
1149
1150 // Indices
1151 BOOST_UBLAS_INLINE
1152 size_type index1 () const {
1153 return it_.index1 ();
1154 }
1155 BOOST_UBLAS_INLINE
1156 size_type index2 () const {
1157 return it_.index2 ();
1158 }
1159
1160 // Assignment
1161 BOOST_UBLAS_INLINE
1162 const_iterator1 &operator = (const const_iterator1 &it) {
1163 container_const_reference<self_type>::assign (&it ());
1164 it_ = it.it_;
1165 return *this;
1166 }
1167
1168 // Comparison
1169 BOOST_UBLAS_INLINE
1170 bool operator == (const const_iterator1 &it) const {
1171 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1172 return it_ == it.it_;
1173 }
1174 BOOST_UBLAS_INLINE
1175 bool operator < (const const_iterator1 &it) const {
1176 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1177 return it_ < it.it_;
1178 }
1179
1180 private:
1181 const_subiterator1_type it_;
1182 };
1183#endif
1184
1185 BOOST_UBLAS_INLINE
1186 const_iterator1 begin1 () const {
1187 return find1 (rank: 0, i: 0, j: 0);
1188 }
1189 BOOST_UBLAS_INLINE
1190 const_iterator1 cbegin1 () const {
1191 return begin1 ();
1192 }
1193 BOOST_UBLAS_INLINE
1194 const_iterator1 end1 () const {
1195 return find1 (rank: 0, i: size1 (), j: 0);
1196 }
1197 BOOST_UBLAS_INLINE
1198 const_iterator1 cend1 () const {
1199 return end1 ();
1200 }
1201
1202#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1203 class const_iterator2:
1204 public container_const_reference<matrix_unary1>,
1205 public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
1206 iterator_base<const_iterator2, value_type>::type {
1207 public:
1208 typedef typename E::const_iterator2::iterator_category iterator_category;
1209 typedef typename matrix_unary1::difference_type difference_type;
1210 typedef typename matrix_unary1::value_type value_type;
1211 typedef typename matrix_unary1::const_reference reference;
1212 typedef typename matrix_unary1::const_pointer pointer;
1213
1214 typedef const_iterator1 dual_iterator_type;
1215 typedef const_reverse_iterator1 dual_reverse_iterator_type;
1216
1217 // Construction and destruction
1218 BOOST_UBLAS_INLINE
1219 const_iterator2 ():
1220 container_const_reference<self_type> (), it_ () {}
1221 BOOST_UBLAS_INLINE
1222 const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
1223 container_const_reference<self_type> (mu), it_ (it) {}
1224
1225 // Arithmetic
1226 BOOST_UBLAS_INLINE
1227 const_iterator2 &operator ++ () {
1228 ++ it_;
1229 return *this;
1230 }
1231 BOOST_UBLAS_INLINE
1232 const_iterator2 &operator -- () {
1233 -- it_;
1234 return *this;
1235 }
1236 BOOST_UBLAS_INLINE
1237 const_iterator2 &operator += (difference_type n) {
1238 it_ += n;
1239 return *this;
1240 }
1241 BOOST_UBLAS_INLINE
1242 const_iterator2 &operator -= (difference_type n) {
1243 it_ -= n;
1244 return *this;
1245 }
1246 BOOST_UBLAS_INLINE
1247 difference_type operator - (const const_iterator2 &it) const {
1248 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1249 return it_ - it.it_;
1250 }
1251
1252 // Dereference
1253 BOOST_UBLAS_INLINE
1254 const_reference operator * () const {
1255 return functor_type::apply (*it_);
1256 }
1257 BOOST_UBLAS_INLINE
1258 const_reference operator [] (difference_type n) const {
1259 return *(*this + n);
1260 }
1261
1262#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1263 BOOST_UBLAS_INLINE
1264#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1265 typename self_type::
1266#endif
1267 const_iterator1 begin () const {
1268 return (*this) ().find1 (1, 0, index2 ());
1269 }
1270 BOOST_UBLAS_INLINE
1271#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1272 typename self_type::
1273#endif
1274 const_iterator1 cbegin () const {
1275 return begin ();
1276 }
1277 BOOST_UBLAS_INLINE
1278#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1279 typename self_type::
1280#endif
1281 const_iterator1 end () const {
1282 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1283 }
1284 BOOST_UBLAS_INLINE
1285#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1286 typename self_type::
1287#endif
1288 const_iterator1 cend () const {
1289 return end ();
1290 }
1291 BOOST_UBLAS_INLINE
1292#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1293 typename self_type::
1294#endif
1295 const_reverse_iterator1 rbegin () const {
1296 return const_reverse_iterator1 (end ());
1297 }
1298 BOOST_UBLAS_INLINE
1299#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1300 typename self_type::
1301#endif
1302 const_reverse_iterator1 crbegin () const {
1303 return rbegin ();
1304 }
1305 BOOST_UBLAS_INLINE
1306#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1307 typename self_type::
1308#endif
1309 const_reverse_iterator1 rend () const {
1310 return const_reverse_iterator1 (begin ());
1311 }
1312 BOOST_UBLAS_INLINE
1313#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1314 typename self_type::
1315#endif
1316 const_reverse_iterator1 crend () const {
1317 return rend ();
1318 }
1319#endif
1320
1321 // Indices
1322 BOOST_UBLAS_INLINE
1323 size_type index1 () const {
1324 return it_.index1 ();
1325 }
1326 BOOST_UBLAS_INLINE
1327 size_type index2 () const {
1328 return it_.index2 ();
1329 }
1330
1331 // Assignment
1332 BOOST_UBLAS_INLINE
1333 const_iterator2 &operator = (const const_iterator2 &it) {
1334 container_const_reference<self_type>::assign (&it ());
1335 it_ = it.it_;
1336 return *this;
1337 }
1338
1339 // Comparison
1340 BOOST_UBLAS_INLINE
1341 bool operator == (const const_iterator2 &it) const {
1342 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1343 return it_ == it.it_;
1344 }
1345 BOOST_UBLAS_INLINE
1346 bool operator < (const const_iterator2 &it) const {
1347 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1348 return it_ < it.it_;
1349 }
1350
1351 private:
1352 const_subiterator2_type it_;
1353 };
1354#endif
1355
1356 BOOST_UBLAS_INLINE
1357 const_iterator2 begin2 () const {
1358 return find2 (rank: 0, i: 0, j: 0);
1359 }
1360 BOOST_UBLAS_INLINE
1361 const_iterator2 cbegin2 () const {
1362 return begin2 ();
1363 }
1364 BOOST_UBLAS_INLINE
1365 const_iterator2 end2 () const {
1366 return find2 (rank: 0, i: 0, j: size2 ());
1367 }
1368 BOOST_UBLAS_INLINE
1369 const_iterator2 cend2 () const {
1370 return end2 ();
1371 }
1372
1373 // Reverse iterators
1374
1375 BOOST_UBLAS_INLINE
1376 const_reverse_iterator1 rbegin1 () const {
1377 return const_reverse_iterator1 (end1 ());
1378 }
1379 BOOST_UBLAS_INLINE
1380 const_reverse_iterator1 crbegin1 () const {
1381 return rbegin1 ();
1382 }
1383 BOOST_UBLAS_INLINE
1384 const_reverse_iterator1 rend1 () const {
1385 return const_reverse_iterator1 (begin1 ());
1386 }
1387 BOOST_UBLAS_INLINE
1388 const_reverse_iterator1 crend1 () const {
1389 return rend1 ();
1390 }
1391
1392 BOOST_UBLAS_INLINE
1393 const_reverse_iterator2 rbegin2 () const {
1394 return const_reverse_iterator2 (end2 ());
1395 }
1396 BOOST_UBLAS_INLINE
1397 const_reverse_iterator2 crbegin2 () const {
1398 return rbegin2 ();
1399 }
1400 BOOST_UBLAS_INLINE
1401 const_reverse_iterator2 rend2 () const {
1402 return const_reverse_iterator2 (begin2 ());
1403 }
1404 BOOST_UBLAS_INLINE
1405 const_reverse_iterator2 crend2 () const {
1406 return rend2 ();
1407 }
1408
1409private:
1410 expression_closure_type e_;
1411};
1412
1413template<class E, class F>
1414struct matrix_unary1_traits {
1415 typedef matrix_unary1<E, F> expression_type;
1416#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1417 typedef expression_type result_type;
1418#else
1419 typedef typename E::matrix_temporary_type result_type;
1420#endif
1421};
1422
1423// (- m) [i] [j] = - m [i] [j]
1424template<class E>
1425BOOST_UBLAS_INLINE
1426typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::result_type
1427operator - (const matrix_expression<E> &e) {
1428 typedef typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
1429 return expression_type (e ());
1430}
1431
1432// (conj m) [i] [j] = conj (m [i] [j])
1433template<class E>
1434BOOST_UBLAS_INLINE
1435typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::result_type
1436conj (const matrix_expression<E> &e) {
1437 typedef typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
1438 return expression_type (e ());
1439}
1440
1441// (real m) [i] [j] = real (m [i] [j])
1442template<class E>
1443BOOST_UBLAS_INLINE
1444typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::result_type
1445real (const matrix_expression<E> &e) {
1446 typedef typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
1447 return expression_type (e ());
1448}
1449
1450// (imag m) [i] [j] = imag (m [i] [j])
1451template<class E>
1452BOOST_UBLAS_INLINE
1453typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::result_type
1454imag (const matrix_expression<E> &e) {
1455 typedef typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
1456 return expression_type (e ());
1457}
1458
1459template<class E, class F>
1460class matrix_unary2:
1461 public matrix_expression<matrix_unary2<E, F> > {
1462
1463 typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
1464 E,
1465 const E>::type expression_type;
1466 typedef F functor_type;
1467public:
1468 typedef typename boost::mpl::if_<boost::is_const<expression_type>,
1469 typename E::const_closure_type,
1470 typename E::closure_type>::type expression_closure_type;
1471private:
1472 typedef matrix_unary2<E, F> self_type;
1473public:
1474#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1475 using matrix_expression<self_type>::operator ();
1476#endif
1477 typedef typename E::size_type size_type;
1478 typedef typename E::difference_type difference_type;
1479 typedef typename F::result_type value_type;
1480 typedef value_type const_reference;
1481 typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
1482 typename E::reference,
1483 value_type>::type reference;
1484
1485 typedef const self_type const_closure_type;
1486 typedef self_type closure_type;
1487 typedef typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
1488 row_major_tag>,
1489 column_major_tag,
1490 typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
1491 column_major_tag>,
1492 row_major_tag,
1493 typename E::orientation_category>::type>::type orientation_category;
1494 typedef typename E::storage_category storage_category;
1495
1496 // Construction and destruction
1497 BOOST_UBLAS_INLINE
1498 // matrix_unary2 may be used as mutable expression -
1499 // this is the only non const expression constructor
1500 explicit matrix_unary2 (expression_type &e):
1501 e_ (e) {}
1502
1503 // Accessors
1504 BOOST_UBLAS_INLINE
1505 size_type size1 () const {
1506 return e_.size2 ();
1507 }
1508 BOOST_UBLAS_INLINE
1509 size_type size2 () const {
1510 return e_.size1 ();
1511 }
1512
1513public:
1514 // Expression accessors
1515 BOOST_UBLAS_INLINE
1516 const expression_closure_type &expression () const {
1517 return e_;
1518 }
1519
1520public:
1521 // Element access
1522 BOOST_UBLAS_INLINE
1523 const_reference operator () (size_type i, size_type j) const {
1524 return functor_type::apply (e_ (j, i));
1525 }
1526 BOOST_UBLAS_INLINE
1527 reference operator () (size_type i, size_type j) {
1528 BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
1529 return e_ (j, i);
1530 }
1531
1532 // Element access
1533 BOOST_UBLAS_INLINE
1534 const_reference operator () (size_type i) const {
1535 return functor_type::apply (e_ (i));
1536 }
1537 BOOST_UBLAS_INLINE
1538 reference operator () (size_type i) {
1539 BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
1540 return e_ (i);
1541 }
1542
1543 // Closure comparison
1544 BOOST_UBLAS_INLINE
1545 bool same_closure (const matrix_unary2 &mu2) const {
1546 return (*this).expression ().same_closure (mu2.expression ());
1547 }
1548
1549 // Iterator types
1550private:
1551 typedef typename E::const_iterator1 const_subiterator2_type;
1552 typedef typename E::const_iterator2 const_subiterator1_type;
1553 typedef const value_type *const_pointer;
1554
1555public:
1556#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1557 typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
1558 typedef const_iterator1 iterator1;
1559 typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
1560 typedef const_iterator2 iterator2;
1561#else
1562 class const_iterator1;
1563 typedef const_iterator1 iterator1;
1564 class const_iterator2;
1565 typedef const_iterator2 iterator2;
1566#endif
1567 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1568 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1569
1570 // Element lookup
1571 BOOST_UBLAS_INLINE
1572 const_iterator1 find1 (int rank, size_type i, size_type j) const {
1573 const_subiterator1_type it1 (e_.find2 (rank, j, i));
1574#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1575 return const_iterator1 (*this, it1.index2 (), it1.index1 ());
1576#else
1577 return const_iterator1 (*this, it1);
1578#endif
1579 }
1580 BOOST_UBLAS_INLINE
1581 const_iterator2 find2 (int rank, size_type i, size_type j) const {
1582 const_subiterator2_type it2 (e_.find1 (rank, j, i));
1583#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1584 return const_iterator2 (*this, it2.index2 (), it2.index1 ());
1585#else
1586 return const_iterator2 (*this, it2);
1587#endif
1588 }
1589
1590 // Iterators enhance the iterators of the referenced expression
1591 // with the unary functor.
1592
1593#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1594 class const_iterator1:
1595 public container_const_reference<matrix_unary2>,
1596 public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
1597 iterator_base<const_iterator1, value_type>::type {
1598 public:
1599 typedef typename E::const_iterator2::iterator_category iterator_category;
1600 typedef typename matrix_unary2::difference_type difference_type;
1601 typedef typename matrix_unary2::value_type value_type;
1602 typedef typename matrix_unary2::const_reference reference;
1603 typedef typename matrix_unary2::const_pointer pointer;
1604
1605 typedef const_iterator2 dual_iterator_type;
1606 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1607
1608 // Construction and destruction
1609 BOOST_UBLAS_INLINE
1610 const_iterator1 ():
1611 container_const_reference<self_type> (), it_ () {}
1612 BOOST_UBLAS_INLINE
1613 const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
1614 container_const_reference<self_type> (mu), it_ (it) {}
1615
1616 // Arithmetic
1617 BOOST_UBLAS_INLINE
1618 const_iterator1 &operator ++ () {
1619 ++ it_;
1620 return *this;
1621 }
1622 BOOST_UBLAS_INLINE
1623 const_iterator1 &operator -- () {
1624 -- it_;
1625 return *this;
1626 }
1627 BOOST_UBLAS_INLINE
1628 const_iterator1 &operator += (difference_type n) {
1629 it_ += n;
1630 return *this;
1631 }
1632 BOOST_UBLAS_INLINE
1633 const_iterator1 &operator -= (difference_type n) {
1634 it_ -= n;
1635 return *this;
1636 }
1637 BOOST_UBLAS_INLINE
1638 difference_type operator - (const const_iterator1 &it) const {
1639 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1640 return it_ - it.it_;
1641 }
1642
1643 // Dereference
1644 BOOST_UBLAS_INLINE
1645 const_reference operator * () const {
1646 return functor_type::apply (*it_);
1647 }
1648 BOOST_UBLAS_INLINE
1649 const_reference operator [] (difference_type n) const {
1650 return *(*this + n);
1651 }
1652
1653#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1654 BOOST_UBLAS_INLINE
1655#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1656 typename self_type::
1657#endif
1658 const_iterator2 begin () const {
1659 return (*this) ().find2 (1, index1 (), 0);
1660 }
1661 BOOST_UBLAS_INLINE
1662#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1663 typename self_type::
1664#endif
1665 const_iterator2 cbegin () const {
1666 return begin ();
1667 }
1668 BOOST_UBLAS_INLINE
1669#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1670 typename self_type::
1671#endif
1672 const_iterator2 end () const {
1673 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1674 }
1675 BOOST_UBLAS_INLINE
1676#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1677 typename self_type::
1678#endif
1679 const_iterator2 cend () const {
1680 return end ();
1681 }
1682 BOOST_UBLAS_INLINE
1683#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1684 typename self_type::
1685#endif
1686 const_reverse_iterator2 rbegin () const {
1687 return const_reverse_iterator2 (end ());
1688 }
1689 BOOST_UBLAS_INLINE
1690#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1691 typename self_type::
1692#endif
1693 const_reverse_iterator2 crbegin () const {
1694 return rbegin ();
1695 }
1696 BOOST_UBLAS_INLINE
1697#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1698 typename self_type::
1699#endif
1700 const_reverse_iterator2 rend () const {
1701 return const_reverse_iterator2 (begin ());
1702 }
1703 BOOST_UBLAS_INLINE
1704#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1705 typename self_type::
1706#endif
1707 const_reverse_iterator2 crend () const {
1708 return rend ();
1709 }
1710#endif
1711
1712 // Indices
1713 BOOST_UBLAS_INLINE
1714 size_type index1 () const {
1715 return it_.index2 ();
1716 }
1717 BOOST_UBLAS_INLINE
1718 size_type index2 () const {
1719 return it_.index1 ();
1720 }
1721
1722 // Assignment
1723 BOOST_UBLAS_INLINE
1724 const_iterator1 &operator = (const const_iterator1 &it) {
1725 container_const_reference<self_type>::assign (&it ());
1726 it_ = it.it_;
1727 return *this;
1728 }
1729
1730 // Comparison
1731 BOOST_UBLAS_INLINE
1732 bool operator == (const const_iterator1 &it) const {
1733 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1734 return it_ == it.it_;
1735 }
1736 BOOST_UBLAS_INLINE
1737 bool operator < (const const_iterator1 &it) const {
1738 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1739 return it_ < it.it_;
1740 }
1741
1742 private:
1743 const_subiterator1_type it_;
1744 };
1745#endif
1746
1747 BOOST_UBLAS_INLINE
1748 const_iterator1 begin1 () const {
1749 return find1 (rank: 0, i: 0, j: 0);
1750 }
1751 BOOST_UBLAS_INLINE
1752 const_iterator1 cbegin1 () const {
1753 return begin1 ();
1754 }
1755 BOOST_UBLAS_INLINE
1756 const_iterator1 end1 () const {
1757 return find1 (rank: 0, i: size1 (), j: 0);
1758 }
1759 BOOST_UBLAS_INLINE
1760 const_iterator1 cend1 () const {
1761 return end1 ();
1762 }
1763
1764#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1765 class const_iterator2:
1766 public container_const_reference<matrix_unary2>,
1767 public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
1768 iterator_base<const_iterator2, value_type>::type {
1769 public:
1770 typedef typename E::const_iterator1::iterator_category iterator_category;
1771 typedef typename matrix_unary2::difference_type difference_type;
1772 typedef typename matrix_unary2::value_type value_type;
1773 typedef typename matrix_unary2::const_reference reference;
1774 typedef typename matrix_unary2::const_pointer pointer;
1775
1776 typedef const_iterator1 dual_iterator_type;
1777 typedef const_reverse_iterator1 dual_reverse_iterator_type;
1778
1779 // Construction and destruction
1780 BOOST_UBLAS_INLINE
1781 const_iterator2 ():
1782 container_const_reference<self_type> (), it_ () {}
1783 BOOST_UBLAS_INLINE
1784 const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
1785 container_const_reference<self_type> (mu), it_ (it) {}
1786
1787 // Arithmetic
1788 BOOST_UBLAS_INLINE
1789 const_iterator2 &operator ++ () {
1790 ++ it_;
1791 return *this;
1792 }
1793 BOOST_UBLAS_INLINE
1794 const_iterator2 &operator -- () {
1795 -- it_;
1796 return *this;
1797 }
1798 BOOST_UBLAS_INLINE
1799 const_iterator2 &operator += (difference_type n) {
1800 it_ += n;
1801 return *this;
1802 }
1803 BOOST_UBLAS_INLINE
1804 const_iterator2 &operator -= (difference_type n) {
1805 it_ -= n;
1806 return *this;
1807 }
1808 BOOST_UBLAS_INLINE
1809 difference_type operator - (const const_iterator2 &it) const {
1810 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1811 return it_ - it.it_;
1812 }
1813
1814 // Dereference
1815 BOOST_UBLAS_INLINE
1816 const_reference operator * () const {
1817 return functor_type::apply (*it_);
1818 }
1819 BOOST_UBLAS_INLINE
1820 const_reference operator [] (difference_type n) const {
1821 return *(*this + n);
1822 }
1823
1824#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1825 BOOST_UBLAS_INLINE
1826#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1827 typename self_type::
1828#endif
1829 const_iterator1 begin () const {
1830 return (*this) ().find1 (1, 0, index2 ());
1831 }
1832 BOOST_UBLAS_INLINE
1833#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1834 typename self_type::
1835#endif
1836 const_iterator1 cbegin () const {
1837 return begin ();
1838 }
1839 BOOST_UBLAS_INLINE
1840#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1841 typename self_type::
1842#endif
1843 const_iterator1 end () const {
1844 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1845 }
1846 BOOST_UBLAS_INLINE
1847#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1848 typename self_type::
1849#endif
1850 const_iterator1 cend () const {
1851 return end ();
1852 }
1853 BOOST_UBLAS_INLINE
1854#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1855 typename self_type::
1856#endif
1857 const_reverse_iterator1 rbegin () const {
1858 return const_reverse_iterator1 (end ());
1859 }
1860 BOOST_UBLAS_INLINE
1861#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1862 typename self_type::
1863#endif
1864 const_reverse_iterator1 crbegin () const {
1865 return rbegin ();
1866 }
1867 BOOST_UBLAS_INLINE
1868#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1869 typename self_type::
1870#endif
1871 const_reverse_iterator1 rend () const {
1872 return const_reverse_iterator1 (begin ());
1873 }
1874 BOOST_UBLAS_INLINE
1875#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1876 typename self_type::
1877#endif
1878 const_reverse_iterator1 crend () const {
1879 return rend ();
1880 }
1881#endif
1882
1883 // Indices
1884 BOOST_UBLAS_INLINE
1885 size_type index1 () const {
1886 return it_.index2 ();
1887 }
1888 BOOST_UBLAS_INLINE
1889 size_type index2 () const {
1890 return it_.index1 ();
1891 }
1892
1893 // Assignment
1894 BOOST_UBLAS_INLINE
1895 const_iterator2 &operator = (const const_iterator2 &it) {
1896 container_const_reference<self_type>::assign (&it ());
1897 it_ = it.it_;
1898 return *this;
1899 }
1900
1901 // Comparison
1902 BOOST_UBLAS_INLINE
1903 bool operator == (const const_iterator2 &it) const {
1904 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1905 return it_ == it.it_;
1906 }
1907 BOOST_UBLAS_INLINE
1908 bool operator < (const const_iterator2 &it) const {
1909 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1910 return it_ < it.it_;
1911 }
1912
1913 private:
1914 const_subiterator2_type it_;
1915 };
1916#endif
1917
1918 BOOST_UBLAS_INLINE
1919 const_iterator2 begin2 () const {
1920 return find2 (rank: 0, i: 0, j: 0);
1921 }
1922 BOOST_UBLAS_INLINE
1923 const_iterator2 cbegin2 () const {
1924 return begin2 ();
1925 }
1926 BOOST_UBLAS_INLINE
1927 const_iterator2 end2 () const {
1928 return find2 (rank: 0, i: 0, j: size2 ());
1929 }
1930 BOOST_UBLAS_INLINE
1931 const_iterator2 cend2 () const {
1932 return end2 ();
1933 }
1934
1935 // Reverse iterators
1936
1937 BOOST_UBLAS_INLINE
1938 const_reverse_iterator1 rbegin1 () const {
1939 return const_reverse_iterator1 (end1 ());
1940 }
1941 BOOST_UBLAS_INLINE
1942 const_reverse_iterator1 crbegin1 () const {
1943 return rbegin1 ();
1944 }
1945 BOOST_UBLAS_INLINE
1946 const_reverse_iterator1 rend1 () const {
1947 return const_reverse_iterator1 (begin1 ());
1948 }
1949 BOOST_UBLAS_INLINE
1950 const_reverse_iterator1 crend1 () const {
1951 return rend1 ();
1952 }
1953
1954 BOOST_UBLAS_INLINE
1955 const_reverse_iterator2 rbegin2 () const {
1956 return const_reverse_iterator2 (end2 ());
1957 }
1958 BOOST_UBLAS_INLINE
1959 const_reverse_iterator2 crbegin2 () const {
1960 return rbegin2 ();
1961 }
1962 BOOST_UBLAS_INLINE
1963 const_reverse_iterator2 rend2 () const {
1964 return const_reverse_iterator2 (begin2 ());
1965 }
1966 BOOST_UBLAS_INLINE
1967 const_reverse_iterator2 crend2 () const {
1968 return rend2 ();
1969 }
1970
1971private:
1972 expression_closure_type e_;
1973};
1974
1975template<class E, class F>
1976struct matrix_unary2_traits {
1977 typedef matrix_unary2<E, F> expression_type;
1978#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1979 typedef expression_type result_type;
1980#else
1981 typedef typename E::matrix_temporary_type result_type;
1982#endif
1983};
1984
1985// (trans m) [i] [j] = m [j] [i]
1986template<class E>
1987BOOST_UBLAS_INLINE
1988typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::result_type
1989trans (const matrix_expression<E> &e) {
1990 typedef typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
1991 return expression_type (e ());
1992}
1993template<class E>
1994BOOST_UBLAS_INLINE
1995typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::result_type
1996trans (matrix_expression<E> &e) {
1997 typedef typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
1998 return expression_type (e ());
1999}
2000
2001// (herm m) [i] [j] = conj (m [j] [i])
2002template<class E>
2003BOOST_UBLAS_INLINE
2004typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::result_type
2005herm (const matrix_expression<E> &e) {
2006 typedef typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
2007 return expression_type (e ());
2008}
2009
2010template<class E1, class E2, class F>
2011class matrix_binary:
2012 public matrix_expression<matrix_binary<E1, E2, F> > {
2013
2014 typedef E1 expression1_type;
2015 typedef E2 expression2_type;
2016 typedef F functor_type;
2017public:
2018 typedef typename E1::const_closure_type expression1_closure_type;
2019 typedef typename E2::const_closure_type expression2_closure_type;
2020private:
2021 typedef matrix_binary<E1, E2, F> self_type;
2022public:
2023#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2024 using matrix_expression<self_type>::operator ();
2025#endif
2026 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
2027 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
2028 typedef typename F::result_type value_type;
2029 typedef value_type const_reference;
2030 typedef const_reference reference;
2031 typedef const self_type const_closure_type;
2032 typedef const_closure_type closure_type;
2033 typedef unknown_orientation_tag orientation_category;
2034 typedef unknown_storage_tag storage_category;
2035
2036 // Construction and destruction
2037 BOOST_UBLAS_INLINE
2038 matrix_binary (const E1 &e1, const E2 &e2):
2039 e1_ (e1), e2_ (e2) {}
2040
2041 // Accessors
2042 BOOST_UBLAS_INLINE
2043 size_type size1 () const {
2044 return BOOST_UBLAS_SAME (e1_.size1 (), e2_.size1 ());
2045 }
2046 BOOST_UBLAS_INLINE
2047 size_type size2 () const {
2048 return BOOST_UBLAS_SAME (e1_.size2 (), e2_.size2 ());
2049 }
2050
2051public:
2052 // Expression accessors
2053 BOOST_UBLAS_INLINE
2054 const expression1_closure_type &expression1 () const {
2055 return e1_;
2056 }
2057 BOOST_UBLAS_INLINE
2058 const expression2_closure_type &expression2 () const {
2059 return e2_;
2060 }
2061
2062public:
2063 // Element access
2064 BOOST_UBLAS_INLINE
2065 const_reference operator () (size_type i, size_type j) const {
2066 return functor_type::apply (e1_ (i, j), e2_ (i, j));
2067 }
2068
2069 // Element access
2070 BOOST_UBLAS_INLINE
2071 const_reference operator () (size_type i) const {
2072 return functor_type::apply (e1_ (i), e2_ (i));
2073 }
2074
2075 // Closure comparison
2076 BOOST_UBLAS_INLINE
2077 bool same_closure (const matrix_binary &mb) const {
2078 return (*this).expression1 ().same_closure (mb.expression1 ()) &&
2079 (*this).expression2 ().same_closure (mb.expression2 ());
2080 }
2081
2082 // Iterator types
2083private:
2084 typedef typename E1::const_iterator1 const_iterator11_type;
2085 typedef typename E1::const_iterator2 const_iterator12_type;
2086 typedef typename E2::const_iterator1 const_iterator21_type;
2087 typedef typename E2::const_iterator2 const_iterator22_type;
2088 typedef const value_type *const_pointer;
2089
2090public:
2091#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2092 typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
2093 typename const_iterator21_type::iterator_category>::iterator_category iterator_category1;
2094 typedef indexed_const_iterator1<const_closure_type, iterator_category1> const_iterator1;
2095 typedef const_iterator1 iterator1;
2096 typedef typename iterator_restrict_traits<typename const_iterator12_type::iterator_category,
2097 typename const_iterator22_type::iterator_category>::iterator_category iterator_category2;
2098 typedef indexed_const_iterator2<const_closure_type, iterator_category2> const_iterator2;
2099 typedef const_iterator2 iterator2;
2100#else
2101 class const_iterator1;
2102 typedef const_iterator1 iterator1;
2103 class const_iterator2;
2104 typedef const_iterator2 iterator2;
2105#endif
2106 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2107 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2108
2109 // Element lookup
2110 BOOST_UBLAS_INLINE
2111 const_iterator1 find1 (int rank, size_type i, size_type j) const {
2112 const_iterator11_type it11 (e1_.find1 (rank, i, j));
2113 const_iterator11_type it11_end (e1_.find1 (rank, size1 (), j));
2114 const_iterator21_type it21 (e2_.find1 (rank, i, j));
2115 const_iterator21_type it21_end (e2_.find1 (rank, size1 (), j));
2116 BOOST_UBLAS_CHECK (rank == 0 || it11 == it11_end || it11.index2 () == j, internal_logic ())
2117 BOOST_UBLAS_CHECK (rank == 0 || it21 == it21_end || it21.index2 () == j, internal_logic ())
2118 i = (std::min) (it11 != it11_end ? it11.index1 () : size1 (),
2119 it21 != it21_end ? it21.index1 () : size1 ());
2120#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2121 return const_iterator1 (*this, i, j);
2122#else
2123 return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end);
2124#endif
2125 }
2126 BOOST_UBLAS_INLINE
2127 const_iterator2 find2 (int rank, size_type i, size_type j) const {
2128 const_iterator12_type it12 (e1_.find2 (rank, i, j));
2129 const_iterator12_type it12_end (e1_.find2 (rank, i, size2 ()));
2130 const_iterator22_type it22 (e2_.find2 (rank, i, j));
2131 const_iterator22_type it22_end (e2_.find2 (rank, i, size2 ()));
2132 BOOST_UBLAS_CHECK (rank == 0 || it12 == it12_end || it12.index1 () == i, internal_logic ())
2133 BOOST_UBLAS_CHECK (rank == 0 || it22 == it22_end || it22.index1 () == i, internal_logic ())
2134 j = (std::min) (it12 != it12_end ? it12.index2 () : size2 (),
2135 it22 != it22_end ? it22.index2 () : size2 ());
2136#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2137 return const_iterator2 (*this, i, j);
2138#else
2139 return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end);
2140#endif
2141 }
2142
2143 // Iterators enhance the iterators of the referenced expression
2144 // with the binary functor.
2145
2146#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2147 class const_iterator1:
2148 public container_const_reference<matrix_binary>,
2149 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
2150 typename E2::const_iterator1::iterator_category>::iterator_category>::template
2151 iterator_base<const_iterator1, value_type>::type {
2152 public:
2153 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
2154 typename E2::const_iterator1::iterator_category>::iterator_category iterator_category;
2155 typedef typename matrix_binary::difference_type difference_type;
2156 typedef typename matrix_binary::value_type value_type;
2157 typedef typename matrix_binary::const_reference reference;
2158 typedef typename matrix_binary::const_pointer pointer;
2159
2160 typedef const_iterator2 dual_iterator_type;
2161 typedef const_reverse_iterator2 dual_reverse_iterator_type;
2162
2163 // Construction and destruction
2164 BOOST_UBLAS_INLINE
2165 const_iterator1 ():
2166 container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
2167 BOOST_UBLAS_INLINE
2168 const_iterator1 (const self_type &mb, size_type i, size_type j,
2169 const const_iterator11_type &it1, const const_iterator11_type &it1_end,
2170 const const_iterator21_type &it2, const const_iterator21_type &it2_end):
2171 container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
2172
2173 private:
2174 // Dense specializations
2175 BOOST_UBLAS_INLINE
2176 void increment (dense_random_access_iterator_tag) {
2177 ++ i_; ++ it1_; ++ it2_;
2178 }
2179 BOOST_UBLAS_INLINE
2180 void decrement (dense_random_access_iterator_tag) {
2181 -- i_; -- it1_; -- it2_;
2182 }
2183 BOOST_UBLAS_INLINE
2184 void increment (dense_random_access_iterator_tag, difference_type n) {
2185 i_ += n; it1_ += n; it2_ += n;
2186 }
2187 BOOST_UBLAS_INLINE
2188 void decrement (dense_random_access_iterator_tag, difference_type n) {
2189 i_ -= n; it1_ -= n; it2_ -= n;
2190 }
2191 BOOST_UBLAS_INLINE
2192 value_type dereference (dense_random_access_iterator_tag) const {
2193 return functor_type::apply (*it1_, *it2_);
2194 }
2195
2196 // Packed specializations
2197 BOOST_UBLAS_INLINE
2198 void increment (packed_random_access_iterator_tag) {
2199 if (it1_ != it1_end_)
2200 if (it1_.index1 () <= i_)
2201 ++ it1_;
2202 if (it2_ != it2_end_)
2203 if (it2_.index1 () <= i_)
2204 ++ it2_;
2205 ++ i_;
2206 }
2207 BOOST_UBLAS_INLINE
2208 void decrement (packed_random_access_iterator_tag) {
2209 if (it1_ != it1_end_)
2210 if (i_ <= it1_.index1 ())
2211 -- it1_;
2212 if (it2_ != it2_end_)
2213 if (i_ <= it2_.index1 ())
2214 -- it2_;
2215 -- i_;
2216 }
2217 BOOST_UBLAS_INLINE
2218 void increment (packed_random_access_iterator_tag, difference_type n) {
2219 while (n > 0) {
2220 increment (packed_random_access_iterator_tag ());
2221 --n;
2222 }
2223 while (n < 0) {
2224 decrement (packed_random_access_iterator_tag ());
2225 ++n;
2226 }
2227 }
2228 BOOST_UBLAS_INLINE
2229 void decrement (packed_random_access_iterator_tag, difference_type n) {
2230 while (n > 0) {
2231 decrement (packed_random_access_iterator_tag ());
2232 --n;
2233 }
2234 while (n < 0) {
2235 increment (packed_random_access_iterator_tag ());
2236 ++n;
2237 }
2238 }
2239 BOOST_UBLAS_INLINE
2240 value_type dereference (packed_random_access_iterator_tag) const {
2241 typename E1::value_type t1 = typename E1::value_type/*zero*/();
2242 if (it1_ != it1_end_) {
2243 BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
2244 if (it1_.index1 () == i_)
2245 t1 = *it1_;
2246 }
2247 typename E2::value_type t2 = typename E2::value_type/*zero*/();
2248 if (it2_ != it2_end_) {
2249 BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
2250 if (it2_.index1 () == i_)
2251 t2 = *it2_;
2252 }
2253 return functor_type::apply (t1, t2);
2254 }
2255
2256 // Sparse specializations
2257 BOOST_UBLAS_INLINE
2258 void increment (sparse_bidirectional_iterator_tag) {
2259 size_type index1 = (*this) ().size1 ();
2260 if (it1_ != it1_end_) {
2261 if (it1_.index1 () <= i_)
2262 ++ it1_;
2263 if (it1_ != it1_end_)
2264 index1 = it1_.index1 ();
2265 }
2266 size_type index2 = (*this) ().size1 ();
2267 if (it2_ != it2_end_)
2268 if (it2_.index1 () <= i_)
2269 ++ it2_;
2270 if (it2_ != it2_end_) {
2271 index2 = it2_.index1 ();
2272 }
2273 i_ = (std::min) (index1, index2);
2274 }
2275 BOOST_UBLAS_INLINE
2276 void decrement (sparse_bidirectional_iterator_tag) {
2277 size_type index1 = (*this) ().size1 ();
2278 if (it1_ != it1_end_) {
2279 if (i_ <= it1_.index1 ())
2280 -- it1_;
2281 if (it1_ != it1_end_)
2282 index1 = it1_.index1 ();
2283 }
2284 size_type index2 = (*this) ().size1 ();
2285 if (it2_ != it2_end_) {
2286 if (i_ <= it2_.index1 ())
2287 -- it2_;
2288 if (it2_ != it2_end_)
2289 index2 = it2_.index1 ();
2290 }
2291 i_ = (std::max) (index1, index2);
2292 }
2293 BOOST_UBLAS_INLINE
2294 void increment (sparse_bidirectional_iterator_tag, difference_type n) {
2295 while (n > 0) {
2296 increment (sparse_bidirectional_iterator_tag ());
2297 --n;
2298 }
2299 while (n < 0) {
2300 decrement (sparse_bidirectional_iterator_tag ());
2301 ++n;
2302 }
2303 }
2304 BOOST_UBLAS_INLINE
2305 void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
2306 while (n > 0) {
2307 decrement (sparse_bidirectional_iterator_tag ());
2308 --n;
2309 }
2310 while (n < 0) {
2311 increment (sparse_bidirectional_iterator_tag ());
2312 ++n;
2313 }
2314 }
2315 BOOST_UBLAS_INLINE
2316 value_type dereference (sparse_bidirectional_iterator_tag) const {
2317 typename E1::value_type t1 = typename E1::value_type/*zero*/();
2318 if (it1_ != it1_end_) {
2319 BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
2320 if (it1_.index1 () == i_)
2321 t1 = *it1_;
2322 }
2323 typename E2::value_type t2 = typename E2::value_type/*zero*/();
2324 if (it2_ != it2_end_) {
2325 BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
2326 if (it2_.index1 () == i_)
2327 t2 = *it2_;
2328 }
2329 return functor_type::apply (t1, t2);
2330 }
2331
2332 public:
2333 // Arithmetic
2334 BOOST_UBLAS_INLINE
2335 const_iterator1 &operator ++ () {
2336 increment (iterator_category ());
2337 return *this;
2338 }
2339 BOOST_UBLAS_INLINE
2340 const_iterator1 &operator -- () {
2341 decrement (iterator_category ());
2342 return *this;
2343 }
2344 BOOST_UBLAS_INLINE
2345 const_iterator1 &operator += (difference_type n) {
2346 increment (iterator_category (), n);
2347 return *this;
2348 }
2349 BOOST_UBLAS_INLINE
2350 const_iterator1 &operator -= (difference_type n) {
2351 decrement (iterator_category (), n);
2352 return *this;
2353 }
2354 BOOST_UBLAS_INLINE
2355 difference_type operator - (const const_iterator1 &it) const {
2356 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2357 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
2358 return index1 () - it.index1 ();
2359 }
2360
2361 // Dereference
2362 BOOST_UBLAS_INLINE
2363 const_reference operator * () const {
2364 return dereference (iterator_category ());
2365 }
2366 BOOST_UBLAS_INLINE
2367 const_reference operator [] (difference_type n) const {
2368 return *(*this + n);
2369 }
2370
2371#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2372 BOOST_UBLAS_INLINE
2373#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2374 typename self_type::
2375#endif
2376 const_iterator2 begin () const {
2377 return (*this) ().find2 (1, index1 (), 0);
2378 }
2379 BOOST_UBLAS_INLINE
2380#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2381 typename self_type::
2382#endif
2383 const_iterator2 cbegin () const {
2384 return begin ();
2385 }
2386 BOOST_UBLAS_INLINE
2387#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2388 typename self_type::
2389#endif
2390 const_iterator2 end () const {
2391 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
2392 }
2393 BOOST_UBLAS_INLINE
2394#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2395 typename self_type::
2396#endif
2397 const_iterator2 cend () const {
2398 return end ();
2399 }
2400 BOOST_UBLAS_INLINE
2401#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2402 typename self_type::
2403#endif
2404 const_reverse_iterator2 rbegin () const {
2405 return const_reverse_iterator2 (end ());
2406 }
2407 BOOST_UBLAS_INLINE
2408#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2409 typename self_type::
2410#endif
2411 const_reverse_iterator2 crbegin () const {
2412 return rbegin ();
2413 }
2414 BOOST_UBLAS_INLINE
2415#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2416 typename self_type::
2417#endif
2418 const_reverse_iterator2 rend () const {
2419 return const_reverse_iterator2 (begin ());
2420 }
2421 BOOST_UBLAS_INLINE
2422#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2423 typename self_type::
2424#endif
2425 const_reverse_iterator2 crend () const {
2426 return rend ();
2427 }
2428#endif
2429
2430 // Indices
2431 BOOST_UBLAS_INLINE
2432 size_type index1 () const {
2433 return i_;
2434 }
2435 BOOST_UBLAS_INLINE
2436 size_type index2 () const {
2437 // if (it1_ != it1_end_ && it2_ != it2_end_)
2438 // return BOOST_UBLAS_SAME (it1_.index2 (), it2_.index2 ());
2439 // else
2440 return j_;
2441 }
2442
2443 // Assignment
2444 BOOST_UBLAS_INLINE
2445 const_iterator1 &operator = (const const_iterator1 &it) {
2446 container_const_reference<self_type>::assign (&it ());
2447 i_ = it.i_;
2448 j_ = it.j_;
2449 it1_ = it.it1_;
2450 it1_end_ = it.it1_end_;
2451 it2_ = it.it2_;
2452 it2_end_ = it.it2_end_;
2453 return *this;
2454 }
2455
2456 // Comparison
2457 BOOST_UBLAS_INLINE
2458 bool operator == (const const_iterator1 &it) const {
2459 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2460 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
2461 return index1 () == it.index1 ();
2462 }
2463 BOOST_UBLAS_INLINE
2464 bool operator < (const const_iterator1 &it) const {
2465 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2466 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
2467 return index1 () < it.index1 ();
2468 }
2469
2470 private:
2471 size_type i_;
2472 size_type j_;
2473 const_iterator11_type it1_;
2474 const_iterator11_type it1_end_;
2475 const_iterator21_type it2_;
2476 const_iterator21_type it2_end_;
2477 };
2478#endif
2479
2480 BOOST_UBLAS_INLINE
2481 const_iterator1 begin1 () const {
2482 return find1 (rank: 0, i: 0, j: 0);
2483 }
2484 BOOST_UBLAS_INLINE
2485 const_iterator1 cbegin1 () const {
2486 return begin1 ();
2487 }
2488 BOOST_UBLAS_INLINE
2489 const_iterator1 end1 () const {
2490 return find1 (rank: 0, i: size1 (), j: 0);
2491 }
2492 BOOST_UBLAS_INLINE
2493 const_iterator1 cend1 () const {
2494 return end1 ();
2495 }
2496
2497#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2498 class const_iterator2:
2499 public container_const_reference<matrix_binary>,
2500 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
2501 typename E2::const_iterator2::iterator_category>::iterator_category>::template
2502 iterator_base<const_iterator2, value_type>::type {
2503 public:
2504 typedef typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
2505 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
2506 typedef typename matrix_binary::difference_type difference_type;
2507 typedef typename matrix_binary::value_type value_type;
2508 typedef typename matrix_binary::const_reference reference;
2509 typedef typename matrix_binary::const_pointer pointer;
2510
2511 typedef const_iterator1 dual_iterator_type;
2512 typedef const_reverse_iterator1 dual_reverse_iterator_type;
2513
2514 // Construction and destruction
2515 BOOST_UBLAS_INLINE
2516 const_iterator2 ():
2517 container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
2518 BOOST_UBLAS_INLINE
2519 const_iterator2 (const self_type &mb, size_type i, size_type j,
2520 const const_iterator12_type &it1, const const_iterator12_type &it1_end,
2521 const const_iterator22_type &it2, const const_iterator22_type &it2_end):
2522 container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
2523
2524 private:
2525 // Dense access specializations
2526 BOOST_UBLAS_INLINE
2527 void increment (dense_random_access_iterator_tag) {
2528 ++ j_; ++ it1_; ++ it2_;
2529 }
2530 BOOST_UBLAS_INLINE
2531 void decrement (dense_random_access_iterator_tag) {
2532 -- j_; -- it1_; -- it2_;
2533 }
2534 BOOST_UBLAS_INLINE
2535 void increment (dense_random_access_iterator_tag, difference_type n) {
2536 j_ += n; it1_ += n; it2_ += n;
2537 }
2538 BOOST_UBLAS_INLINE
2539 void decrement (dense_random_access_iterator_tag, difference_type n) {
2540 j_ -= n; it1_ -= n; it2_ -= n;
2541 }
2542 BOOST_UBLAS_INLINE
2543 value_type dereference (dense_random_access_iterator_tag) const {
2544 return functor_type::apply (*it1_, *it2_);
2545 }
2546
2547 // Packed specializations
2548 BOOST_UBLAS_INLINE
2549 void increment (packed_random_access_iterator_tag) {
2550 if (it1_ != it1_end_)
2551 if (it1_.index2 () <= j_)
2552 ++ it1_;
2553 if (it2_ != it2_end_)
2554 if (it2_.index2 () <= j_)
2555 ++ it2_;
2556 ++ j_;
2557 }
2558 BOOST_UBLAS_INLINE
2559 void decrement (packed_random_access_iterator_tag) {
2560 if (it1_ != it1_end_)
2561 if (j_ <= it1_.index2 ())
2562 -- it1_;
2563 if (it2_ != it2_end_)
2564 if (j_ <= it2_.index2 ())
2565 -- it2_;
2566 -- j_;
2567 }
2568 BOOST_UBLAS_INLINE
2569 void increment (packed_random_access_iterator_tag, difference_type n) {
2570 while (n > 0) {
2571 increment (packed_random_access_iterator_tag ());
2572 --n;
2573 }
2574 while (n < 0) {
2575 decrement (packed_random_access_iterator_tag ());
2576 ++n;
2577 }
2578 }
2579 BOOST_UBLAS_INLINE
2580 void decrement (packed_random_access_iterator_tag, difference_type n) {
2581 while (n > 0) {
2582 decrement (packed_random_access_iterator_tag ());
2583 --n;
2584 }
2585 while (n < 0) {
2586 increment (packed_random_access_iterator_tag ());
2587 ++n;
2588 }
2589 }
2590 BOOST_UBLAS_INLINE
2591 value_type dereference (packed_random_access_iterator_tag) const {
2592 typename E1::value_type t1 = typename E1::value_type/*zero*/();
2593 if (it1_ != it1_end_) {
2594 BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
2595 if (it1_.index2 () == j_)
2596 t1 = *it1_;
2597 }
2598 typename E2::value_type t2 = typename E2::value_type/*zero*/();
2599 if (it2_ != it2_end_) {
2600 BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
2601 if (it2_.index2 () == j_)
2602 t2 = *it2_;
2603 }
2604 return functor_type::apply (t1, t2);
2605 }
2606
2607 // Sparse specializations
2608 BOOST_UBLAS_INLINE
2609 void increment (sparse_bidirectional_iterator_tag) {
2610 size_type index1 = (*this) ().size2 ();
2611 if (it1_ != it1_end_) {
2612 if (it1_.index2 () <= j_)
2613 ++ it1_;
2614 if (it1_ != it1_end_)
2615 index1 = it1_.index2 ();
2616 }
2617 size_type index2 = (*this) ().size2 ();
2618 if (it2_ != it2_end_) {
2619 if (it2_.index2 () <= j_)
2620 ++ it2_;
2621 if (it2_ != it2_end_)
2622 index2 = it2_.index2 ();
2623 }
2624 j_ = (std::min) (index1, index2);
2625 }
2626 BOOST_UBLAS_INLINE
2627 void decrement (sparse_bidirectional_iterator_tag) {
2628 size_type index1 = (*this) ().size2 ();
2629 if (it1_ != it1_end_) {
2630 if (j_ <= it1_.index2 ())
2631 -- it1_;
2632 if (it1_ != it1_end_)
2633 index1 = it1_.index2 ();
2634 }
2635 size_type index2 = (*this) ().size2 ();
2636 if (it2_ != it2_end_) {
2637 if (j_ <= it2_.index2 ())
2638 -- it2_;
2639 if (it2_ != it2_end_)
2640 index2 = it2_.index2 ();
2641 }
2642 j_ = (std::max) (index1, index2);
2643 }
2644 BOOST_UBLAS_INLINE
2645 void increment (sparse_bidirectional_iterator_tag, difference_type n) {
2646 while (n > 0) {
2647 increment (sparse_bidirectional_iterator_tag ());
2648 --n;
2649 }
2650 while (n < 0) {
2651 decrement (sparse_bidirectional_iterator_tag ());
2652 ++n;
2653 }
2654 }
2655 BOOST_UBLAS_INLINE
2656 void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
2657 while (n > 0) {
2658 decrement (sparse_bidirectional_iterator_tag ());
2659 --n;
2660 }
2661 while (n < 0) {
2662 increment (sparse_bidirectional_iterator_tag ());
2663 ++n;
2664 }
2665 }
2666 BOOST_UBLAS_INLINE
2667 value_type dereference (sparse_bidirectional_iterator_tag) const {
2668 typename E1::value_type t1 = typename E1::value_type/*zero*/();
2669 if (it1_ != it1_end_) {
2670 BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
2671 if (it1_.index2 () == j_)
2672 t1 = *it1_;
2673 }
2674 typename E2::value_type t2 = typename E2::value_type/*zero*/();
2675 if (it2_ != it2_end_) {
2676 BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
2677 if (it2_.index2 () == j_)
2678 t2 = *it2_;
2679 }
2680 return functor_type::apply (t1, t2);
2681 }
2682
2683 public:
2684 // Arithmetic
2685 BOOST_UBLAS_INLINE
2686 const_iterator2 &operator ++ () {
2687 increment (iterator_category ());
2688 return *this;
2689 }
2690 BOOST_UBLAS_INLINE
2691 const_iterator2 &operator -- () {
2692 decrement (iterator_category ());
2693 return *this;
2694 }
2695 BOOST_UBLAS_INLINE
2696 const_iterator2 &operator += (difference_type n) {
2697 increment (iterator_category (), n);
2698 return *this;
2699 }
2700 BOOST_UBLAS_INLINE
2701 const_iterator2 &operator -= (difference_type n) {
2702 decrement (iterator_category (), n);
2703 return *this;
2704 }
2705 BOOST_UBLAS_INLINE
2706 difference_type operator - (const const_iterator2 &it) const {
2707 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2708 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
2709 return index2 () - it.index2 ();
2710 }
2711
2712 // Dereference
2713 BOOST_UBLAS_INLINE
2714 const_reference operator * () const {
2715 return dereference (iterator_category ());
2716 }
2717 BOOST_UBLAS_INLINE
2718 const_reference operator [] (difference_type n) const {
2719 return *(*this + n);
2720 }
2721
2722#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2723 BOOST_UBLAS_INLINE
2724#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2725 typename self_type::
2726#endif
2727 const_iterator1 begin () const {
2728 return (*this) ().find1 (1, 0, index2 ());
2729 }
2730 BOOST_UBLAS_INLINE
2731#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2732 typename self_type::
2733#endif
2734 const_iterator1 cbegin () const {
2735 return begin ();
2736 }
2737 BOOST_UBLAS_INLINE
2738#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2739 typename self_type::
2740#endif
2741 const_iterator1 end () const {
2742 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2743 }
2744 BOOST_UBLAS_INLINE
2745#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2746 typename self_type::
2747#endif
2748 const_iterator1 cend () const {
2749 return end ();
2750 }
2751 BOOST_UBLAS_INLINE
2752#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2753 typename self_type::
2754#endif
2755 const_reverse_iterator1 rbegin () const {
2756 return const_reverse_iterator1 (end ());
2757 }
2758 BOOST_UBLAS_INLINE
2759#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2760 typename self_type::
2761#endif
2762 const_reverse_iterator1 crbegin () const {
2763 return rbegin ();
2764 }
2765 BOOST_UBLAS_INLINE
2766#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2767 typename self_type::
2768#endif
2769 const_reverse_iterator1 rend () const {
2770 return const_reverse_iterator1 (begin ());
2771 }
2772 BOOST_UBLAS_INLINE
2773#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2774 typename self_type::
2775#endif
2776 const_reverse_iterator1 crend () const {
2777 return rend ();
2778 }
2779#endif
2780
2781 // Indices
2782 BOOST_UBLAS_INLINE
2783 size_type index1 () const {
2784 // if (it1_ != it1_end_ && it2_ != it2_end_)
2785 // return BOOST_UBLAS_SAME (it1_.index1 (), it2_.index1 ());
2786 // else
2787 return i_;
2788 }
2789 BOOST_UBLAS_INLINE
2790 size_type index2 () const {
2791 return j_;
2792 }
2793
2794 // Assignment
2795 BOOST_UBLAS_INLINE
2796 const_iterator2 &operator = (const const_iterator2 &it) {
2797 container_const_reference<self_type>::assign (&it ());
2798 i_ = it.i_;
2799 j_ = it.j_;
2800 it1_ = it.it1_;
2801 it1_end_ = it.it1_end_;
2802 it2_ = it.it2_;
2803 it2_end_ = it.it2_end_;
2804 return *this;
2805 }
2806
2807 // Comparison
2808 BOOST_UBLAS_INLINE
2809 bool operator == (const const_iterator2 &it) const {
2810 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2811 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
2812 return index2 () == it.index2 ();
2813 }
2814 BOOST_UBLAS_INLINE
2815 bool operator < (const const_iterator2 &it) const {
2816 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2817 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
2818 return index2 () < it.index2 ();
2819 }
2820
2821 private:
2822 size_type i_;
2823 size_type j_;
2824 const_iterator12_type it1_;
2825 const_iterator12_type it1_end_;
2826 const_iterator22_type it2_;
2827 const_iterator22_type it2_end_;
2828 };
2829#endif
2830
2831 BOOST_UBLAS_INLINE
2832 const_iterator2 begin2 () const {
2833 return find2 (rank: 0, i: 0, j: 0);
2834 }
2835 BOOST_UBLAS_INLINE
2836 const_iterator2 cbegin2 () const {
2837 return begin2 ();
2838 }
2839 BOOST_UBLAS_INLINE
2840 const_iterator2 end2 () const {
2841 return find2 (rank: 0, i: 0, j: size2 ());
2842 }
2843 BOOST_UBLAS_INLINE
2844 const_iterator2 cend2 () const {
2845 return end2 ();
2846 }
2847
2848 // Reverse iterators
2849
2850 BOOST_UBLAS_INLINE
2851 const_reverse_iterator1 rbegin1 () const {
2852 return const_reverse_iterator1 (end1 ());
2853 }
2854 BOOST_UBLAS_INLINE
2855 const_reverse_iterator1 crbegin1 () const {
2856 return rbegin1 ();
2857 }
2858 BOOST_UBLAS_INLINE
2859 const_reverse_iterator1 rend1 () const {
2860 return const_reverse_iterator1 (begin1 ());
2861 }
2862 BOOST_UBLAS_INLINE
2863 const_reverse_iterator1 crend1 () const {
2864 return rend1 ();
2865 }
2866
2867 BOOST_UBLAS_INLINE
2868 const_reverse_iterator2 rbegin2 () const {
2869 return const_reverse_iterator2 (end2 ());
2870 }
2871 BOOST_UBLAS_INLINE
2872 const_reverse_iterator2 crbegin2 () const {
2873 return rbegin2 ();
2874 }
2875 BOOST_UBLAS_INLINE
2876 const_reverse_iterator2 rend2 () const {
2877 return const_reverse_iterator2 (begin2 ());
2878 }
2879 BOOST_UBLAS_INLINE
2880 const_reverse_iterator2 crend2 () const {
2881 return rend2 ();
2882 }
2883
2884private:
2885 expression1_closure_type e1_;
2886 expression2_closure_type e2_;
2887};
2888
2889template<class E1, class E2, class F>
2890struct matrix_binary_traits {
2891 typedef matrix_binary<E1, E2, F> expression_type;
2892#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
2893 typedef expression_type result_type;
2894#else
2895 typedef typename E1::matrix_temporary_type result_type;
2896#endif
2897};
2898
2899// (m1 + m2) [i] [j] = m1 [i] [j] + m2 [i] [j]
2900template<class E1, class E2>
2901BOOST_UBLAS_INLINE
2902typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
2903typename E2::value_type> >::result_type
2904operator + (const matrix_expression<E1> &e1,
2905 const matrix_expression<E2> &e2) {
2906 typedef typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
2907 typename E2::value_type> >::expression_type expression_type;
2908 return expression_type (e1 (), e2 ());
2909}
2910
2911// (m1 - m2) [i] [j] = m1 [i] [j] - m2 [i] [j]
2912template<class E1, class E2>
2913BOOST_UBLAS_INLINE
2914typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
2915typename E2::value_type> >::result_type
2916operator - (const matrix_expression<E1> &e1,
2917 const matrix_expression<E2> &e2) {
2918 typedef typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
2919 typename E2::value_type> >::expression_type expression_type;
2920 return expression_type (e1 (), e2 ());
2921}
2922
2923// (m1 * m2) [i] [j] = m1 [i] [j] * m2 [i] [j]
2924template<class E1, class E2>
2925BOOST_UBLAS_INLINE
2926typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
2927typename E2::value_type> >::result_type
2928element_prod (const matrix_expression<E1> &e1,
2929 const matrix_expression<E2> &e2) {
2930 typedef typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
2931 typename E2::value_type> >::expression_type expression_type;
2932 return expression_type (e1 (), e2 ());
2933}
2934
2935// (m1 / m2) [i] [j] = m1 [i] [j] / m2 [i] [j]
2936template<class E1, class E2>
2937BOOST_UBLAS_INLINE
2938typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
2939typename E2::value_type> >::result_type
2940element_div (const matrix_expression<E1> &e1,
2941 const matrix_expression<E2> &e2) {
2942 typedef typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
2943 typename E2::value_type> >::expression_type expression_type;
2944 return expression_type (e1 (), e2 ());
2945}
2946
2947template<class E1, class E2, class F>
2948class matrix_binary_scalar1:
2949 public matrix_expression<matrix_binary_scalar1<E1, E2, F> > {
2950
2951 typedef E1 expression1_type;
2952 typedef E2 expression2_type;
2953 typedef F functor_type;
2954 typedef const E1& expression1_closure_type;
2955 typedef typename E2::const_closure_type expression2_closure_type;
2956 typedef matrix_binary_scalar1<E1, E2, F> self_type;
2957public:
2958#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2959 using matrix_expression<self_type>::operator ();
2960#endif
2961 typedef typename E2::size_type size_type;
2962 typedef typename E2::difference_type difference_type;
2963 typedef typename F::result_type value_type;
2964 typedef value_type const_reference;
2965 typedef const_reference reference;
2966 typedef const self_type const_closure_type;
2967 typedef const_closure_type closure_type;
2968 typedef typename E2::orientation_category orientation_category;
2969 typedef unknown_storage_tag storage_category;
2970
2971 // Construction and destruction
2972 BOOST_UBLAS_INLINE
2973 matrix_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
2974 e1_ (e1), e2_ (e2) {}
2975
2976 // Accessors
2977 BOOST_UBLAS_INLINE
2978 size_type size1 () const {
2979 return e2_.size1 ();
2980 }
2981 BOOST_UBLAS_INLINE
2982 size_type size2 () const {
2983 return e2_.size2 ();
2984 }
2985
2986public:
2987 // Element access
2988 BOOST_UBLAS_INLINE
2989 const_reference operator () (size_type i, size_type j) const {
2990 return functor_type::apply (expression1_type (e1_), e2_ (i, j));
2991 }
2992
2993 // Element access
2994 BOOST_UBLAS_INLINE
2995 const_reference operator () (size_type i) const {
2996 return functor_type::apply (expression1_type (e1_), e2_ (i));
2997 }
2998
2999 // Closure comparison
3000 BOOST_UBLAS_INLINE
3001 bool same_closure (const matrix_binary_scalar1 &mbs1) const {
3002 return &e1_ == &(mbs1.e1_) &&
3003 (*this).e2_.same_closure (mbs1.e2_);
3004 }
3005
3006 // Iterator types
3007private:
3008 typedef expression1_type const_subiterator1_type;
3009 typedef typename E2::const_iterator1 const_iterator21_type;
3010 typedef typename E2::const_iterator2 const_iterator22_type;
3011 typedef const value_type *const_pointer;
3012
3013public:
3014#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3015 typedef indexed_const_iterator1<const_closure_type, typename const_iterator21_type::iterator_category> const_iterator1;
3016 typedef const_iterator1 iterator1;
3017 typedef indexed_const_iterator2<const_closure_type, typename const_iterator22_type::iterator_category> const_iterator2;
3018 typedef const_iterator2 iterator2;
3019#else
3020 class const_iterator1;
3021 typedef const_iterator1 iterator1;
3022 class const_iterator2;
3023 typedef const_iterator2 iterator2;
3024#endif
3025 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
3026 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
3027
3028 // Element lookup
3029 BOOST_UBLAS_INLINE
3030 const_iterator1 find1 (int rank, size_type i, size_type j) const {
3031 const_iterator21_type it21 (e2_.find1 (rank, i, j));
3032#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3033 return const_iterator1 (*this, it21.index1 (), it21.index2 ());
3034#else
3035 return const_iterator1 (*this, const_subiterator1_type (e1_), it21);
3036#endif
3037 }
3038 BOOST_UBLAS_INLINE
3039 const_iterator2 find2 (int rank, size_type i, size_type j) const {
3040 const_iterator22_type it22 (e2_.find2 (rank, i, j));
3041#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3042 return const_iterator2 (*this, it22.index1 (), it22.index2 ());
3043#else
3044 return const_iterator2 (*this, const_subiterator1_type (e1_), it22);
3045#endif
3046 }
3047
3048 // Iterators enhance the iterators of the referenced expression
3049 // with the binary functor.
3050
3051#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3052 class const_iterator1:
3053 public container_const_reference<matrix_binary_scalar1>,
3054 public iterator_base_traits<typename E2::const_iterator1::iterator_category>::template
3055 iterator_base<const_iterator1, value_type>::type {
3056 public:
3057 typedef typename E2::const_iterator1::iterator_category iterator_category;
3058 typedef typename matrix_binary_scalar1::difference_type difference_type;
3059 typedef typename matrix_binary_scalar1::value_type value_type;
3060 typedef typename matrix_binary_scalar1::const_reference reference;
3061 typedef typename matrix_binary_scalar1::const_pointer pointer;
3062
3063 typedef const_iterator2 dual_iterator_type;
3064 typedef const_reverse_iterator2 dual_reverse_iterator_type;
3065
3066 // Construction and destruction
3067 BOOST_UBLAS_INLINE
3068 const_iterator1 ():
3069 container_const_reference<self_type> (), it1_ (), it2_ () {}
3070 BOOST_UBLAS_INLINE
3071 const_iterator1 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator21_type &it2):
3072 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3073
3074 // Arithmetic
3075 BOOST_UBLAS_INLINE
3076 const_iterator1 &operator ++ () {
3077 ++ it2_;
3078 return *this;
3079 }
3080 BOOST_UBLAS_INLINE
3081 const_iterator1 &operator -- () {
3082 -- it2_ ;
3083 return *this;
3084 }
3085 BOOST_UBLAS_INLINE
3086 const_iterator1 &operator += (difference_type n) {
3087 it2_ += n;
3088 return *this;
3089 }
3090 BOOST_UBLAS_INLINE
3091 const_iterator1 &operator -= (difference_type n) {
3092 it2_ -= n;
3093 return *this;
3094 }
3095 BOOST_UBLAS_INLINE
3096 difference_type operator - (const const_iterator1 &it) const {
3097 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3098 // FIXME we shouldn't compare floats
3099 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3100 return it2_ - it.it2_;
3101 }
3102
3103 // Dereference
3104 BOOST_UBLAS_INLINE
3105 const_reference operator * () const {
3106 return functor_type::apply (it1_, *it2_);
3107 }
3108 BOOST_UBLAS_INLINE
3109 const_reference operator [] (difference_type n) const {
3110 return *(*this + n);
3111 }
3112
3113#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3114 BOOST_UBLAS_INLINE
3115#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3116 typename self_type::
3117#endif
3118 const_iterator2 begin () const {
3119 return (*this) ().find2 (1, index1 (), 0);
3120 }
3121 BOOST_UBLAS_INLINE
3122#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3123 typename self_type::
3124#endif
3125 const_iterator2 cbegin () const {
3126 return begin ();
3127 }
3128 BOOST_UBLAS_INLINE
3129#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3130 typename self_type::
3131#endif
3132 const_iterator2 end () const {
3133 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
3134 }
3135 BOOST_UBLAS_INLINE
3136#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3137 typename self_type::
3138#endif
3139 const_iterator2 cend () const {
3140 return end ();
3141 }
3142 BOOST_UBLAS_INLINE
3143#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3144 typename self_type::
3145#endif
3146 const_reverse_iterator2 rbegin () const {
3147 return const_reverse_iterator2 (end ());
3148 }
3149 BOOST_UBLAS_INLINE
3150#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3151 typename self_type::
3152#endif
3153 const_reverse_iterator2 crbegin () const {
3154 return rbegin ();
3155 }
3156 BOOST_UBLAS_INLINE
3157#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3158 typename self_type::
3159#endif
3160 const_reverse_iterator2 rend () const {
3161 return const_reverse_iterator2 (begin ());
3162 }
3163 BOOST_UBLAS_INLINE
3164#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3165 typename self_type::
3166#endif
3167 const_reverse_iterator2 crend () const {
3168 return rend ();
3169 }
3170#endif
3171
3172 // Indices
3173 BOOST_UBLAS_INLINE
3174 size_type index1 () const {
3175 return it2_.index1 ();
3176 }
3177 BOOST_UBLAS_INLINE
3178 size_type index2 () const {
3179 return it2_.index2 ();
3180 }
3181
3182 // Assignment
3183 BOOST_UBLAS_INLINE
3184 const_iterator1 &operator = (const const_iterator1 &it) {
3185 container_const_reference<self_type>::assign (&it ());
3186 it1_ = it.it1_;
3187 it2_ = it.it2_;
3188 return *this;
3189 }
3190
3191 // Comparison
3192 BOOST_UBLAS_INLINE
3193 bool operator == (const const_iterator1 &it) const {
3194 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3195 // FIXME we shouldn't compare floats
3196 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3197 return it2_ == it.it2_;
3198 }
3199 BOOST_UBLAS_INLINE
3200 bool operator < (const const_iterator1 &it) const {
3201 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3202 // FIXME we shouldn't compare floats
3203 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3204 return it2_ < it.it2_;
3205 }
3206
3207 private:
3208 const_subiterator1_type it1_;
3209 const_iterator21_type it2_;
3210 };
3211#endif
3212
3213 BOOST_UBLAS_INLINE
3214 const_iterator1 begin1 () const {
3215 return find1 (rank: 0, i: 0, j: 0);
3216 }
3217 BOOST_UBLAS_INLINE
3218 const_iterator1 cbegin1 () const {
3219 return begin1 ();
3220 }
3221 BOOST_UBLAS_INLINE
3222 const_iterator1 end1 () const {
3223 return find1 (rank: 0, i: size1 (), j: 0);
3224 }
3225 BOOST_UBLAS_INLINE
3226 const_iterator1 cend1 () const {
3227 return end1 ();
3228 }
3229
3230#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3231 class const_iterator2:
3232 public container_const_reference<matrix_binary_scalar1>,
3233 public iterator_base_traits<typename E2::const_iterator2::iterator_category>::template
3234 iterator_base<const_iterator2, value_type>::type {
3235 public:
3236 typedef typename E2::const_iterator2::iterator_category iterator_category;
3237 typedef typename matrix_binary_scalar1::difference_type difference_type;
3238 typedef typename matrix_binary_scalar1::value_type value_type;
3239 typedef typename matrix_binary_scalar1::const_reference reference;
3240 typedef typename matrix_binary_scalar1::const_pointer pointer;
3241
3242 typedef const_iterator1 dual_iterator_type;
3243 typedef const_reverse_iterator1 dual_reverse_iterator_type;
3244
3245 // Construction and destruction
3246 BOOST_UBLAS_INLINE
3247 const_iterator2 ():
3248 container_const_reference<self_type> (), it1_ (), it2_ () {}
3249 BOOST_UBLAS_INLINE
3250 const_iterator2 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator22_type &it2):
3251 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3252
3253 // Arithmetic
3254 BOOST_UBLAS_INLINE
3255 const_iterator2 &operator ++ () {
3256 ++ it2_;
3257 return *this;
3258 }
3259 BOOST_UBLAS_INLINE
3260 const_iterator2 &operator -- () {
3261 -- it2_;
3262 return *this;
3263 }
3264 BOOST_UBLAS_INLINE
3265 const_iterator2 &operator += (difference_type n) {
3266 it2_ += n;
3267 return *this;
3268 }
3269 BOOST_UBLAS_INLINE
3270 const_iterator2 &operator -= (difference_type n) {
3271 it2_ -= n;
3272 return *this;
3273 }
3274 BOOST_UBLAS_INLINE
3275 difference_type operator - (const const_iterator2 &it) const {
3276 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3277 // FIXME we shouldn't compare floats
3278 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3279 return it2_ - it.it2_;
3280 }
3281
3282 // Dereference
3283 BOOST_UBLAS_INLINE
3284 const_reference operator * () const {
3285 return functor_type::apply (it1_, *it2_);
3286 }
3287 BOOST_UBLAS_INLINE
3288 const_reference operator [] (difference_type n) const {
3289 return *(*this + n);
3290 }
3291
3292#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3293 BOOST_UBLAS_INLINE
3294#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3295 typename self_type::
3296#endif
3297 const_iterator1 begin () const {
3298 return (*this) ().find1 (1, 0, index2 ());
3299 }
3300 BOOST_UBLAS_INLINE
3301#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3302 typename self_type::
3303#endif
3304 const_iterator1 cbegin () const {
3305 return begin ();
3306 }
3307 BOOST_UBLAS_INLINE
3308#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3309 typename self_type::
3310#endif
3311 const_iterator1 end () const {
3312 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
3313 }
3314 BOOST_UBLAS_INLINE
3315#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3316 typename self_type::
3317#endif
3318 const_iterator1 cend () const {
3319 return end ();
3320 }
3321 BOOST_UBLAS_INLINE
3322#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3323 typename self_type::
3324#endif
3325 const_reverse_iterator1 rbegin () const {
3326 return const_reverse_iterator1 (end ());
3327 }
3328 BOOST_UBLAS_INLINE
3329#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3330 typename self_type::
3331#endif
3332 const_reverse_iterator1 crbegin () const {
3333 return rbegin ();
3334 }
3335 BOOST_UBLAS_INLINE
3336#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3337 typename self_type::
3338#endif
3339 const_reverse_iterator1 rend () const {
3340 return const_reverse_iterator1 (begin ());
3341 }
3342 BOOST_UBLAS_INLINE
3343#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3344 typename self_type::
3345#endif
3346 const_reverse_iterator1 crend () const {
3347 return rend ();
3348 }
3349#endif
3350
3351 // Indices
3352 BOOST_UBLAS_INLINE
3353 size_type index1 () const {
3354 return it2_.index1 ();
3355 }
3356 BOOST_UBLAS_INLINE
3357 size_type index2 () const {
3358 return it2_.index2 ();
3359 }
3360
3361 // Assignment
3362 BOOST_UBLAS_INLINE
3363 const_iterator2 &operator = (const const_iterator2 &it) {
3364 container_const_reference<self_type>::assign (&it ());
3365 it1_ = it.it1_;
3366 it2_ = it.it2_;
3367 return *this;
3368 }
3369
3370 // Comparison
3371 BOOST_UBLAS_INLINE
3372 bool operator == (const const_iterator2 &it) const {
3373 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3374 // FIXME we shouldn't compare floats
3375 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3376 return it2_ == it.it2_;
3377 }
3378 BOOST_UBLAS_INLINE
3379 bool operator < (const const_iterator2 &it) const {
3380 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3381 // FIXME we shouldn't compare floats
3382 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3383 return it2_ < it.it2_;
3384 }
3385
3386 private:
3387 const_subiterator1_type it1_;
3388 const_iterator22_type it2_;
3389 };
3390#endif
3391
3392 BOOST_UBLAS_INLINE
3393 const_iterator2 begin2 () const {
3394 return find2 (rank: 0, i: 0, j: 0);
3395 }
3396 BOOST_UBLAS_INLINE
3397 const_iterator2 cbegin2 () const {
3398 return begin2 ();
3399 }
3400 BOOST_UBLAS_INLINE
3401 const_iterator2 end2 () const {
3402 return find2 (rank: 0, i: 0, j: size2 ());
3403 }
3404 BOOST_UBLAS_INLINE
3405 const_iterator2 cend2 () const {
3406 return end2 ();
3407 }
3408
3409 // Reverse iterators
3410
3411 BOOST_UBLAS_INLINE
3412 const_reverse_iterator1 rbegin1 () const {
3413 return const_reverse_iterator1 (end1 ());
3414 }
3415 BOOST_UBLAS_INLINE
3416 const_reverse_iterator1 crbegin1 () const {
3417 return rbegin1 ();
3418 }
3419 BOOST_UBLAS_INLINE
3420 const_reverse_iterator1 rend1 () const {
3421 return const_reverse_iterator1 (begin1 ());
3422 }
3423 BOOST_UBLAS_INLINE
3424 const_reverse_iterator1 crend1 () const {
3425 return rend1 ();
3426 }
3427
3428 BOOST_UBLAS_INLINE
3429 const_reverse_iterator2 rbegin2 () const {
3430 return const_reverse_iterator2 (end2 ());
3431 }
3432 BOOST_UBLAS_INLINE
3433 const_reverse_iterator2 crbegin2 () const {
3434 return rbegin2 ();
3435 }
3436 BOOST_UBLAS_INLINE
3437 const_reverse_iterator2 rend2 () const {
3438 return const_reverse_iterator2 (begin2 ());
3439 }
3440 BOOST_UBLAS_INLINE
3441 const_reverse_iterator2 crend2 () const {
3442 return rend2 ();
3443 }
3444
3445private:
3446 expression1_closure_type e1_;
3447 expression2_closure_type e2_;
3448};
3449
3450template<class E1, class E2, class F>
3451struct matrix_binary_scalar1_traits {
3452 typedef matrix_binary_scalar1<E1, E2, F> expression_type; // allow E1 to be builtin type
3453#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
3454 typedef expression_type result_type;
3455#else
3456 typedef typename E2::matrix_temporary_type result_type;
3457#endif
3458};
3459
3460// (t * m) [i] [j] = t * m [i] [j]
3461template<class T1, class E2>
3462BOOST_UBLAS_INLINE
3463typename boost::enable_if< is_convertible<T1, typename E2::value_type >,
3464typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
3465>::type
3466operator * (const T1 &e1,
3467 const matrix_expression<E2> &e2) {
3468 typedef typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
3469 return expression_type (e1, e2 ());
3470}
3471
3472
3473template<class E1, class E2, class F>
3474class matrix_binary_scalar2:
3475 public matrix_expression<matrix_binary_scalar2<E1, E2, F> > {
3476
3477 typedef E1 expression1_type;
3478 typedef E2 expression2_type;
3479 typedef F functor_type;
3480public:
3481 typedef typename E1::const_closure_type expression1_closure_type;
3482 typedef const E2& expression2_closure_type;
3483private:
3484 typedef matrix_binary_scalar2<E1, E2, F> self_type;
3485public:
3486#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
3487 using matrix_expression<self_type>::operator ();
3488#endif
3489 typedef typename E1::size_type size_type;
3490 typedef typename E1::difference_type difference_type;
3491 typedef typename F::result_type value_type;
3492 typedef value_type const_reference;
3493 typedef const_reference reference;
3494
3495 typedef const self_type const_closure_type;
3496 typedef const_closure_type closure_type;
3497 typedef typename E1::orientation_category orientation_category;
3498 typedef unknown_storage_tag storage_category;
3499
3500 // Construction and destruction
3501 BOOST_UBLAS_INLINE
3502 matrix_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
3503 e1_ (e1), e2_ (e2) {}
3504
3505 // Accessors
3506 BOOST_UBLAS_INLINE
3507 size_type size1 () const {
3508 return e1_.size1 ();
3509 }
3510 BOOST_UBLAS_INLINE
3511 size_type size2 () const {
3512 return e1_.size2 ();
3513 }
3514
3515public:
3516 // Element access
3517 BOOST_UBLAS_INLINE
3518 const_reference operator () (size_type i, size_type j) const {
3519 return functor_type::apply (e1_ (i, j), expression2_type (e2_));
3520 }
3521 // Element access
3522 BOOST_UBLAS_INLINE
3523 const_reference operator () (size_type i) const {
3524 return functor_type::apply (e1_ (i), expression2_type (e2_));
3525 }
3526
3527 // Closure comparison
3528 BOOST_UBLAS_INLINE
3529 bool same_closure (const matrix_binary_scalar2 &mbs2) const {
3530 return (*this).e1_.same_closure (mbs2.e1_) &&
3531 &e2_ == &(mbs2.e2_);
3532 }
3533
3534 // Iterator types
3535private:
3536 typedef typename E1::const_iterator1 const_iterator11_type;
3537 typedef typename E1::const_iterator2 const_iterator12_type;
3538 typedef expression2_type const_subiterator2_type;
3539 typedef const value_type *const_pointer;
3540
3541public:
3542#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3543 typedef indexed_const_iterator1<const_closure_type, typename const_iterator11_type::iterator_category> const_iterator1;
3544 typedef const_iterator1 iterator1;
3545 typedef indexed_const_iterator2<const_closure_type, typename const_iterator12_type::iterator_category> const_iterator2;
3546 typedef const_iterator2 iterator2;
3547#else
3548 class const_iterator1;
3549 typedef const_iterator1 iterator1;
3550 class const_iterator2;
3551 typedef const_iterator2 iterator2;
3552#endif
3553 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
3554 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
3555
3556 // Element lookup
3557 BOOST_UBLAS_INLINE
3558 const_iterator1 find1 (int rank, size_type i, size_type j) const {
3559 const_iterator11_type it11 (e1_.find1 (rank, i, j));
3560#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3561 return const_iterator1 (*this, it11.index1 (), it11.index2 ());
3562#else
3563 return const_iterator1 (*this, it11, const_subiterator2_type (e2_));
3564#endif
3565 }
3566 BOOST_UBLAS_INLINE
3567 const_iterator2 find2 (int rank, size_type i, size_type j) const {
3568 const_iterator12_type it12 (e1_.find2 (rank, i, j));
3569#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3570 return const_iterator2 (*this, it12.index1 (), it12.index2 ());
3571#else
3572 return const_iterator2 (*this, it12, const_subiterator2_type (e2_));
3573#endif
3574 }
3575
3576 // Iterators enhance the iterators of the referenced expression
3577 // with the binary functor.
3578
3579#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3580 class const_iterator1:
3581 public container_const_reference<matrix_binary_scalar2>,
3582 public iterator_base_traits<typename E1::const_iterator1::iterator_category>::template
3583 iterator_base<const_iterator1, value_type>::type {
3584 public:
3585 typedef typename E1::const_iterator1::iterator_category iterator_category;
3586 typedef typename matrix_binary_scalar2::difference_type difference_type;
3587 typedef typename matrix_binary_scalar2::value_type value_type;
3588 typedef typename matrix_binary_scalar2::const_reference reference;
3589 typedef typename matrix_binary_scalar2::const_pointer pointer;
3590
3591 typedef const_iterator2 dual_iterator_type;
3592 typedef const_reverse_iterator2 dual_reverse_iterator_type;
3593
3594 // Construction and destruction
3595 BOOST_UBLAS_INLINE
3596 const_iterator1 ():
3597 container_const_reference<self_type> (), it1_ (), it2_ () {}
3598 BOOST_UBLAS_INLINE
3599 const_iterator1 (const self_type &mbs, const const_iterator11_type &it1, const const_subiterator2_type &it2):
3600 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3601
3602 // Arithmetic
3603 BOOST_UBLAS_INLINE
3604 const_iterator1 &operator ++ () {
3605 ++ it1_;
3606 return *this;
3607 }
3608 BOOST_UBLAS_INLINE
3609 const_iterator1 &operator -- () {
3610 -- it1_ ;
3611 return *this;
3612 }
3613 BOOST_UBLAS_INLINE
3614 const_iterator1 &operator += (difference_type n) {
3615 it1_ += n;
3616 return *this;
3617 }
3618 BOOST_UBLAS_INLINE
3619 const_iterator1 &operator -= (difference_type n) {
3620 it1_ -= n;
3621 return *this;
3622 }
3623 BOOST_UBLAS_INLINE
3624 difference_type operator - (const const_iterator1 &it) const {
3625 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3626 // FIXME we shouldn't compare floats
3627 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3628 return it1_ - it.it1_;
3629 }
3630
3631 // Dereference
3632 BOOST_UBLAS_INLINE
3633 const_reference operator * () const {
3634 return functor_type::apply (*it1_, it2_);
3635 }
3636 BOOST_UBLAS_INLINE
3637 const_reference operator [] (difference_type n) const {
3638 return *(*this + n);
3639 }
3640
3641#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3642 BOOST_UBLAS_INLINE
3643#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3644 typename self_type::
3645#endif
3646 const_iterator2 begin () const {
3647 return (*this) ().find2 (1, index1 (), 0);
3648 }
3649 BOOST_UBLAS_INLINE
3650#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3651 typename self_type::
3652#endif
3653 const_iterator2 cbegin () const {
3654 return begin ();
3655 }
3656 BOOST_UBLAS_INLINE
3657#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3658 typename self_type::
3659#endif
3660 const_iterator2 end () const {
3661 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
3662 }
3663 BOOST_UBLAS_INLINE
3664#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3665 typename self_type::
3666#endif
3667 const_iterator2 cend () const {
3668 return end ();
3669 }
3670 BOOST_UBLAS_INLINE
3671#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3672 typename self_type::
3673#endif
3674 const_reverse_iterator2 rbegin () const {
3675 return const_reverse_iterator2 (end ());
3676 }
3677 BOOST_UBLAS_INLINE
3678#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3679 typename self_type::
3680#endif
3681 const_reverse_iterator2 crbegin () const {
3682 return rbegin ();
3683 }
3684 BOOST_UBLAS_INLINE
3685#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3686 typename self_type::
3687#endif
3688 const_reverse_iterator2 rend () const {
3689 return const_reverse_iterator2 (begin ());
3690 }
3691 BOOST_UBLAS_INLINE
3692#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3693 typename self_type::
3694#endif
3695 const_reverse_iterator2 crend () const {
3696 return rend ();
3697 }
3698#endif
3699
3700 // Indices
3701 BOOST_UBLAS_INLINE
3702 size_type index1 () const {
3703 return it1_.index1 ();
3704 }
3705 BOOST_UBLAS_INLINE
3706 size_type index2 () const {
3707 return it1_.index2 ();
3708 }
3709
3710 // Assignment
3711 BOOST_UBLAS_INLINE
3712 const_iterator1 &operator = (const const_iterator1 &it) {
3713 container_const_reference<self_type>::assign (&it ());
3714 it1_ = it.it1_;
3715 it2_ = it.it2_;
3716 return *this;
3717 }
3718
3719 // Comparison
3720 BOOST_UBLAS_INLINE
3721 bool operator == (const const_iterator1 &it) const {
3722 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3723 // FIXME we shouldn't compare floats
3724 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3725 return it1_ == it.it1_;
3726 }
3727 BOOST_UBLAS_INLINE
3728 bool operator < (const const_iterator1 &it) const {
3729 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3730 // FIXME we shouldn't compare floats
3731 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3732 return it1_ < it.it1_;
3733 }
3734
3735 private:
3736 const_iterator11_type it1_;
3737 const_subiterator2_type it2_;
3738 };
3739#endif
3740
3741 BOOST_UBLAS_INLINE
3742 const_iterator1 begin1 () const {
3743 return find1 (rank: 0, i: 0, j: 0);
3744 }
3745 BOOST_UBLAS_INLINE
3746 const_iterator1 cbegin1 () const {
3747 return begin1 ();
3748 }
3749 BOOST_UBLAS_INLINE
3750 const_iterator1 end1 () const {
3751 return find1 (rank: 0, i: size1 (), j: 0);
3752 }
3753 BOOST_UBLAS_INLINE
3754 const_iterator1 cend1 () const {
3755 return end1 ();
3756 }
3757
3758#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3759 class const_iterator2:
3760 public container_const_reference<matrix_binary_scalar2>,
3761 public iterator_base_traits<typename E1::const_iterator2::iterator_category>::template
3762 iterator_base<const_iterator2, value_type>::type {
3763 public:
3764 typedef typename E1::const_iterator2::iterator_category iterator_category;
3765 typedef typename matrix_binary_scalar2::difference_type difference_type;
3766 typedef typename matrix_binary_scalar2::value_type value_type;
3767 typedef typename matrix_binary_scalar2::const_reference reference;
3768 typedef typename matrix_binary_scalar2::const_pointer pointer;
3769
3770 typedef const_iterator1 dual_iterator_type;
3771 typedef const_reverse_iterator1 dual_reverse_iterator_type;
3772
3773 // Construction and destruction
3774 BOOST_UBLAS_INLINE
3775 const_iterator2 ():
3776 container_const_reference<self_type> (), it1_ (), it2_ () {}
3777 BOOST_UBLAS_INLINE
3778 const_iterator2 (const self_type &mbs, const const_iterator12_type &it1, const const_subiterator2_type &it2):
3779 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3780
3781 // Arithmetic
3782 BOOST_UBLAS_INLINE
3783 const_iterator2 &operator ++ () {
3784 ++ it1_;
3785 return *this;
3786 }
3787 BOOST_UBLAS_INLINE
3788 const_iterator2 &operator -- () {
3789 -- it1_;
3790 return *this;
3791 }
3792 BOOST_UBLAS_INLINE
3793 const_iterator2 &operator += (difference_type n) {
3794 it1_ += n;
3795 return *this;
3796 }
3797 BOOST_UBLAS_INLINE
3798 const_iterator2 &operator -= (difference_type n) {
3799 it1_ -= n;
3800 return *this;
3801 }
3802 BOOST_UBLAS_INLINE
3803 difference_type operator - (const const_iterator2 &it) const {
3804 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3805 // FIXME we shouldn't compare floats
3806 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3807 return it1_ - it.it1_;
3808 }
3809
3810 // Dereference
3811 BOOST_UBLAS_INLINE
3812 const_reference operator * () const {
3813 return functor_type::apply (*it1_, it2_);
3814 }
3815 BOOST_UBLAS_INLINE
3816 const_reference operator [] (difference_type n) const {
3817 return *(*this + n);
3818 }
3819
3820#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3821 BOOST_UBLAS_INLINE
3822#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3823 typename self_type::
3824#endif
3825 const_iterator1 begin () const {
3826 return (*this) ().find1 (1, 0, index2 ());
3827 }
3828 BOOST_UBLAS_INLINE
3829#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3830 typename self_type::
3831#endif
3832 const_iterator1 cbegin () const {
3833 return begin ();
3834 }
3835 BOOST_UBLAS_INLINE
3836#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3837 typename self_type::
3838#endif
3839 const_iterator1 end () const {
3840 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
3841 }
3842 BOOST_UBLAS_INLINE
3843#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3844 typename self_type::
3845#endif
3846 const_iterator1 cend () const {
3847 return end ();
3848 }
3849 BOOST_UBLAS_INLINE
3850#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3851 typename self_type::
3852#endif
3853 const_reverse_iterator1 rbegin () const {
3854 return const_reverse_iterator1 (end ());
3855 }
3856 BOOST_UBLAS_INLINE
3857#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3858 typename self_type::
3859#endif
3860 const_reverse_iterator1 crbegin () const {
3861 return rbegin ();
3862 }
3863 BOOST_UBLAS_INLINE
3864#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3865 typename self_type::
3866#endif
3867 const_reverse_iterator1 rend () const {
3868 return const_reverse_iterator1 (begin ());
3869 }
3870 BOOST_UBLAS_INLINE
3871#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3872 typename self_type::
3873#endif
3874 const_reverse_iterator1 crend () const {
3875 return rend ();
3876 }
3877#endif
3878
3879 // Indices
3880 BOOST_UBLAS_INLINE
3881 size_type index1 () const {
3882 return it1_.index1 ();
3883 }
3884 BOOST_UBLAS_INLINE
3885 size_type index2 () const {
3886 return it1_.index2 ();
3887 }
3888
3889 // Assignment
3890 BOOST_UBLAS_INLINE
3891 const_iterator2 &operator = (const const_iterator2 &it) {
3892 container_const_reference<self_type>::assign (&it ());
3893 it1_ = it.it1_;
3894 it2_ = it.it2_;
3895 return *this;
3896 }
3897
3898 // Comparison
3899 BOOST_UBLAS_INLINE
3900 bool operator == (const const_iterator2 &it) const {
3901 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3902 // FIXME we shouldn't compare floats
3903 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3904 return it1_ == it.it1_;
3905 }
3906 BOOST_UBLAS_INLINE
3907 bool operator < (const const_iterator2 &it) const {
3908 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3909 // FIXME we shouldn't compare floats
3910 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3911 return it1_ < it.it1_;
3912 }
3913
3914 private:
3915 const_iterator12_type it1_;
3916 const_subiterator2_type it2_;
3917 };
3918#endif
3919
3920 BOOST_UBLAS_INLINE
3921 const_iterator2 begin2 () const {
3922 return find2 (rank: 0, i: 0, j: 0);
3923 }
3924 BOOST_UBLAS_INLINE
3925 const_iterator2 cbegin2 () const {
3926 return begin2 ();
3927 }
3928 BOOST_UBLAS_INLINE
3929 const_iterator2 end2 () const {
3930 return find2 (rank: 0, i: 0, j: size2 ());
3931 }
3932 BOOST_UBLAS_INLINE
3933 const_iterator2 cend2 () const {
3934 return end2 ();
3935 }
3936
3937 // Reverse iterators
3938
3939 BOOST_UBLAS_INLINE
3940 const_reverse_iterator1 rbegin1 () const {
3941 return const_reverse_iterator1 (end1 ());
3942 }
3943 BOOST_UBLAS_INLINE
3944 const_reverse_iterator1 crbegin1 () const {
3945 return rbegin1 ();
3946 }
3947 BOOST_UBLAS_INLINE
3948 const_reverse_iterator1 rend1 () const {
3949 return const_reverse_iterator1 (begin1 ());
3950 }
3951 BOOST_UBLAS_INLINE
3952 const_reverse_iterator1 crend1 () const {
3953 return rend1 ();
3954 }
3955
3956 BOOST_UBLAS_INLINE
3957 const_reverse_iterator2 rbegin2 () const {
3958 return const_reverse_iterator2 (end2 ());
3959 }
3960 BOOST_UBLAS_INLINE
3961 const_reverse_iterator2 crbegin2 () const {
3962 return rbegin2 ();
3963 }
3964 BOOST_UBLAS_INLINE
3965 const_reverse_iterator2 rend2 () const {
3966 return const_reverse_iterator2 (begin2 ());
3967 }
3968 BOOST_UBLAS_INLINE
3969 const_reverse_iterator2 crend2 () const {
3970 return rend2 ();
3971 }
3972
3973private:
3974 expression1_closure_type e1_;
3975 expression2_closure_type e2_;
3976};
3977
3978template<class E1, class E2, class F>
3979struct matrix_binary_scalar2_traits {
3980 typedef matrix_binary_scalar2<E1, E2, F> expression_type; // allow E2 to be builtin type
3981#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
3982 typedef expression_type result_type;
3983#else
3984 typedef typename E1::matrix_temporary_type result_type;
3985#endif
3986};
3987
3988// (m * t) [i] [j] = m [i] [j] * t
3989template<class E1, class T2>
3990BOOST_UBLAS_INLINE
3991typename boost::enable_if< is_convertible<T2, typename E1::value_type>,
3992typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
3993>::type
3994operator * (const matrix_expression<E1> &e1,
3995 const T2 &e2) {
3996 typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
3997 return expression_type (e1 (), e2);
3998}
3999
4000// (m / t) [i] [j] = m [i] [j] / t
4001template<class E1, class T2>
4002BOOST_UBLAS_INLINE
4003typename boost::enable_if< is_convertible<T2, typename E1::value_type>,
4004typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
4005>::type
4006operator / (const matrix_expression<E1> &e1,
4007 const T2 &e2) {
4008 typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
4009 return expression_type (e1 (), e2);
4010}
4011
4012
4013template<class E1, class E2, class F>
4014class matrix_vector_binary1:
4015 public vector_expression<matrix_vector_binary1<E1, E2, F> > {
4016
4017public:
4018 typedef E1 expression1_type;
4019 typedef E2 expression2_type;
4020private:
4021 typedef F functor_type;
4022public:
4023 typedef typename E1::const_closure_type expression1_closure_type;
4024 typedef typename E2::const_closure_type expression2_closure_type;
4025private:
4026 typedef matrix_vector_binary1<E1, E2, F> self_type;
4027public:
4028#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4029 using vector_expression<self_type>::operator ();
4030#endif
4031 static const unsigned complexity = 1;
4032 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
4033 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
4034 typedef typename F::result_type value_type;
4035 typedef value_type const_reference;
4036 typedef const_reference reference;
4037 typedef const self_type const_closure_type;
4038 typedef const_closure_type closure_type;
4039 typedef unknown_storage_tag storage_category;
4040
4041 // Construction and destruction
4042 BOOST_UBLAS_INLINE
4043 matrix_vector_binary1 (const expression1_type &e1, const expression2_type &e2):
4044 e1_ (e1), e2_ (e2) {}
4045
4046 // Accessors
4047 BOOST_UBLAS_INLINE
4048 size_type size () const {
4049 return e1_.size1 ();
4050 }
4051
4052public:
4053 // Expression accessors
4054 BOOST_UBLAS_INLINE
4055 const expression1_closure_type &expression1 () const {
4056 return e1_;
4057 }
4058 BOOST_UBLAS_INLINE
4059 const expression2_closure_type &expression2 () const {
4060 return e2_;
4061 }
4062
4063public:
4064 // Element access
4065 BOOST_UBLAS_INLINE
4066 const_reference operator () (size_type i) const {
4067 return functor_type::apply (e1_, e2_, i);
4068 }
4069
4070 // Closure comparison
4071 BOOST_UBLAS_INLINE
4072 bool same_closure (const matrix_vector_binary1 &mvb1) const {
4073 return (*this).expression1 ().same_closure (mvb1.expression1 ()) &&
4074 (*this).expression2 ().same_closure (mvb1.expression2 ());
4075 }
4076
4077 // Iterator types
4078private:
4079 typedef typename E1::const_iterator1 const_subiterator1_type;
4080 typedef typename E2::const_iterator const_subiterator2_type;
4081 typedef const value_type *const_pointer;
4082
4083public:
4084#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4085 typedef indexed_const_iterator<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator;
4086 typedef const_iterator iterator;
4087#else
4088 class const_iterator;
4089 typedef const_iterator iterator;
4090#endif
4091
4092 // Element lookup
4093 BOOST_UBLAS_INLINE
4094 const_iterator find (size_type i) const {
4095#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4096 const_subiterator1_type it1 (e1_.find1 (0, i, 0));
4097 return const_iterator (*this, it1.index1 ());
4098#else
4099 return const_iterator (*this, e1_.find1 (0, i, 0));
4100#endif
4101 }
4102
4103
4104#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4105 class const_iterator:
4106 public container_const_reference<matrix_vector_binary1>,
4107 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4108 typename E2::const_iterator::iterator_category>::iterator_category>::template
4109 iterator_base<const_iterator, value_type>::type {
4110 public:
4111 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4112 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
4113 typedef typename matrix_vector_binary1::difference_type difference_type;
4114 typedef typename matrix_vector_binary1::value_type value_type;
4115 typedef typename matrix_vector_binary1::const_reference reference;
4116 typedef typename matrix_vector_binary1::const_pointer pointer;
4117
4118 // Construction and destruction
4119#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4120 BOOST_UBLAS_INLINE
4121 const_iterator ():
4122 container_const_reference<self_type> (), it1_ (), e2_begin_ (), e2_end_ () {}
4123 BOOST_UBLAS_INLINE
4124 const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
4125 container_const_reference<self_type> (mvb), it1_ (it1), e2_begin_ (mvb.expression2 ().begin ()), e2_end_ (mvb.expression2 ().end ()) {}
4126#else
4127 BOOST_UBLAS_INLINE
4128 const_iterator ():
4129 container_const_reference<self_type> (), it1_ () {}
4130 BOOST_UBLAS_INLINE
4131 const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
4132 container_const_reference<self_type> (mvb), it1_ (it1) {}
4133#endif
4134
4135 private:
4136 // Dense random access specialization
4137 BOOST_UBLAS_INLINE
4138 value_type dereference (dense_random_access_iterator_tag) const {
4139 const self_type &mvb = (*this) ();
4140#ifdef BOOST_UBLAS_USE_INDEXING
4141 return mvb (index ());
4142#elif BOOST_UBLAS_USE_ITERATING
4143 difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
4144#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4145 return functor_type::apply (size, it1_.begin (), e2_begin_);
4146#else
4147 return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
4148#endif
4149#else
4150 difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
4151 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
4152#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4153 return functor_type::apply (size, it1_.begin (), e2_begin_);
4154#else
4155 return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
4156#endif
4157 else
4158 return mvb (index ());
4159#endif
4160 }
4161
4162 // Packed bidirectional specialization
4163 BOOST_UBLAS_INLINE
4164 value_type dereference (packed_random_access_iterator_tag) const {
4165#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4166 return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_);
4167#else
4168 const self_type &mvb = (*this) ();
4169#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4170 return functor_type::apply (it1_.begin (), it1_.end (),
4171 mvb.expression2 ().begin (), mvb.expression2 ().end ());
4172#else
4173 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
4174 boost::numeric::ublas::end (it1_, iterator1_tag ()),
4175 mvb.expression2 ().begin (), mvb.expression2 ().end ());
4176#endif
4177#endif
4178 }
4179
4180 // Sparse bidirectional specialization
4181 BOOST_UBLAS_INLINE
4182 value_type dereference (sparse_bidirectional_iterator_tag) const {
4183#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4184 return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ());
4185#else
4186 const self_type &mvb = (*this) ();
4187#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4188 return functor_type::apply (it1_.begin (), it1_.end (),
4189 mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
4190#else
4191 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
4192 boost::numeric::ublas::end (it1_, iterator1_tag ()),
4193 mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
4194#endif
4195#endif
4196 }
4197
4198 public:
4199 // Arithmetic
4200 BOOST_UBLAS_INLINE
4201 const_iterator &operator ++ () {
4202 ++ it1_;
4203 return *this;
4204 }
4205 BOOST_UBLAS_INLINE
4206 const_iterator &operator -- () {
4207 -- it1_;
4208 return *this;
4209 }
4210 BOOST_UBLAS_INLINE
4211 const_iterator &operator += (difference_type n) {
4212 it1_ += n;
4213 return *this;
4214 }
4215 BOOST_UBLAS_INLINE
4216 const_iterator &operator -= (difference_type n) {
4217 it1_ -= n;
4218 return *this;
4219 }
4220 BOOST_UBLAS_INLINE
4221 difference_type operator - (const const_iterator &it) const {
4222 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4223 return it1_ - it.it1_;
4224 }
4225
4226 // Dereference
4227 BOOST_UBLAS_INLINE
4228 const_reference operator * () const {
4229 return dereference (iterator_category ());
4230 }
4231 BOOST_UBLAS_INLINE
4232 const_reference operator [] (difference_type n) const {
4233 return *(*this + n);
4234 }
4235
4236 // Index
4237 BOOST_UBLAS_INLINE
4238 size_type index () const {
4239 return it1_.index1 ();
4240 }
4241
4242 // Assignment
4243 BOOST_UBLAS_INLINE
4244 const_iterator &operator = (const const_iterator &it) {
4245 container_const_reference<self_type>::assign (&it ());
4246 it1_ = it.it1_;
4247#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4248 e2_begin_ = it.e2_begin_;
4249 e2_end_ = it.e2_end_;
4250#endif
4251 return *this;
4252 }
4253
4254 // Comparison
4255 BOOST_UBLAS_INLINE
4256 bool operator == (const const_iterator &it) const {
4257 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4258 return it1_ == it.it1_;
4259 }
4260 BOOST_UBLAS_INLINE
4261 bool operator < (const const_iterator &it) const {
4262 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4263 return it1_ < it.it1_;
4264 }
4265
4266 private:
4267 const_subiterator1_type it1_;
4268#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4269 // Mutable due to assignment
4270 /* const */ const_subiterator2_type e2_begin_;
4271 /* const */ const_subiterator2_type e2_end_;
4272#endif
4273 };
4274#endif
4275
4276 BOOST_UBLAS_INLINE
4277 const_iterator begin () const {
4278 return find (i: 0);
4279 }
4280 BOOST_UBLAS_INLINE
4281 const_iterator cbegin () const {
4282 return begin ();
4283 }
4284 BOOST_UBLAS_INLINE
4285 const_iterator end () const {
4286 return find (i: size ());
4287 }
4288 BOOST_UBLAS_INLINE
4289 const_iterator cend () const {
4290 return end ();
4291 }
4292
4293 // Reverse iterator
4294 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
4295
4296 BOOST_UBLAS_INLINE
4297 const_reverse_iterator rbegin () const {
4298 return const_reverse_iterator (end ());
4299 }
4300 BOOST_UBLAS_INLINE
4301 const_reverse_iterator crbegin () const {
4302 return rbegin ();
4303 }
4304 BOOST_UBLAS_INLINE
4305 const_reverse_iterator rend () const {
4306 return const_reverse_iterator (begin ());
4307 }
4308 BOOST_UBLAS_INLINE
4309 const_reverse_iterator crend () const {
4310 return rend ();
4311 }
4312
4313private:
4314 expression1_closure_type e1_;
4315 expression2_closure_type e2_;
4316};
4317
4318template<class T1, class E1, class T2, class E2>
4319struct matrix_vector_binary1_traits {
4320 typedef unknown_storage_tag storage_category;
4321 typedef row_major_tag orientation_category;
4322 typedef typename promote_traits<T1, T2>::promote_type promote_type;
4323 typedef matrix_vector_binary1<E1, E2, matrix_vector_prod1<E1, E2, promote_type> > expression_type;
4324#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
4325 typedef expression_type result_type;
4326#else
4327 typedef typename E1::vector_temporary_type result_type;
4328#endif
4329};
4330
4331template<class E1, class E2>
4332BOOST_UBLAS_INLINE
4333typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4334typename E2::value_type, E2>::result_type
4335prod (const matrix_expression<E1> &e1,
4336 const vector_expression<E2> &e2,
4337 unknown_storage_tag,
4338 row_major_tag) {
4339 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4340 typename E2::value_type, E2>::expression_type expression_type;
4341 return expression_type (e1 (), e2 ());
4342}
4343
4344// Dispatcher
4345template<class E1, class E2>
4346BOOST_UBLAS_INLINE
4347typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4348typename E2::value_type, E2>::result_type
4349prod (const matrix_expression<E1> &e1,
4350 const vector_expression<E2> &e2) {
4351 BOOST_STATIC_ASSERT (E2::complexity == 0);
4352 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4353 typename E2::value_type, E2>::storage_category storage_category;
4354 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4355 typename E2::value_type, E2>::orientation_category orientation_category;
4356 return prod (e1, e2, storage_category (), orientation_category ());
4357}
4358
4359template<class E1, class E2>
4360BOOST_UBLAS_INLINE
4361typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4362typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4363prec_prod (const matrix_expression<E1> &e1,
4364 const vector_expression<E2> &e2,
4365 unknown_storage_tag,
4366 row_major_tag) {
4367 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4368 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
4369 return expression_type (e1 (), e2 ());
4370}
4371
4372// Dispatcher
4373template<class E1, class E2>
4374BOOST_UBLAS_INLINE
4375typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4376typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4377prec_prod (const matrix_expression<E1> &e1,
4378 const vector_expression<E2> &e2) {
4379 BOOST_STATIC_ASSERT (E2::complexity == 0);
4380 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4381 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
4382 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4383 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
4384 return prec_prod (e1, e2, storage_category (), orientation_category ());
4385}
4386
4387template<class V, class E1, class E2>
4388BOOST_UBLAS_INLINE
4389V &
4390prod (const matrix_expression<E1> &e1,
4391 const vector_expression<E2> &e2,
4392 V &v) {
4393 return v.assign (prod (e1, e2));
4394}
4395
4396template<class V, class E1, class E2>
4397BOOST_UBLAS_INLINE
4398V &
4399prec_prod (const matrix_expression<E1> &e1,
4400 const vector_expression<E2> &e2,
4401 V &v) {
4402 return v.assign (prec_prod (e1, e2));
4403}
4404
4405template<class V, class E1, class E2>
4406BOOST_UBLAS_INLINE
4407V
4408prod (const matrix_expression<E1> &e1,
4409 const vector_expression<E2> &e2) {
4410 return V (prod (e1, e2));
4411}
4412
4413template<class V, class E1, class E2>
4414BOOST_UBLAS_INLINE
4415V
4416prec_prod (const matrix_expression<E1> &e1,
4417 const vector_expression<E2> &e2) {
4418 return V (prec_prod (e1, e2));
4419}
4420
4421template<class E1, class E2, class F>
4422class matrix_vector_binary2:
4423 public vector_expression<matrix_vector_binary2<E1, E2, F> > {
4424
4425 typedef E1 expression1_type;
4426 typedef E2 expression2_type;
4427 typedef F functor_type;
4428public:
4429 typedef typename E1::const_closure_type expression1_closure_type;
4430 typedef typename E2::const_closure_type expression2_closure_type;
4431private:
4432 typedef matrix_vector_binary2<E1, E2, F> self_type;
4433public:
4434#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4435 using vector_expression<self_type>::operator ();
4436#endif
4437 static const unsigned complexity = 1;
4438 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
4439 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
4440 typedef typename F::result_type value_type;
4441 typedef value_type const_reference;
4442 typedef const_reference reference;
4443 typedef const self_type const_closure_type;
4444 typedef const_closure_type closure_type;
4445 typedef unknown_storage_tag storage_category;
4446
4447 // Construction and destruction
4448 BOOST_UBLAS_INLINE
4449 matrix_vector_binary2 (const expression1_type &e1, const expression2_type &e2):
4450 e1_ (e1), e2_ (e2) {}
4451
4452 // Accessors
4453 BOOST_UBLAS_INLINE
4454 size_type size () const {
4455 return e2_.size2 ();
4456 }
4457
4458public:
4459 // Expression accessors
4460 BOOST_UBLAS_INLINE
4461 const expression1_closure_type &expression1 () const {
4462 return e1_;
4463 }
4464 BOOST_UBLAS_INLINE
4465 const expression2_closure_type &expression2 () const {
4466 return e2_;
4467 }
4468public:
4469
4470 // Element access
4471 BOOST_UBLAS_INLINE
4472 const_reference operator () (size_type j) const {
4473 return functor_type::apply (e1_, e2_, j);
4474 }
4475
4476 // Closure comparison
4477 BOOST_UBLAS_INLINE
4478 bool same_closure (const matrix_vector_binary2 &mvb2) const {
4479 return (*this).expression1 ().same_closure (mvb2.expression1 ()) &&
4480 (*this).expression2 ().same_closure (mvb2.expression2 ());
4481 }
4482
4483 // Iterator types
4484private:
4485 typedef typename E1::const_iterator const_subiterator1_type;
4486 typedef typename E2::const_iterator2 const_subiterator2_type;
4487 typedef const value_type *const_pointer;
4488
4489public:
4490#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4491 typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
4492 typedef const_iterator iterator;
4493#else
4494 class const_iterator;
4495 typedef const_iterator iterator;
4496#endif
4497
4498 // Element lookup
4499 BOOST_UBLAS_INLINE
4500 const_iterator find (size_type j) const {
4501#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4502 const_subiterator2_type it2 (e2_.find2 (0, 0, j));
4503 return const_iterator (*this, it2.index2 ());
4504#else
4505 return const_iterator (*this, e2_.find2 (0, 0, j));
4506#endif
4507 }
4508
4509
4510#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4511 class const_iterator:
4512 public container_const_reference<matrix_vector_binary2>,
4513 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
4514 typename E2::const_iterator2::iterator_category>::iterator_category>::template
4515 iterator_base<const_iterator, value_type>::type {
4516 public:
4517 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
4518 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
4519 typedef typename matrix_vector_binary2::difference_type difference_type;
4520 typedef typename matrix_vector_binary2::value_type value_type;
4521 typedef typename matrix_vector_binary2::const_reference reference;
4522 typedef typename matrix_vector_binary2::const_pointer pointer;
4523
4524 // Construction and destruction
4525#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4526 BOOST_UBLAS_INLINE
4527 const_iterator ():
4528 container_const_reference<self_type> (), it2_ (), e1_begin_ (), e1_end_ () {}
4529 BOOST_UBLAS_INLINE
4530 const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
4531 container_const_reference<self_type> (mvb), it2_ (it2), e1_begin_ (mvb.expression1 ().begin ()), e1_end_ (mvb.expression1 ().end ()) {}
4532#else
4533 BOOST_UBLAS_INLINE
4534 const_iterator ():
4535 container_const_reference<self_type> (), it2_ () {}
4536 BOOST_UBLAS_INLINE
4537 const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
4538 container_const_reference<self_type> (mvb), it2_ (it2) {}
4539#endif
4540
4541 private:
4542 // Dense random access specialization
4543 BOOST_UBLAS_INLINE
4544 value_type dereference (dense_random_access_iterator_tag) const {
4545 const self_type &mvb = (*this) ();
4546#ifdef BOOST_UBLAS_USE_INDEXING
4547 return mvb (index ());
4548#elif BOOST_UBLAS_USE_ITERATING
4549 difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
4550#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4551 return functor_type::apply (size, e1_begin_, it2_.begin ());
4552#else
4553 return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
4554#endif
4555#else
4556 difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
4557 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
4558#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4559 return functor_type::apply (size, e1_begin_, it2_.begin ());
4560#else
4561 return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
4562#endif
4563 else
4564 return mvb (index ());
4565#endif
4566 }
4567
4568 // Packed bidirectional specialization
4569 BOOST_UBLAS_INLINE
4570 value_type dereference (packed_random_access_iterator_tag) const {
4571#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4572 return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end ());
4573#else
4574 const self_type &mvb = (*this) ();
4575#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4576 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4577 it2_.begin (), it2_.end ());
4578#else
4579 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4580 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
4581 boost::numeric::ublas::end (it2_, iterator2_tag ()));
4582#endif
4583#endif
4584 }
4585
4586 // Sparse bidirectional specialization
4587 BOOST_UBLAS_INLINE
4588 value_type dereference (sparse_bidirectional_iterator_tag) const {
4589#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4590 return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
4591#else
4592 const self_type &mvb = (*this) ();
4593#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4594 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4595 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
4596#else
4597 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4598 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
4599 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
4600#endif
4601#endif
4602 }
4603
4604 public:
4605 // Arithmetic
4606 BOOST_UBLAS_INLINE
4607 const_iterator &operator ++ () {
4608 ++ it2_;
4609 return *this;
4610 }
4611 BOOST_UBLAS_INLINE
4612 const_iterator &operator -- () {
4613 -- it2_;
4614 return *this;
4615 }
4616 BOOST_UBLAS_INLINE
4617 const_iterator &operator += (difference_type n) {
4618 it2_ += n;
4619 return *this;
4620 }
4621 BOOST_UBLAS_INLINE
4622 const_iterator &operator -= (difference_type n) {
4623 it2_ -= n;
4624 return *this;
4625 }
4626 BOOST_UBLAS_INLINE
4627 difference_type operator - (const const_iterator &it) const {
4628 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4629 return it2_ - it.it2_;
4630 }
4631
4632 // Dereference
4633 BOOST_UBLAS_INLINE
4634 const_reference operator * () const {
4635 return dereference (iterator_category ());
4636 }
4637 BOOST_UBLAS_INLINE
4638 const_reference operator [] (difference_type n) const {
4639 return *(*this + n);
4640 }
4641
4642 // Index
4643 BOOST_UBLAS_INLINE
4644 size_type index () const {
4645 return it2_.index2 ();
4646 }
4647
4648 // Assignment
4649 BOOST_UBLAS_INLINE
4650 const_iterator &operator = (const const_iterator &it) {
4651 container_const_reference<self_type>::assign (&it ());
4652 it2_ = it.it2_;
4653#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4654 e1_begin_ = it.e1_begin_;
4655 e1_end_ = it.e1_end_;
4656#endif
4657 return *this;
4658 }
4659
4660 // Comparison
4661 BOOST_UBLAS_INLINE
4662 bool operator == (const const_iterator &it) const {
4663 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4664 return it2_ == it.it2_;
4665 }
4666 BOOST_UBLAS_INLINE
4667 bool operator < (const const_iterator &it) const {
4668 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4669 return it2_ < it.it2_;
4670 }
4671
4672 private:
4673 const_subiterator2_type it2_;
4674#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4675 // Mutable due to assignment
4676 /* const */ const_subiterator1_type e1_begin_;
4677 /* const */ const_subiterator1_type e1_end_;
4678#endif
4679 };
4680#endif
4681
4682 BOOST_UBLAS_INLINE
4683 const_iterator begin () const {
4684 return find (j: 0);
4685 }
4686 BOOST_UBLAS_INLINE
4687 const_iterator cbegin () const {
4688 return begin ();
4689 }
4690 BOOST_UBLAS_INLINE
4691 const_iterator end () const {
4692 return find (j: size ());
4693 }
4694 BOOST_UBLAS_INLINE
4695 const_iterator cend () const {
4696 return end ();
4697 }
4698
4699 // Reverse iterator
4700 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
4701
4702 BOOST_UBLAS_INLINE
4703 const_reverse_iterator rbegin () const {
4704 return const_reverse_iterator (end ());
4705 }
4706 BOOST_UBLAS_INLINE
4707 const_reverse_iterator crbegin () const {
4708 return rbegin ();
4709 }
4710 BOOST_UBLAS_INLINE
4711 const_reverse_iterator rend () const {
4712 return const_reverse_iterator (begin ());
4713 }
4714 BOOST_UBLAS_INLINE
4715 const_reverse_iterator crend () const {
4716 return rend ();
4717 }
4718
4719private:
4720 expression1_closure_type e1_;
4721 expression2_closure_type e2_;
4722};
4723
4724template<class T1, class E1, class T2, class E2>
4725struct matrix_vector_binary2_traits {
4726 typedef unknown_storage_tag storage_category;
4727 typedef column_major_tag orientation_category;
4728 typedef typename promote_traits<T1, T2>::promote_type promote_type;
4729 typedef matrix_vector_binary2<E1, E2, matrix_vector_prod2<E1, E2, promote_type> > expression_type;
4730#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
4731 typedef expression_type result_type;
4732#else
4733 typedef typename E2::vector_temporary_type result_type;
4734#endif
4735};
4736
4737template<class E1, class E2>
4738BOOST_UBLAS_INLINE
4739typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4740typename E2::value_type, E2>::result_type
4741prod (const vector_expression<E1> &e1,
4742 const matrix_expression<E2> &e2,
4743 unknown_storage_tag,
4744 column_major_tag) {
4745 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4746 typename E2::value_type, E2>::expression_type expression_type;
4747 return expression_type (e1 (), e2 ());
4748}
4749
4750// Dispatcher
4751template<class E1, class E2>
4752BOOST_UBLAS_INLINE
4753typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4754typename E2::value_type, E2>::result_type
4755prod (const vector_expression<E1> &e1,
4756 const matrix_expression<E2> &e2) {
4757 BOOST_STATIC_ASSERT (E1::complexity == 0);
4758 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4759 typename E2::value_type, E2>::storage_category storage_category;
4760 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4761 typename E2::value_type, E2>::orientation_category orientation_category;
4762 return prod (e1, e2, storage_category (), orientation_category ());
4763}
4764
4765template<class E1, class E2>
4766BOOST_UBLAS_INLINE
4767typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4768typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4769prec_prod (const vector_expression<E1> &e1,
4770 const matrix_expression<E2> &e2,
4771 unknown_storage_tag,
4772 column_major_tag) {
4773 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4774 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
4775 return expression_type (e1 (), e2 ());
4776}
4777
4778// Dispatcher
4779template<class E1, class E2>
4780BOOST_UBLAS_INLINE
4781typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4782typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4783prec_prod (const vector_expression<E1> &e1,
4784 const matrix_expression<E2> &e2) {
4785 BOOST_STATIC_ASSERT (E1::complexity == 0);
4786 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4787 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
4788 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4789 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
4790 return prec_prod (e1, e2, storage_category (), orientation_category ());
4791}
4792
4793template<class V, class E1, class E2>
4794BOOST_UBLAS_INLINE
4795V &
4796prod (const vector_expression<E1> &e1,
4797 const matrix_expression<E2> &e2,
4798 V &v) {
4799 return v.assign (prod (e1, e2));
4800}
4801
4802template<class V, class E1, class E2>
4803BOOST_UBLAS_INLINE
4804V &
4805prec_prod (const vector_expression<E1> &e1,
4806 const matrix_expression<E2> &e2,
4807 V &v) {
4808 return v.assign (prec_prod (e1, e2));
4809}
4810
4811template<class V, class E1, class E2>
4812BOOST_UBLAS_INLINE
4813V
4814prod (const vector_expression<E1> &e1,
4815 const matrix_expression<E2> &e2) {
4816 return V (prod (e1, e2));
4817}
4818
4819template<class V, class E1, class E2>
4820BOOST_UBLAS_INLINE
4821V
4822prec_prod (const vector_expression<E1> &e1,
4823 const matrix_expression<E2> &e2) {
4824 return V (prec_prod (e1, e2));
4825}
4826
4827template<class E1, class E2, class F>
4828class matrix_matrix_binary:
4829 public matrix_expression<matrix_matrix_binary<E1, E2, F> > {
4830
4831public:
4832 typedef E1 expression1_type;
4833 typedef E2 expression2_type;
4834private:
4835 typedef F functor_type;
4836public:
4837 typedef typename E1::const_closure_type expression1_closure_type;
4838 typedef typename E2::const_closure_type expression2_closure_type;
4839private:
4840 typedef matrix_matrix_binary<E1, E2, F> self_type;
4841public:
4842#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4843 using matrix_expression<self_type>::operator ();
4844#endif
4845 static const unsigned complexity = 1;
4846 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
4847 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
4848 typedef typename F::result_type value_type;
4849 typedef value_type const_reference;
4850 typedef const_reference reference;
4851 typedef const self_type const_closure_type;
4852 typedef const_closure_type closure_type;
4853 typedef unknown_orientation_tag orientation_category;
4854 typedef unknown_storage_tag storage_category;
4855
4856 // Construction and destruction
4857 BOOST_UBLAS_INLINE
4858 matrix_matrix_binary (const expression1_type &e1, const expression2_type &e2):
4859 e1_ (e1), e2_ (e2) {}
4860
4861 // Accessors
4862 BOOST_UBLAS_INLINE
4863 size_type size1 () const {
4864 return e1_.size1 ();
4865 }
4866 BOOST_UBLAS_INLINE
4867 size_type size2 () const {
4868 return e2_.size2 ();
4869 }
4870
4871public:
4872 // Expression accessors
4873 BOOST_UBLAS_INLINE
4874 const expression1_closure_type &expression1 () const {
4875 return e1_;
4876 }
4877 BOOST_UBLAS_INLINE
4878 const expression2_closure_type &expression2 () const {
4879 return e2_;
4880 }
4881
4882public:
4883 // Element access
4884 BOOST_UBLAS_INLINE
4885 const_reference operator () (size_type i, size_type j) const {
4886 return functor_type::apply (e1_, e2_, i, j);
4887 }
4888
4889 // Element access
4890 BOOST_UBLAS_INLINE
4891 const_reference operator () (size_type i) const {
4892 return functor_type::apply (e1_, e2_, i);
4893 }
4894
4895 // Closure comparison
4896 BOOST_UBLAS_INLINE
4897 bool same_closure (const matrix_matrix_binary &mmb) const {
4898 return (*this).expression1 ().same_closure (mmb.expression1 ()) &&
4899 (*this).expression2 ().same_closure (mmb.expression2 ());
4900 }
4901
4902 // Iterator types
4903private:
4904 typedef typename E1::const_iterator1 const_iterator11_type;
4905 typedef typename E1::const_iterator2 const_iterator12_type;
4906 typedef typename E2::const_iterator1 const_iterator21_type;
4907 typedef typename E2::const_iterator2 const_iterator22_type;
4908 typedef const value_type *const_pointer;
4909
4910public:
4911#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4912 typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
4913 typename const_iterator22_type::iterator_category>::iterator_category iterator_category;
4914 typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
4915 typedef const_iterator1 iterator1;
4916 typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
4917 typedef const_iterator2 iterator2;
4918#else
4919 class const_iterator1;
4920 typedef const_iterator1 iterator1;
4921 class const_iterator2;
4922 typedef const_iterator2 iterator2;
4923#endif
4924 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
4925 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
4926
4927 // Element lookup
4928 BOOST_UBLAS_INLINE
4929 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
4930 // FIXME sparse matrix tests fail!
4931 // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
4932 const_iterator11_type it11 (e1_.find1 (0, i, 0));
4933#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4934 return const_iterator1 (*this, it11.index1 (), j);
4935#else
4936 // FIXME sparse matrix tests fail!
4937 // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
4938 const_iterator22_type it22 (e2_.find2 (0, 0, j));
4939 return const_iterator1 (*this, it11, it22);
4940#endif
4941 }
4942 BOOST_UBLAS_INLINE
4943 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
4944 // FIXME sparse matrix tests fail!
4945 // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
4946 const_iterator22_type it22 (e2_.find2 (0, 0, j));
4947#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4948 return const_iterator2 (*this, i, it22.index2 ());
4949#else
4950 // FIXME sparse matrix tests fail!
4951 // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
4952 const_iterator11_type it11 (e1_.find1 (0, i, 0));
4953 return const_iterator2 (*this, it11, it22);
4954#endif
4955 }
4956
4957
4958#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4959 class const_iterator1:
4960 public container_const_reference<matrix_matrix_binary>,
4961 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4962 typename E2::const_iterator2::iterator_category>::iterator_category>::template
4963 iterator_base<const_iterator1, value_type>::type {
4964 public:
4965 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4966 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
4967 typedef typename matrix_matrix_binary::difference_type difference_type;
4968 typedef typename matrix_matrix_binary::value_type value_type;
4969 typedef typename matrix_matrix_binary::const_reference reference;
4970 typedef typename matrix_matrix_binary::const_pointer pointer;
4971
4972 typedef const_iterator2 dual_iterator_type;
4973 typedef const_reverse_iterator2 dual_reverse_iterator_type;
4974
4975 // Construction and destruction
4976#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4977 BOOST_UBLAS_INLINE
4978 const_iterator1 ():
4979 container_const_reference<self_type> (), it1_ (), it2_ (), it2_begin_ (), it2_end_ () {}
4980 BOOST_UBLAS_INLINE
4981 const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
4982 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it2_begin_ (it2.begin ()), it2_end_ (it2.end ()) {}
4983#else
4984 BOOST_UBLAS_INLINE
4985 const_iterator1 ():
4986 container_const_reference<self_type> (), it1_ (), it2_ () {}
4987 BOOST_UBLAS_INLINE
4988 const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
4989 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
4990#endif
4991
4992 private:
4993 // Random access specialization
4994 BOOST_UBLAS_INLINE
4995 value_type dereference (dense_random_access_iterator_tag) const {
4996 const self_type &mmb = (*this) ();
4997#ifdef BOOST_UBLAS_USE_INDEXING
4998 return mmb (index1 (), index2 ());
4999#elif BOOST_UBLAS_USE_ITERATING
5000 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
5001#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5002 return functor_type::apply (size, it1_.begin (), it2_begin_);
5003#else
5004 return functor_type::apply (size, it1_.begin (), it2_.begin ());
5005#endif
5006#else
5007 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
5008 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
5009#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5010 return functor_type::apply (size, it1_.begin (), it2_begin_);
5011#else
5012 return functor_type::apply (size, it1_.begin (), it2_.begin ());
5013#endif
5014 else
5015 return mmb (index1 (), index2 ());
5016#endif
5017 }
5018
5019 // Packed bidirectional specialization
5020 BOOST_UBLAS_INLINE
5021 value_type dereference (packed_random_access_iterator_tag) const {
5022#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5023 return functor_type::apply (it1_.begin (), it1_.end (),
5024 it2_begin_, it2_end_, packed_random_access_iterator_tag ());
5025#else
5026#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5027 return functor_type::apply (it1_.begin (), it1_.end (),
5028 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
5029#else
5030 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
5031 boost::numeric::ublas::end (it1_, iterator1_tag ()),
5032 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
5033 boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
5034#endif
5035#endif
5036 }
5037
5038 // Sparse bidirectional specialization
5039 BOOST_UBLAS_INLINE
5040 value_type dereference (sparse_bidirectional_iterator_tag) const {
5041#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5042 return functor_type::apply (it1_.begin (), it1_.end (),
5043 it2_begin_, it2_end_, sparse_bidirectional_iterator_tag ());
5044#else
5045#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5046 return functor_type::apply (it1_.begin (), it1_.end (),
5047 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
5048#else
5049 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
5050 boost::numeric::ublas::end (it1_, iterator1_tag ()),
5051 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
5052 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
5053#endif
5054#endif
5055 }
5056
5057 public:
5058 // Arithmetic
5059 BOOST_UBLAS_INLINE
5060 const_iterator1 &operator ++ () {
5061 ++ it1_;
5062 return *this;
5063 }
5064 BOOST_UBLAS_INLINE
5065 const_iterator1 &operator -- () {
5066 -- it1_;
5067 return *this;
5068 }
5069 BOOST_UBLAS_INLINE
5070 const_iterator1 &operator += (difference_type n) {
5071 it1_ += n;
5072 return *this;
5073 }
5074 BOOST_UBLAS_INLINE
5075 const_iterator1 &operator -= (difference_type n) {
5076 it1_ -= n;
5077 return *this;
5078 }
5079 BOOST_UBLAS_INLINE
5080 difference_type operator - (const const_iterator1 &it) const {
5081 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5082 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
5083 return it1_ - it.it1_;
5084 }
5085
5086 // Dereference
5087 BOOST_UBLAS_INLINE
5088 const_reference operator * () const {
5089 return dereference (iterator_category ());
5090 }
5091 BOOST_UBLAS_INLINE
5092 const_reference operator [] (difference_type n) const {
5093 return *(*this + n);
5094 }
5095
5096#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5097 BOOST_UBLAS_INLINE
5098#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5099 typename self_type::
5100#endif
5101 const_iterator2 begin () const {
5102 return (*this) ().find2 (1, index1 (), 0);
5103 }
5104 BOOST_UBLAS_INLINE
5105#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5106 typename self_type::
5107#endif
5108 const_iterator2 cbegin () const {
5109 return begin ();
5110 }
5111 BOOST_UBLAS_INLINE
5112#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5113 typename self_type::
5114#endif
5115 const_iterator2 end () const {
5116 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
5117 }
5118 BOOST_UBLAS_INLINE
5119#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5120 typename self_type::
5121#endif
5122 const_iterator2 cend () const {
5123 return end ();
5124 }
5125 BOOST_UBLAS_INLINE
5126#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5127 typename self_type::
5128#endif
5129 const_reverse_iterator2 rbegin () const {
5130 return const_reverse_iterator2 (end ());
5131 }
5132 BOOST_UBLAS_INLINE
5133#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5134 typename self_type::
5135#endif
5136 const_reverse_iterator2 crbegin () const {
5137 return rbegin ();
5138 }
5139 BOOST_UBLAS_INLINE
5140#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5141 typename self_type::
5142#endif
5143 const_reverse_iterator2 rend () const {
5144 return const_reverse_iterator2 (begin ());
5145 }
5146 BOOST_UBLAS_INLINE
5147#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5148 typename self_type::
5149#endif
5150 const_reverse_iterator2 crend () const {
5151 return rend ();
5152 }
5153#endif
5154
5155 // Indices
5156 BOOST_UBLAS_INLINE
5157 size_type index1 () const {
5158 return it1_.index1 ();
5159 }
5160 BOOST_UBLAS_INLINE
5161 size_type index2 () const {
5162 return it2_.index2 ();
5163 }
5164
5165 // Assignment
5166 BOOST_UBLAS_INLINE
5167 const_iterator1 &operator = (const const_iterator1 &it) {
5168 container_const_reference<self_type>::assign (&it ());
5169 it1_ = it.it1_;
5170 it2_ = it.it2_;
5171#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5172 it2_begin_ = it.it2_begin_;
5173 it2_end_ = it.it2_end_;
5174#endif
5175 return *this;
5176 }
5177
5178 // Comparison
5179 BOOST_UBLAS_INLINE
5180 bool operator == (const const_iterator1 &it) const {
5181 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5182 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
5183 return it1_ == it.it1_;
5184 }
5185 BOOST_UBLAS_INLINE
5186 bool operator < (const const_iterator1 &it) const {
5187 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5188 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
5189 return it1_ < it.it1_;
5190 }
5191
5192 private:
5193 const_iterator11_type it1_;
5194 // Mutable due to assignment
5195 /* const */ const_iterator22_type it2_;
5196#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5197 /* const */ const_iterator21_type it2_begin_;
5198 /* const */ const_iterator21_type it2_end_;
5199#endif
5200 };
5201#endif
5202
5203 BOOST_UBLAS_INLINE
5204 const_iterator1 begin1 () const {
5205 return find1 (0, i: 0, j: 0);
5206 }
5207 BOOST_UBLAS_INLINE
5208 const_iterator1 cbegin1 () const {
5209 return begin1 ();
5210 }
5211 BOOST_UBLAS_INLINE
5212 const_iterator1 end1 () const {
5213 return find1 (0, i: size1 (), j: 0);
5214 }
5215 BOOST_UBLAS_INLINE
5216 const_iterator1 cend1 () const {
5217 return end1 ();
5218 }
5219
5220#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
5221 class const_iterator2:
5222 public container_const_reference<matrix_matrix_binary>,
5223 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
5224 typename E2::const_iterator2::iterator_category>::iterator_category>::template
5225 iterator_base<const_iterator2, value_type>::type {
5226 public:
5227 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
5228 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
5229 typedef typename matrix_matrix_binary::difference_type difference_type;
5230 typedef typename matrix_matrix_binary::value_type value_type;
5231 typedef typename matrix_matrix_binary::const_reference reference;
5232 typedef typename matrix_matrix_binary::const_pointer pointer;
5233
5234 typedef const_iterator1 dual_iterator_type;
5235 typedef const_reverse_iterator1 dual_reverse_iterator_type;
5236
5237 // Construction and destruction
5238#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5239 BOOST_UBLAS_INLINE
5240 const_iterator2 ():
5241 container_const_reference<self_type> (), it1_ (), it2_ (), it1_begin_ (), it1_end_ () {}
5242 BOOST_UBLAS_INLINE
5243 const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
5244 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it1_begin_ (it1.begin ()), it1_end_ (it1.end ()) {}
5245#else
5246 BOOST_UBLAS_INLINE
5247 const_iterator2 ():
5248 container_const_reference<self_type> (), it1_ (), it2_ () {}
5249 BOOST_UBLAS_INLINE
5250 const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
5251 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
5252#endif
5253
5254 private:
5255 // Random access specialization
5256 BOOST_UBLAS_INLINE
5257 value_type dereference (dense_random_access_iterator_tag) const {
5258 const self_type &mmb = (*this) ();
5259#ifdef BOOST_UBLAS_USE_INDEXING
5260 return mmb (index1 (), index2 ());
5261#elif BOOST_UBLAS_USE_ITERATING
5262 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
5263#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5264 return functor_type::apply (size, it1_begin_, it2_.begin ());
5265#else
5266 return functor_type::apply (size, it1_.begin (), it2_.begin ());
5267#endif
5268#else
5269 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
5270 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
5271#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5272 return functor_type::apply (size, it1_begin_, it2_.begin ());
5273#else
5274 return functor_type::apply (size, it1_.begin (), it2_.begin ());
5275#endif
5276 else
5277 return mmb (index1 (), index2 ());
5278#endif
5279 }
5280
5281 // Packed bidirectional specialization
5282 BOOST_UBLAS_INLINE
5283 value_type dereference (packed_random_access_iterator_tag) const {
5284#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5285 return functor_type::apply (it1_begin_, it1_end_,
5286 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
5287#else
5288#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5289 return functor_type::apply (it1_.begin (), it1_.end (),
5290 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
5291#else
5292 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
5293 boost::numeric::ublas::end (it1_, iterator1_tag ()),
5294 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
5295 boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
5296#endif
5297#endif
5298 }
5299
5300 // Sparse bidirectional specialization
5301 BOOST_UBLAS_INLINE
5302 value_type dereference (sparse_bidirectional_iterator_tag) const {
5303#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5304 return functor_type::apply (it1_begin_, it1_end_,
5305 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
5306#else
5307#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5308 return functor_type::apply (it1_.begin (), it1_.end (),
5309 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
5310#else
5311 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
5312 boost::numeric::ublas::end (it1_, iterator1_tag ()),
5313 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
5314 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
5315#endif
5316#endif
5317 }
5318
5319 public:
5320 // Arithmetic
5321 BOOST_UBLAS_INLINE
5322 const_iterator2 &operator ++ () {
5323 ++ it2_;
5324 return *this;
5325 }
5326 BOOST_UBLAS_INLINE
5327 const_iterator2 &operator -- () {
5328 -- it2_;
5329 return *this;
5330 }
5331 BOOST_UBLAS_INLINE
5332 const_iterator2 &operator += (difference_type n) {
5333 it2_ += n;
5334 return *this;
5335 }
5336 BOOST_UBLAS_INLINE
5337 const_iterator2 &operator -= (difference_type n) {
5338 it2_ -= n;
5339 return *this;
5340 }
5341 BOOST_UBLAS_INLINE
5342 difference_type operator - (const const_iterator2 &it) const {
5343 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5344 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5345 return it2_ - it.it2_;
5346 }
5347
5348 // Dereference
5349 BOOST_UBLAS_INLINE
5350 const_reference operator * () const {
5351 return dereference (iterator_category ());
5352 }
5353 BOOST_UBLAS_INLINE
5354 const_reference operator [] (difference_type n) const {
5355 return *(*this + n);
5356 }
5357
5358#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5359 BOOST_UBLAS_INLINE
5360#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5361 typename self_type::
5362#endif
5363 const_iterator1 begin () const {
5364 return (*this) ().find1 (1, 0, index2 ());
5365 }
5366 BOOST_UBLAS_INLINE
5367#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5368 typename self_type::
5369#endif
5370 const_iterator1 cbegin () const {
5371 return begin ();
5372 }
5373 BOOST_UBLAS_INLINE
5374#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5375 typename self_type::
5376#endif
5377 const_iterator1 end () const {
5378 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
5379 }
5380 BOOST_UBLAS_INLINE
5381#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5382 typename self_type::
5383#endif
5384 const_iterator1 cend () const {
5385 return end ();
5386 }
5387 BOOST_UBLAS_INLINE
5388#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5389 typename self_type::
5390#endif
5391 const_reverse_iterator1 rbegin () const {
5392 return const_reverse_iterator1 (end ());
5393 }
5394 BOOST_UBLAS_INLINE
5395#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5396 typename self_type::
5397#endif
5398 const_reverse_iterator1 crbegin () const {
5399 return rbegin ();
5400 }
5401 BOOST_UBLAS_INLINE
5402#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5403 typename self_type::
5404#endif
5405 const_reverse_iterator1 rend () const {
5406 return const_reverse_iterator1 (begin ());
5407 }
5408 BOOST_UBLAS_INLINE
5409#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5410 typename self_type::
5411#endif
5412 const_reverse_iterator1 crend () const {
5413 return rend ();
5414 }
5415#endif
5416
5417 // Indices
5418 BOOST_UBLAS_INLINE
5419 size_type index1 () const {
5420 return it1_.index1 ();
5421 }
5422 BOOST_UBLAS_INLINE
5423 size_type index2 () const {
5424 return it2_.index2 ();
5425 }
5426
5427 // Assignment
5428 BOOST_UBLAS_INLINE
5429 const_iterator2 &operator = (const const_iterator2 &it) {
5430 container_const_reference<self_type>::assign (&it ());
5431 it1_ = it.it1_;
5432 it2_ = it.it2_;
5433#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5434 it1_begin_ = it.it1_begin_;
5435 it1_end_ = it.it1_end_;
5436#endif
5437 return *this;
5438 }
5439
5440 // Comparison
5441 BOOST_UBLAS_INLINE
5442 bool operator == (const const_iterator2 &it) const {
5443 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5444 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5445 return it2_ == it.it2_;
5446 }
5447 BOOST_UBLAS_INLINE
5448 bool operator < (const const_iterator2 &it) const {
5449 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5450 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5451 return it2_ < it.it2_;
5452 }
5453
5454 private:
5455 // Mutable due to assignment
5456 /* const */ const_iterator11_type it1_;
5457 const_iterator22_type it2_;
5458#ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5459 /* const */ const_iterator12_type it1_begin_;
5460 /* const */ const_iterator12_type it1_end_;
5461#endif
5462 };
5463#endif
5464
5465 BOOST_UBLAS_INLINE
5466 const_iterator2 begin2 () const {
5467 return find2 (0, i: 0, j: 0);
5468 }
5469 BOOST_UBLAS_INLINE
5470 const_iterator2 cbegin2 () const {
5471 return begin2 ();
5472 }
5473 BOOST_UBLAS_INLINE
5474 const_iterator2 end2 () const {
5475 return find2 (0, i: 0, j: size2 ());
5476 }
5477 BOOST_UBLAS_INLINE
5478 const_iterator2 cend2 () const {
5479 return end2 ();
5480 }
5481
5482 // Reverse iterators
5483
5484 BOOST_UBLAS_INLINE
5485 const_reverse_iterator1 rbegin1 () const {
5486 return const_reverse_iterator1 (end1 ());
5487 }
5488 BOOST_UBLAS_INLINE
5489 const_reverse_iterator1 crbegin1 () const {
5490 return rbegin1 ();
5491 }
5492 BOOST_UBLAS_INLINE
5493 const_reverse_iterator1 rend1 () const {
5494 return const_reverse_iterator1 (begin1 ());
5495 }
5496 BOOST_UBLAS_INLINE
5497 const_reverse_iterator1 crend1 () const {
5498 return rend1 ();
5499 }
5500
5501 BOOST_UBLAS_INLINE
5502 const_reverse_iterator2 rbegin2 () const {
5503 return const_reverse_iterator2 (end2 ());
5504 }
5505 BOOST_UBLAS_INLINE
5506 const_reverse_iterator2 crbegin2 () const {
5507 return rbegin2 ();
5508 }
5509 BOOST_UBLAS_INLINE
5510 const_reverse_iterator2 rend2 () const {
5511 return const_reverse_iterator2 (begin2 ());
5512 }
5513 BOOST_UBLAS_INLINE
5514 const_reverse_iterator2 crend2 () const {
5515 return rend2 ();
5516 }
5517
5518private:
5519 expression1_closure_type e1_;
5520 expression2_closure_type e2_;
5521};
5522
5523template<class T1, class E1, class T2, class E2>
5524struct matrix_matrix_binary_traits {
5525 typedef unknown_storage_tag storage_category;
5526 typedef unknown_orientation_tag orientation_category;
5527 typedef typename promote_traits<T1, T2>::promote_type promote_type;
5528 typedef matrix_matrix_binary<E1, E2, matrix_matrix_prod<E1, E2, promote_type> > expression_type;
5529#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
5530 typedef expression_type result_type;
5531#else
5532 typedef typename E1::matrix_temporary_type result_type;
5533#endif
5534};
5535
5536template<class E1, class E2>
5537BOOST_UBLAS_INLINE
5538typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5539typename E2::value_type, E2>::result_type
5540prod (const matrix_expression<E1> &e1,
5541 const matrix_expression<E2> &e2,
5542 unknown_storage_tag,
5543 unknown_orientation_tag) {
5544 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5545 typename E2::value_type, E2>::expression_type expression_type;
5546 return expression_type (e1 (), e2 ());
5547}
5548
5549// Dispatcher
5550template<class E1, class E2>
5551BOOST_UBLAS_INLINE
5552typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5553typename E2::value_type, E2>::result_type
5554prod (const matrix_expression<E1> &e1,
5555 const matrix_expression<E2> &e2) {
5556 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
5557 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5558 typename E2::value_type, E2>::storage_category storage_category;
5559 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5560 typename E2::value_type, E2>::orientation_category orientation_category;
5561 return prod (e1, e2, storage_category (), orientation_category ());
5562}
5563
5564template<class E1, class E2>
5565BOOST_UBLAS_INLINE
5566typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5567typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
5568prec_prod (const matrix_expression<E1> &e1,
5569 const matrix_expression<E2> &e2,
5570 unknown_storage_tag,
5571 unknown_orientation_tag) {
5572 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5573 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
5574 return expression_type (e1 (), e2 ());
5575}
5576
5577// Dispatcher
5578template<class E1, class E2>
5579BOOST_UBLAS_INLINE
5580typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5581typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
5582prec_prod (const matrix_expression<E1> &e1,
5583 const matrix_expression<E2> &e2) {
5584 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
5585 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5586 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
5587 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5588 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
5589 return prec_prod (e1, e2, storage_category (), orientation_category ());
5590}
5591
5592template<class M, class E1, class E2>
5593BOOST_UBLAS_INLINE
5594M &
5595prod (const matrix_expression<E1> &e1,
5596 const matrix_expression<E2> &e2,
5597 M &m) {
5598 return m.assign (prod (e1, e2));
5599}
5600
5601template<class M, class E1, class E2>
5602BOOST_UBLAS_INLINE
5603M &
5604prec_prod (const matrix_expression<E1> &e1,
5605 const matrix_expression<E2> &e2,
5606 M &m) {
5607 return m.assign (prec_prod (e1, e2));
5608}
5609
5610template<class M, class E1, class E2>
5611BOOST_UBLAS_INLINE
5612M
5613prod (const matrix_expression<E1> &e1,
5614 const matrix_expression<E2> &e2) {
5615 return M (prod (e1, e2));
5616}
5617
5618template<class M, class E1, class E2>
5619BOOST_UBLAS_INLINE
5620M
5621prec_prod (const matrix_expression<E1> &e1,
5622 const matrix_expression<E2> &e2) {
5623 return M (prec_prod (e1, e2));
5624}
5625
5626template<class E, class F>
5627class matrix_scalar_unary:
5628 public scalar_expression<matrix_scalar_unary<E, F> > {
5629public:
5630 typedef E expression_type;
5631 typedef F functor_type;
5632 typedef typename F::result_type value_type;
5633 typedef typename E::const_closure_type expression_closure_type;
5634
5635 // Construction and destruction
5636 BOOST_UBLAS_INLINE
5637 explicit matrix_scalar_unary (const expression_type &e):
5638 e_ (e) {}
5639
5640private:
5641 // Expression accessors
5642 BOOST_UBLAS_INLINE
5643 const expression_closure_type &expression () const {
5644 return e_;
5645 }
5646
5647public:
5648 BOOST_UBLAS_INLINE
5649 operator value_type () const {
5650 return functor_type::apply (e_);
5651 }
5652
5653private:
5654 expression_closure_type e_;
5655};
5656
5657template<class E, class F>
5658struct matrix_scalar_unary_traits {
5659 typedef matrix_scalar_unary<E, F> expression_type;
5660#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
5661 typedef expression_type result_type;
5662#else
5663 typedef typename F::result_type result_type;
5664#endif
5665};
5666
5667template<class E>
5668BOOST_UBLAS_INLINE
5669typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::result_type
5670norm_1 (const matrix_expression<E> &e) {
5671 typedef typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::expression_type expression_type;
5672 return expression_type (e ());
5673}
5674
5675template<class E>
5676BOOST_UBLAS_INLINE
5677typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::result_type
5678norm_frobenius (const matrix_expression<E> &e) {
5679 typedef typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::expression_type expression_type;
5680 return expression_type (e ());
5681}
5682
5683template<class E>
5684BOOST_UBLAS_INLINE
5685typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::result_type
5686norm_inf (const matrix_expression<E> &e) {
5687 typedef typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::expression_type expression_type;
5688 return expression_type (e ());
5689}
5690
5691}}}
5692
5693#endif
5694

source code of include/boost/numeric/ublas/matrix_expression.hpp