New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
triangular.hpp in vendors/XIOS/current/extern/boost/include/boost/numeric/ublas – NEMO

source: vendors/XIOS/current/extern/boost/include/boost/numeric/ublas/triangular.hpp @ 3408

Last change on this file since 3408 was 3408, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

  • Property svn:keywords set to Id
File size: 98.4 KB
Line 
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_TRIANGULAR_
14#define _BOOST_UBLAS_TRIANGULAR_
15
16#include <boost/numeric/ublas/matrix.hpp>
17#include <boost/numeric/ublas/detail/temporary.hpp>
18#include <boost/type_traits/remove_const.hpp>
19
20// Iterators based on ideas of Jeremy Siek
21
22namespace boost { namespace numeric { namespace ublas {
23
24    namespace detail {
25        using namespace boost::numeric::ublas;
26
27        // Matrix resizing algorithm
28        template <class L, class T, class M>
29        BOOST_UBLAS_INLINE
30        void matrix_resize_preserve (M& m, M& temporary) {
31            typedef L layout_type;
32            typedef T triangular_type;
33            typedef typename M::size_type size_type;
34            const size_type msize1 (m.size1 ());        // original size
35            const size_type msize2 (m.size2 ());
36            const size_type size1 (temporary.size1 ());    // new size is specified by temporary
37            const size_type size2 (temporary.size2 ());
38            // Common elements to preserve
39            const size_type size1_min = (std::min) (size1, msize1);
40            const size_type size2_min = (std::min) (size2, msize2);
41            // Order for major and minor sizes
42            const size_type major_size = layout_type::size_M (size1_min, size2_min);
43            const size_type minor_size = layout_type::size_m (size1_min, size2_min);
44            // Indexing copy over major
45            for (size_type major = 0; major != major_size; ++major) {
46                for (size_type minor = 0; minor != minor_size; ++minor) {
47                        // find indexes - use invertability of element_ functions
48                    const size_type i1 = layout_type::index_M(major, minor);
49                    const size_type i2 = layout_type::index_m(major, minor);
50                    if ( triangular_type::other(i1,i2) ) {
51                        temporary.data () [triangular_type::element (layout_type (), i1, size1, i2, size2)] =
52                            m.data() [triangular_type::element (layout_type (), i1, msize1, i2, msize2)];
53                    }
54                }
55            }
56            m.assign_temporary (temporary);
57        }
58    }
59
60    /** \brief A triangular matrix of values of type \c T.
61     *
62     * For a \f$(n \times n )\f$-dimensional lower triangular matrix and if \f$0 \leq i < n\f$, \f$0 \leq j < n\f$ and \f$i>j\f$ holds,
63     * \f$m_{i,j}=0\f$. Furthermore if \f$m_{i,i}=1\f$, the matrix is called unit lower triangular.
64     *
65     * For a \f$(n \times n )\f$-dimensional upper triangular matrix and if \f$0 \leq i < n\f$, \f$0 \leq j < n\f$ and \f$i<j\f$ holds,
66     * \f$m_{i,j}=0\f$. Furthermore if \f$m_{i,i}=1\f$, the matrix is called unit upper triangular.
67     *
68     * The default storage for triangular matrices is packed. Orientation and storage can also be specified.
69     * Default is \c row_major and and unbounded_array. It is \b not required by the storage to initialize
70     * elements of the matrix.
71     *
72     * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
73     * \tparam TRI the type of the triangular matrix. It can either be \c lower or \c upper. Default is \c lower
74     * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
75     * \tparam A the type of Storage array. Default is \c unbounded_array
76     */
77    template<class T, class TRI, class L, class A>
78    class triangular_matrix:
79        public matrix_container<triangular_matrix<T, TRI, L, A> > {
80
81        typedef T *pointer;
82        typedef TRI triangular_type;
83        typedef L layout_type;
84        typedef triangular_matrix<T, TRI, L, A> self_type;
85    public:
86#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
87        using matrix_container<self_type>::operator ();
88#endif
89        typedef typename A::size_type size_type;
90        typedef typename A::difference_type difference_type;
91        typedef T value_type;
92        typedef const T &const_reference;
93        typedef T &reference;
94        typedef A array_type;
95
96        typedef const matrix_reference<const self_type> const_closure_type;
97        typedef matrix_reference<self_type> closure_type;
98        typedef vector<T, A> vector_temporary_type;
99        typedef matrix<T, L, A> matrix_temporary_type;  // general sub-matrix
100        typedef packed_tag storage_category;
101        typedef typename L::orientation_category orientation_category;
102
103        // Construction and destruction
104        BOOST_UBLAS_INLINE
105        triangular_matrix ():
106            matrix_container<self_type> (),
107            size1_ (0), size2_ (0), data_ (0) {}
108        BOOST_UBLAS_INLINE
109        triangular_matrix (size_type size1, size_type size2):
110            matrix_container<self_type> (),
111            size1_ (size1), size2_ (size2), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
112        }
113        BOOST_UBLAS_INLINE
114        triangular_matrix (size_type size1, size_type size2, const array_type &data):
115            matrix_container<self_type> (),
116            size1_ (size1), size2_ (size2), data_ (data) {}
117        BOOST_UBLAS_INLINE
118        triangular_matrix (const triangular_matrix &m):
119            matrix_container<self_type> (),
120            size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
121        template<class AE>
122        BOOST_UBLAS_INLINE
123        triangular_matrix (const matrix_expression<AE> &ae):
124            matrix_container<self_type> (),
125            size1_ (ae ().size1 ()), size2_ (ae ().size2 ()),
126            data_ (triangular_type::packed_size (layout_type (), size1_, size2_)) {
127            matrix_assign<scalar_assign> (*this, ae);
128        }
129
130        // Accessors
131        BOOST_UBLAS_INLINE
132        size_type size1 () const {
133            return size1_;
134        }
135        BOOST_UBLAS_INLINE
136        size_type size2 () const {
137            return size2_;
138        }
139
140        // Storage accessors
141        BOOST_UBLAS_INLINE
142        const array_type &data () const {
143            return data_;
144        }
145        BOOST_UBLAS_INLINE
146        array_type &data () {
147            return data_;
148        }
149
150        // Resizing
151        BOOST_UBLAS_INLINE
152        void resize (size_type size1, size_type size2, bool preserve = true) {
153            if (preserve) {
154                self_type temporary (size1, size2);
155                detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary);
156            }
157            else {
158                data ().resize (triangular_type::packed_size (layout_type (), size1, size2));
159                size1_ = size1;
160                size2_ = size2;
161            }
162        }
163        BOOST_UBLAS_INLINE
164        void resize_packed_preserve (size_type size1, size_type size2) {
165            size1_ = size1;
166            size2_ = size2;
167            data ().resize (triangular_type::packed_size (layout_type (), size1_, size2_), value_type ());
168        }
169
170        // Element access
171        BOOST_UBLAS_INLINE
172        const_reference operator () (size_type i, size_type j) const {
173            BOOST_UBLAS_CHECK (i < size1_, bad_index ());
174            BOOST_UBLAS_CHECK (j < size2_, bad_index ());
175            if (triangular_type::other (i, j))
176                return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
177            else if (triangular_type::one (i, j))
178                return one_;
179            else
180                return zero_;
181        }
182        BOOST_UBLAS_INLINE
183        reference at_element (size_type i, size_type j) {
184            BOOST_UBLAS_CHECK (i < size1_, bad_index ());
185            BOOST_UBLAS_CHECK (j < size2_, bad_index ());
186            return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
187        }
188        BOOST_UBLAS_INLINE
189        reference operator () (size_type i, size_type j) {
190            BOOST_UBLAS_CHECK (i < size1_, bad_index ());
191            BOOST_UBLAS_CHECK (j < size2_, bad_index ());
192            if (!triangular_type::other (i, j)) {
193                bad_index ().raise ();
194                // NEVER reached
195            }
196            return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
197        }
198       
199        // Element assignment
200        BOOST_UBLAS_INLINE
201        reference insert_element (size_type i, size_type j, const_reference t) {
202            return (operator () (i, j) = t);
203        }
204        BOOST_UBLAS_INLINE
205        void erase_element (size_type i, size_type j) {
206            operator () (i, j) = value_type/*zero*/();
207        }
208       
209        // Zeroing
210        BOOST_UBLAS_INLINE
211        void clear () {
212            // data ().clear ();
213            std::fill (data ().begin (), data ().end (), value_type/*zero*/());
214        }
215
216        // Assignment
217        BOOST_UBLAS_INLINE
218        triangular_matrix &operator = (const triangular_matrix &m) {
219            size1_ = m.size1_;
220            size2_ = m.size2_;
221            data () = m.data ();
222            return *this;
223        }
224        BOOST_UBLAS_INLINE
225        triangular_matrix &assign_temporary (triangular_matrix &m) {
226            swap (m);
227            return *this;
228        }
229        template<class AE>
230        BOOST_UBLAS_INLINE
231        triangular_matrix &operator = (const matrix_expression<AE> &ae) {
232            self_type temporary (ae);
233            return assign_temporary (temporary);
234        }
235        template<class AE>
236        BOOST_UBLAS_INLINE
237        triangular_matrix &assign (const matrix_expression<AE> &ae) {
238            matrix_assign<scalar_assign> (*this, ae);
239            return *this;
240        }
241        template<class AE>
242        BOOST_UBLAS_INLINE
243        triangular_matrix& operator += (const matrix_expression<AE> &ae) {
244            self_type temporary (*this + ae);
245            return assign_temporary (temporary);
246        }
247        template<class AE>
248        BOOST_UBLAS_INLINE
249        triangular_matrix &plus_assign (const matrix_expression<AE> &ae) {
250            matrix_assign<scalar_plus_assign> (*this, ae);
251            return *this;
252        }
253        template<class AE>
254        BOOST_UBLAS_INLINE
255        triangular_matrix& operator -= (const matrix_expression<AE> &ae) {
256            self_type temporary (*this - ae);
257            return assign_temporary (temporary);
258        }
259        template<class AE>
260        BOOST_UBLAS_INLINE
261        triangular_matrix &minus_assign (const matrix_expression<AE> &ae) {
262            matrix_assign<scalar_minus_assign> (*this, ae);
263            return *this;
264        }
265        template<class AT>
266        BOOST_UBLAS_INLINE
267        triangular_matrix& operator *= (const AT &at) {
268            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
269            return *this;
270        }
271        template<class AT>
272        BOOST_UBLAS_INLINE
273        triangular_matrix& operator /= (const AT &at) {
274            matrix_assign_scalar<scalar_divides_assign> (*this, at);
275            return *this;
276        }
277
278        // Swapping
279        BOOST_UBLAS_INLINE
280        void swap (triangular_matrix &m) {
281            if (this != &m) {
282                // BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ());
283                std::swap (size1_, m.size1_);
284                std::swap (size2_, m.size2_);
285                data ().swap (m.data ());
286            }
287        }
288        BOOST_UBLAS_INLINE
289        friend void swap (triangular_matrix &m1, triangular_matrix &m2) {
290            m1.swap (m2);
291        }
292
293        // Iterator types
294#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
295        typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
296        typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
297        typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
298        typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
299#else
300        class const_iterator1;
301        class iterator1;
302        class const_iterator2;
303        class iterator2;
304#endif
305        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
306        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
307        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
308        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
309
310        // Element lookup
311        BOOST_UBLAS_INLINE
312        const_iterator1 find1 (int rank, size_type i, size_type j) const {
313            if (rank == 1)
314                i = triangular_type::restrict1 (i, j, size1_, size2_);
315            if (rank == 0)
316                i = triangular_type::global_restrict1 (i, size1_, j, size2_);
317            return const_iterator1 (*this, i, j);
318        }
319        BOOST_UBLAS_INLINE
320        iterator1 find1 (int rank, size_type i, size_type j) {
321            if (rank == 1)
322                i = triangular_type::mutable_restrict1 (i, j, size1_, size2_);
323            if (rank == 0)
324                i = triangular_type::global_mutable_restrict1 (i, size1_, j, size2_);
325            return iterator1 (*this, i, j);
326        }
327        BOOST_UBLAS_INLINE
328        const_iterator2 find2 (int rank, size_type i, size_type j) const {
329            if (rank == 1)
330                j = triangular_type::restrict2 (i, j, size1_, size2_);
331            if (rank == 0)
332                j = triangular_type::global_restrict2 (i, size1_, j, size2_);
333            return const_iterator2 (*this, i, j);
334        }
335        BOOST_UBLAS_INLINE
336        iterator2 find2 (int rank, size_type i, size_type j) {
337            if (rank == 1)
338                j = triangular_type::mutable_restrict2 (i, j, size1_, size2_);
339            if (rank == 0)
340                j = triangular_type::global_mutable_restrict2 (i, size1_, j, size2_);
341            return iterator2 (*this, i, j);
342        }
343
344        // Iterators simply are indices.
345
346#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
347        class const_iterator1:
348            public container_const_reference<triangular_matrix>,
349            public random_access_iterator_base<packed_random_access_iterator_tag,
350                                               const_iterator1, value_type> {
351        public:
352            typedef typename triangular_matrix::value_type value_type;
353            typedef typename triangular_matrix::difference_type difference_type;
354            typedef typename triangular_matrix::const_reference reference;
355            typedef const typename triangular_matrix::pointer pointer;
356
357            typedef const_iterator2 dual_iterator_type;
358            typedef const_reverse_iterator2 dual_reverse_iterator_type;
359
360            // Construction and destruction
361            BOOST_UBLAS_INLINE
362            const_iterator1 ():
363                container_const_reference<self_type> (), it1_ (), it2_ () {}
364            BOOST_UBLAS_INLINE
365            const_iterator1 (const self_type &m, size_type it1, size_type it2):
366                container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
367            BOOST_UBLAS_INLINE
368            const_iterator1 (const iterator1 &it):
369                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
370
371            // Arithmetic
372            BOOST_UBLAS_INLINE
373            const_iterator1 &operator ++ () {
374                ++ it1_;
375                return *this;
376            }
377            BOOST_UBLAS_INLINE
378            const_iterator1 &operator -- () {
379                -- it1_;
380                return *this;
381            }
382            BOOST_UBLAS_INLINE
383            const_iterator1 &operator += (difference_type n) {
384                it1_ += n;
385                return *this;
386            }
387            BOOST_UBLAS_INLINE
388            const_iterator1 &operator -= (difference_type n) {
389                it1_ -= n;
390                return *this;
391            }
392            BOOST_UBLAS_INLINE
393            difference_type operator - (const const_iterator1 &it) const {
394                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
395                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
396                return it1_ - it.it1_;
397            }
398
399            // Dereference
400            BOOST_UBLAS_INLINE
401            const_reference operator * () const {
402                return (*this) () (it1_, it2_);
403            }
404            BOOST_UBLAS_INLINE
405            const_reference operator [] (difference_type n) const {
406                return *(*this + n);
407            }
408
409#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
410            BOOST_UBLAS_INLINE
411#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
412            typename self_type::
413#endif
414            const_iterator2 begin () const {
415                return (*this) ().find2 (1, it1_, 0);
416            }
417            BOOST_UBLAS_INLINE
418#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
419            typename self_type::
420#endif
421            const_iterator2 end () const {
422                return (*this) ().find2 (1, it1_, (*this) ().size2 ());
423            }
424            BOOST_UBLAS_INLINE
425#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
426            typename self_type::
427#endif
428            const_reverse_iterator2 rbegin () const {
429                return const_reverse_iterator2 (end ());
430            }
431            BOOST_UBLAS_INLINE
432#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
433            typename self_type::
434#endif
435            const_reverse_iterator2 rend () const {
436                return const_reverse_iterator2 (begin ());
437            }
438#endif
439
440            // Indices
441            BOOST_UBLAS_INLINE
442            size_type index1 () const {
443                return it1_;
444            }
445            BOOST_UBLAS_INLINE
446            size_type index2 () const {
447                return it2_;
448            }
449
450            // Assignment
451            BOOST_UBLAS_INLINE
452            const_iterator1 &operator = (const const_iterator1 &it) {
453                container_const_reference<self_type>::assign (&it ());
454                it1_ = it.it1_;
455                it2_ = it.it2_;
456                return *this;
457            }
458
459            // Comparison
460            BOOST_UBLAS_INLINE
461            bool operator == (const const_iterator1 &it) const {
462                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
463                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
464                return it1_ == it.it1_;
465            }
466            BOOST_UBLAS_INLINE
467            bool operator < (const const_iterator1 &it) const {
468                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
469                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
470                return it1_ < it.it1_;
471            }
472
473        private:
474            size_type it1_;
475            size_type it2_;
476        };
477#endif
478
479        BOOST_UBLAS_INLINE
480        const_iterator1 begin1 () const {
481            return find1 (0, 0, 0);
482        }
483        BOOST_UBLAS_INLINE
484        const_iterator1 end1 () const {
485            return find1 (0, size1_, 0);
486        }
487
488#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
489        class iterator1:
490            public container_reference<triangular_matrix>,
491            public random_access_iterator_base<packed_random_access_iterator_tag,
492                                               iterator1, value_type> {
493        public:
494            typedef typename triangular_matrix::value_type value_type;
495            typedef typename triangular_matrix::difference_type difference_type;
496            typedef typename triangular_matrix::reference reference;
497            typedef typename triangular_matrix::pointer pointer;
498
499            typedef iterator2 dual_iterator_type;
500            typedef reverse_iterator2 dual_reverse_iterator_type;
501
502            // Construction and destruction
503            BOOST_UBLAS_INLINE
504            iterator1 ():
505                container_reference<self_type> (), it1_ (), it2_ () {}
506            BOOST_UBLAS_INLINE
507            iterator1 (self_type &m, size_type it1, size_type it2):
508                container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
509
510            // Arithmetic
511            BOOST_UBLAS_INLINE
512            iterator1 &operator ++ () {
513                ++ it1_;
514                return *this;
515            }
516            BOOST_UBLAS_INLINE
517            iterator1 &operator -- () {
518                -- it1_;
519                return *this;
520            }
521            BOOST_UBLAS_INLINE
522            iterator1 &operator += (difference_type n) {
523                it1_ += n;
524                return *this;
525            }
526            BOOST_UBLAS_INLINE
527            iterator1 &operator -= (difference_type n) {
528                it1_ -= n;
529                return *this;
530            }
531            BOOST_UBLAS_INLINE
532            difference_type operator - (const iterator1 &it) const {
533                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
534                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
535                return it1_ - it.it1_;
536            }
537
538            // Dereference
539            BOOST_UBLAS_INLINE
540            reference operator * () const {
541                return (*this) () (it1_, it2_);
542            }
543            BOOST_UBLAS_INLINE
544            reference operator [] (difference_type n) const {
545                return *(*this + n);
546            }
547
548#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
549            BOOST_UBLAS_INLINE
550#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
551            typename self_type::
552#endif
553            iterator2 begin () const {
554                return (*this) ().find2 (1, it1_, 0);
555            }
556            BOOST_UBLAS_INLINE
557#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
558            typename self_type::
559#endif
560            iterator2 end () const {
561                return (*this) ().find2 (1, it1_, (*this) ().size2 ());
562            }
563            BOOST_UBLAS_INLINE
564#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
565            typename self_type::
566#endif
567            reverse_iterator2 rbegin () const {
568                return reverse_iterator2 (end ());
569            }
570            BOOST_UBLAS_INLINE
571#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
572            typename self_type::
573#endif
574            reverse_iterator2 rend () const {
575                return reverse_iterator2 (begin ());
576            }
577#endif
578
579            // Indices
580            BOOST_UBLAS_INLINE
581            size_type index1 () const {
582                return it1_;
583            }
584            BOOST_UBLAS_INLINE
585            size_type index2 () const {
586                return it2_;
587            }
588
589            // Assignment
590            BOOST_UBLAS_INLINE
591            iterator1 &operator = (const iterator1 &it) {
592                container_reference<self_type>::assign (&it ());
593                it1_ = it.it1_;
594                it2_ = it.it2_;
595                return *this;
596            }
597
598            // Comparison
599            BOOST_UBLAS_INLINE
600            bool operator == (const iterator1 &it) const {
601                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
602                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
603                return it1_ == it.it1_;
604            }
605            BOOST_UBLAS_INLINE
606            bool operator < (const iterator1 &it) const {
607                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
608                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
609                return it1_ < it.it1_;
610            }
611
612        private:
613            size_type it1_;
614            size_type it2_;
615
616            friend class const_iterator1;
617        };
618#endif
619
620        BOOST_UBLAS_INLINE
621        iterator1 begin1 () {
622            return find1 (0, 0, 0);
623        }
624        BOOST_UBLAS_INLINE
625        iterator1 end1 () {
626            return find1 (0, size1_, 0);
627        }
628
629#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
630        class const_iterator2:
631            public container_const_reference<triangular_matrix>,
632            public random_access_iterator_base<packed_random_access_iterator_tag,
633                                               const_iterator2, value_type> {
634        public:
635            typedef typename triangular_matrix::value_type value_type;
636            typedef typename triangular_matrix::difference_type difference_type;
637            typedef typename triangular_matrix::const_reference reference;
638            typedef const typename triangular_matrix::pointer pointer;
639
640            typedef const_iterator1 dual_iterator_type;
641            typedef const_reverse_iterator1 dual_reverse_iterator_type;
642
643            // Construction and destruction
644            BOOST_UBLAS_INLINE
645            const_iterator2 ():
646                container_const_reference<self_type> (), it1_ (), it2_ () {}
647            BOOST_UBLAS_INLINE
648            const_iterator2 (const self_type &m, size_type it1, size_type it2):
649                container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
650            BOOST_UBLAS_INLINE
651            const_iterator2 (const iterator2 &it):
652                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
653
654            // Arithmetic
655            BOOST_UBLAS_INLINE
656            const_iterator2 &operator ++ () {
657                ++ it2_;
658                return *this;
659            }
660            BOOST_UBLAS_INLINE
661            const_iterator2 &operator -- () {
662                -- it2_;
663                return *this;
664            }
665            BOOST_UBLAS_INLINE
666            const_iterator2 &operator += (difference_type n) {
667                it2_ += n;
668                return *this;
669            }
670            BOOST_UBLAS_INLINE
671            const_iterator2 &operator -= (difference_type n) {
672                it2_ -= n;
673                return *this;
674            }
675            BOOST_UBLAS_INLINE
676            difference_type operator - (const const_iterator2 &it) const {
677                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
678                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
679                return it2_ - it.it2_;
680            }
681
682            // Dereference
683            BOOST_UBLAS_INLINE
684            const_reference operator * () const {
685                return (*this) () (it1_, it2_);
686            }
687            BOOST_UBLAS_INLINE
688            const_reference operator [] (difference_type n) const {
689                return *(*this + n);
690            }
691
692#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
693            BOOST_UBLAS_INLINE
694#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
695            typename self_type::
696#endif
697            const_iterator1 begin () const {
698                return (*this) ().find1 (1, 0, it2_);
699            }
700            BOOST_UBLAS_INLINE
701#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
702            typename self_type::
703#endif
704            const_iterator1 end () const {
705                return (*this) ().find1 (1, (*this) ().size1 (), it2_);
706            }
707            BOOST_UBLAS_INLINE
708#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
709            typename self_type::
710#endif
711            const_reverse_iterator1 rbegin () const {
712                return const_reverse_iterator1 (end ());
713            }
714            BOOST_UBLAS_INLINE
715#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
716            typename self_type::
717#endif
718            const_reverse_iterator1 rend () const {
719                return const_reverse_iterator1 (begin ());
720            }
721#endif
722
723            // Indices
724            BOOST_UBLAS_INLINE
725            size_type index1 () const {
726                return it1_;
727            }
728            BOOST_UBLAS_INLINE
729            size_type index2 () const {
730                return it2_;
731            }
732
733            // Assignment
734            BOOST_UBLAS_INLINE
735            const_iterator2 &operator = (const const_iterator2 &it) {
736                container_const_reference<self_type>::assign (&it ());
737                it1_ = it.it1_;
738                it2_ = it.it2_;
739                return *this;
740            }
741
742            // Comparison
743            BOOST_UBLAS_INLINE
744            bool operator == (const const_iterator2 &it) const {
745                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
746                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
747                return it2_ == it.it2_;
748            }
749            BOOST_UBLAS_INLINE
750            bool operator < (const const_iterator2 &it) const {
751                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
752                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
753                return it2_ < it.it2_;
754            }
755
756        private:
757            size_type it1_;
758            size_type it2_;
759        };
760#endif
761
762        BOOST_UBLAS_INLINE
763        const_iterator2 begin2 () const {
764            return find2 (0, 0, 0);
765        }
766        BOOST_UBLAS_INLINE
767        const_iterator2 end2 () const {
768            return find2 (0, 0, size2_);
769        }
770
771#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
772        class iterator2:
773            public container_reference<triangular_matrix>,
774            public random_access_iterator_base<packed_random_access_iterator_tag,
775                                               iterator2, value_type> {
776        public:
777            typedef typename triangular_matrix::value_type value_type;
778            typedef typename triangular_matrix::difference_type difference_type;
779            typedef typename triangular_matrix::reference reference;
780            typedef typename triangular_matrix::pointer pointer;
781
782            typedef iterator1 dual_iterator_type;
783            typedef reverse_iterator1 dual_reverse_iterator_type;
784
785            // Construction and destruction
786            BOOST_UBLAS_INLINE
787            iterator2 ():
788                container_reference<self_type> (), it1_ (), it2_ () {}
789            BOOST_UBLAS_INLINE
790            iterator2 (self_type &m, size_type it1, size_type it2):
791                container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
792
793            // Arithmetic
794            BOOST_UBLAS_INLINE
795            iterator2 &operator ++ () {
796                ++ it2_;
797                return *this;
798            }
799            BOOST_UBLAS_INLINE
800            iterator2 &operator -- () {
801                -- it2_;
802                return *this;
803            }
804            BOOST_UBLAS_INLINE
805            iterator2 &operator += (difference_type n) {
806                it2_ += n;
807                return *this;
808            }
809            BOOST_UBLAS_INLINE
810            iterator2 &operator -= (difference_type n) {
811                it2_ -= n;
812                return *this;
813            }
814            BOOST_UBLAS_INLINE
815            difference_type operator - (const iterator2 &it) const {
816                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
817                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
818                return it2_ - it.it2_;
819            }
820
821            // Dereference
822            BOOST_UBLAS_INLINE
823            reference operator * () const {
824                return (*this) () (it1_, it2_);
825            }
826            BOOST_UBLAS_INLINE
827            reference operator [] (difference_type n) const {
828                return *(*this + n);
829            }
830
831#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
832            BOOST_UBLAS_INLINE
833#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
834            typename self_type::
835#endif
836            iterator1 begin () const {
837                return (*this) ().find1 (1, 0, it2_);
838            }
839            BOOST_UBLAS_INLINE
840#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
841            typename self_type::
842#endif
843            iterator1 end () const {
844                return (*this) ().find1 (1, (*this) ().size1 (), it2_);
845            }
846            BOOST_UBLAS_INLINE
847#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
848            typename self_type::
849#endif
850            reverse_iterator1 rbegin () const {
851                return reverse_iterator1 (end ());
852            }
853            BOOST_UBLAS_INLINE
854#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
855            typename self_type::
856#endif
857            reverse_iterator1 rend () const {
858                return reverse_iterator1 (begin ());
859            }
860#endif
861
862            // Indices
863            BOOST_UBLAS_INLINE
864            size_type index1 () const {
865                return it1_;
866            }
867            BOOST_UBLAS_INLINE
868            size_type index2 () const {
869                return it2_;
870            }
871
872            // Assignment
873            BOOST_UBLAS_INLINE
874            iterator2 &operator = (const iterator2 &it) {
875                container_reference<self_type>::assign (&it ());
876                it1_ = it.it1_;
877                it2_ = it.it2_;
878                return *this;
879            }
880
881            // Comparison
882            BOOST_UBLAS_INLINE
883            bool operator == (const iterator2 &it) const {
884                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
885                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
886                return it2_ == it.it2_;
887            }
888            BOOST_UBLAS_INLINE
889            bool operator < (const iterator2 &it) const {
890                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
891                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
892                return it2_ < it.it2_;
893            }
894
895        private:
896            size_type it1_;
897            size_type it2_;
898
899            friend class const_iterator2;
900        };
901#endif
902
903        BOOST_UBLAS_INLINE
904        iterator2 begin2 () {
905            return find2 (0, 0, 0);
906        }
907        BOOST_UBLAS_INLINE
908        iterator2 end2 () {
909            return find2 (0, 0, size2_);
910        }
911
912        // Reverse iterators
913
914        BOOST_UBLAS_INLINE
915        const_reverse_iterator1 rbegin1 () const {
916            return const_reverse_iterator1 (end1 ());
917        }
918        BOOST_UBLAS_INLINE
919        const_reverse_iterator1 rend1 () const {
920            return const_reverse_iterator1 (begin1 ());
921        }
922
923        BOOST_UBLAS_INLINE
924        reverse_iterator1 rbegin1 () {
925            return reverse_iterator1 (end1 ());
926        }
927        BOOST_UBLAS_INLINE
928        reverse_iterator1 rend1 () {
929            return reverse_iterator1 (begin1 ());
930        }
931
932        BOOST_UBLAS_INLINE
933        const_reverse_iterator2 rbegin2 () const {
934            return const_reverse_iterator2 (end2 ());
935        }
936        BOOST_UBLAS_INLINE
937        const_reverse_iterator2 rend2 () const {
938            return const_reverse_iterator2 (begin2 ());
939        }
940
941        BOOST_UBLAS_INLINE
942        reverse_iterator2 rbegin2 () {
943            return reverse_iterator2 (end2 ());
944        }
945        BOOST_UBLAS_INLINE
946        reverse_iterator2 rend2 () {
947            return reverse_iterator2 (begin2 ());
948        }
949
950    private:
951        size_type size1_;
952        size_type size2_;
953        array_type data_;
954        static const value_type zero_;
955        static const value_type one_;
956    };
957
958    template<class T, class TRI, class L, class A>
959    const typename triangular_matrix<T, TRI, L, A>::value_type triangular_matrix<T, TRI, L, A>::zero_ = value_type/*zero*/();
960    template<class T, class TRI, class L, class A>
961    const typename triangular_matrix<T, TRI, L, A>::value_type triangular_matrix<T, TRI, L, A>::one_ (1);
962
963
964    // Triangular matrix adaptor class
965    template<class M, class TRI>
966    class triangular_adaptor:
967        public matrix_expression<triangular_adaptor<M, TRI> > {
968
969        typedef triangular_adaptor<M, TRI> self_type;
970
971    public:
972#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
973        using matrix_expression<self_type>::operator ();
974#endif
975        typedef const M const_matrix_type;
976        typedef M matrix_type;
977        typedef TRI triangular_type;
978        typedef typename M::size_type size_type;
979        typedef typename M::difference_type difference_type;
980        typedef typename M::value_type value_type;
981        typedef typename M::const_reference const_reference;
982        typedef typename boost::mpl::if_<boost::is_const<M>,
983                                          typename M::const_reference,
984                                          typename M::reference>::type reference;
985        typedef typename boost::mpl::if_<boost::is_const<M>,
986                                          typename M::const_closure_type,
987                                          typename M::closure_type>::type matrix_closure_type;
988        typedef const self_type const_closure_type;
989        typedef self_type closure_type;
990        // Replaced by _temporary_traits to avoid type requirements on M
991        //typedef typename M::vector_temporary_type vector_temporary_type;
992        //typedef typename M::matrix_temporary_type matrix_temporary_type;
993        typedef typename storage_restrict_traits<typename M::storage_category,
994                                                 packed_proxy_tag>::storage_category storage_category;
995        typedef typename M::orientation_category orientation_category;
996
997        // Construction and destruction
998        BOOST_UBLAS_INLINE
999        triangular_adaptor (matrix_type &data):
1000            matrix_expression<self_type> (),
1001            data_ (data) {}
1002        BOOST_UBLAS_INLINE
1003        triangular_adaptor (const triangular_adaptor &m):
1004            matrix_expression<self_type> (),
1005            data_ (m.data_) {}
1006
1007        // Accessors
1008        BOOST_UBLAS_INLINE
1009        size_type size1 () const {
1010            return data_.size1 ();
1011        }
1012        BOOST_UBLAS_INLINE
1013        size_type size2 () const {
1014            return data_.size2 ();
1015        }
1016
1017        // Storage accessors
1018        BOOST_UBLAS_INLINE
1019        const matrix_closure_type &data () const {
1020            return data_;
1021        }
1022        BOOST_UBLAS_INLINE
1023        matrix_closure_type &data () {
1024            return data_;
1025        }
1026
1027        // Element access
1028#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1029        BOOST_UBLAS_INLINE
1030        const_reference operator () (size_type i, size_type j) const {
1031            BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1032            BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1033            if (triangular_type::other (i, j))
1034                return data () (i, j);
1035            else if (triangular_type::one (i, j))
1036                return one_;
1037            else
1038                return zero_;
1039        }
1040        BOOST_UBLAS_INLINE
1041        reference operator () (size_type i, size_type j) {
1042            BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1043            BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1044            if (!triangular_type::other (i, j)) {
1045                bad_index ().raise ();
1046                // NEVER reached
1047            }
1048            return data () (i, j);
1049        }
1050#else
1051        BOOST_UBLAS_INLINE
1052        reference operator () (size_type i, size_type j) const {
1053            BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1054            BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1055            if (!triangular_type::other (i, j)) {
1056                bad_index ().raise ();
1057                // NEVER reached
1058            }
1059            return data () (i, j);
1060        }
1061#endif
1062
1063        // Assignment
1064        BOOST_UBLAS_INLINE
1065        triangular_adaptor &operator = (const triangular_adaptor &m) {
1066            matrix_assign<scalar_assign> (*this, m);
1067            return *this;
1068        }
1069        BOOST_UBLAS_INLINE
1070        triangular_adaptor &assign_temporary (triangular_adaptor &m) {
1071            *this = m;
1072            return *this;
1073        }
1074        template<class AE>
1075        BOOST_UBLAS_INLINE
1076        triangular_adaptor &operator = (const matrix_expression<AE> &ae) {
1077            matrix_assign<scalar_assign> (*this, matrix<value_type> (ae));
1078            return *this;
1079        }
1080        template<class AE>
1081        BOOST_UBLAS_INLINE
1082        triangular_adaptor &assign (const matrix_expression<AE> &ae) {
1083            matrix_assign<scalar_assign> (*this, ae);
1084            return *this;
1085        }
1086        template<class AE>
1087        BOOST_UBLAS_INLINE
1088        triangular_adaptor& operator += (const matrix_expression<AE> &ae) {
1089            matrix_assign<scalar_assign> (*this, matrix<value_type> (*this + ae));
1090            return *this;
1091        }
1092        template<class AE>
1093        BOOST_UBLAS_INLINE
1094        triangular_adaptor &plus_assign (const matrix_expression<AE> &ae) {
1095            matrix_assign<scalar_plus_assign> (*this, ae);
1096            return *this;
1097        }
1098        template<class AE>
1099        BOOST_UBLAS_INLINE
1100        triangular_adaptor& operator -= (const matrix_expression<AE> &ae) {
1101            matrix_assign<scalar_assign> (*this, matrix<value_type> (*this - ae));
1102            return *this;
1103        }
1104        template<class AE>
1105        BOOST_UBLAS_INLINE
1106        triangular_adaptor &minus_assign (const matrix_expression<AE> &ae) {
1107            matrix_assign<scalar_minus_assign> (*this, ae);
1108            return *this;
1109        }
1110        template<class AT>
1111        BOOST_UBLAS_INLINE
1112        triangular_adaptor& operator *= (const AT &at) {
1113            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
1114            return *this;
1115        }
1116        template<class AT>
1117        BOOST_UBLAS_INLINE
1118        triangular_adaptor& operator /= (const AT &at) {
1119            matrix_assign_scalar<scalar_divides_assign> (*this, at);
1120            return *this;
1121        }
1122
1123        // Closure comparison
1124        BOOST_UBLAS_INLINE
1125        bool same_closure (const triangular_adaptor &ta) const {
1126            return (*this).data ().same_closure (ta.data ());
1127        }
1128
1129        // Swapping
1130        BOOST_UBLAS_INLINE
1131        void swap (triangular_adaptor &m) {
1132            if (this != &m)
1133                matrix_swap<scalar_swap> (*this, m);
1134        }
1135        BOOST_UBLAS_INLINE
1136        friend void swap (triangular_adaptor &m1, triangular_adaptor &m2) {
1137            m1.swap (m2);
1138        }
1139
1140        // Iterator types
1141   private:
1142        typedef typename M::const_iterator1 const_subiterator1_type;
1143        typedef typename boost::mpl::if_<boost::is_const<M>,
1144                                          typename M::const_iterator1,
1145                                          typename M::iterator1>::type subiterator1_type;
1146        typedef typename M::const_iterator2 const_subiterator2_type;
1147        typedef typename boost::mpl::if_<boost::is_const<M>,
1148                                          typename M::const_iterator2,
1149                                          typename M::iterator2>::type subiterator2_type;
1150
1151    public:
1152#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1153        typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
1154        typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
1155        typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
1156        typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
1157#else
1158        class const_iterator1;
1159        class iterator1;
1160        class const_iterator2;
1161        class iterator2;
1162#endif
1163        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1164        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
1165        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1166        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
1167
1168        // Element lookup
1169        BOOST_UBLAS_INLINE
1170        const_iterator1 find1 (int rank, size_type i, size_type j) const {
1171            if (rank == 1)
1172                i = triangular_type::restrict1 (i, j, size1(), size2());
1173            if (rank == 0)
1174                i = triangular_type::global_restrict1 (i, size1(), j, size2());
1175            return const_iterator1 (*this, data ().find1 (rank, i, j));
1176        }
1177        BOOST_UBLAS_INLINE
1178        iterator1 find1 (int rank, size_type i, size_type j) {
1179            if (rank == 1)
1180                i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
1181            if (rank == 0)
1182                i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
1183            return iterator1 (*this, data ().find1 (rank, i, j));
1184        }
1185        BOOST_UBLAS_INLINE
1186        const_iterator2 find2 (int rank, size_type i, size_type j) const {
1187            if (rank == 1)
1188                j = triangular_type::restrict2 (i, j, size1(), size2());
1189            if (rank == 0)
1190                j = triangular_type::global_restrict2 (i, size1(), j, size2());
1191            return const_iterator2 (*this, data ().find2 (rank, i, j));
1192        }
1193        BOOST_UBLAS_INLINE
1194        iterator2 find2 (int rank, size_type i, size_type j) {
1195            if (rank == 1)
1196                j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
1197            if (rank == 0)
1198                j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
1199            return iterator2 (*this, data ().find2 (rank, i, j));
1200        }
1201
1202        // Iterators simply are indices.
1203
1204#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1205        class const_iterator1:
1206            public container_const_reference<triangular_adaptor>,
1207            public random_access_iterator_base<typename iterator_restrict_traits<
1208                                                   typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1209                                               const_iterator1, value_type> {
1210        public:
1211            typedef typename const_subiterator1_type::value_type value_type;
1212            typedef typename const_subiterator1_type::difference_type difference_type;
1213            typedef typename const_subiterator1_type::reference reference;
1214            typedef typename const_subiterator1_type::pointer pointer;
1215
1216            typedef const_iterator2 dual_iterator_type;
1217            typedef const_reverse_iterator2 dual_reverse_iterator_type;
1218
1219            // Construction and destruction
1220            BOOST_UBLAS_INLINE
1221            const_iterator1 ():
1222                container_const_reference<self_type> (), it1_ () {}
1223            BOOST_UBLAS_INLINE
1224            const_iterator1 (const self_type &m, const const_subiterator1_type &it1):
1225                container_const_reference<self_type> (m), it1_ (it1) {}
1226            BOOST_UBLAS_INLINE
1227            const_iterator1 (const iterator1 &it):
1228                container_const_reference<self_type> (it ()), it1_ (it.it1_) {}
1229
1230            // Arithmetic
1231            BOOST_UBLAS_INLINE
1232            const_iterator1 &operator ++ () {
1233                ++ it1_;
1234                return *this;
1235            }
1236            BOOST_UBLAS_INLINE
1237            const_iterator1 &operator -- () {
1238                -- it1_;
1239                return *this;
1240            }
1241            BOOST_UBLAS_INLINE
1242            const_iterator1 &operator += (difference_type n) {
1243                it1_ += n;
1244                return *this;
1245            }
1246            BOOST_UBLAS_INLINE
1247            const_iterator1 &operator -= (difference_type n) {
1248                it1_ -= n;
1249                return *this;
1250            }
1251            BOOST_UBLAS_INLINE
1252            difference_type operator - (const const_iterator1 &it) const {
1253                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1254                return it1_ - it.it1_;
1255            }
1256
1257            // Dereference
1258            BOOST_UBLAS_INLINE
1259            const_reference operator * () const {
1260                size_type i = index1 ();
1261                size_type j = index2 ();
1262                BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
1263                BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
1264                if (triangular_type::other (i, j))
1265                    return *it1_;
1266                else
1267                    return (*this) () (i, j);
1268            }
1269            BOOST_UBLAS_INLINE
1270            const_reference operator [] (difference_type n) const {
1271                return *(*this + n);
1272            }
1273
1274#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1275            BOOST_UBLAS_INLINE
1276#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1277            typename self_type::
1278#endif
1279            const_iterator2 begin () const {
1280                return (*this) ().find2 (1, index1 (), 0);
1281            }
1282            BOOST_UBLAS_INLINE
1283#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1284            typename self_type::
1285#endif
1286            const_iterator2 end () const {
1287                return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1288            }
1289            BOOST_UBLAS_INLINE
1290#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1291            typename self_type::
1292#endif
1293            const_reverse_iterator2 rbegin () const {
1294                return const_reverse_iterator2 (end ());
1295            }
1296            BOOST_UBLAS_INLINE
1297#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1298            typename self_type::
1299#endif
1300            const_reverse_iterator2 rend () const {
1301                return const_reverse_iterator2 (begin ());
1302            }
1303#endif
1304
1305            // Indices
1306            BOOST_UBLAS_INLINE
1307            size_type index1 () const {
1308                return it1_.index1 ();
1309            }
1310            BOOST_UBLAS_INLINE
1311            size_type index2 () const {
1312                return it1_.index2 ();
1313            }
1314
1315            // Assignment
1316            BOOST_UBLAS_INLINE
1317            const_iterator1 &operator = (const const_iterator1 &it) {
1318                container_const_reference<self_type>::assign (&it ());
1319                it1_ = it.it1_;
1320                return *this;
1321            }
1322
1323            // Comparison
1324            BOOST_UBLAS_INLINE
1325            bool operator == (const const_iterator1 &it) const {
1326                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1327                return it1_ == it.it1_;
1328            }
1329            BOOST_UBLAS_INLINE
1330            bool operator < (const const_iterator1 &it) const {
1331                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1332                return it1_ < it.it1_;
1333            }
1334
1335        private:
1336            const_subiterator1_type it1_;
1337        };
1338#endif
1339
1340        BOOST_UBLAS_INLINE
1341        const_iterator1 begin1 () const {
1342            return find1 (0, 0, 0);
1343        }
1344        BOOST_UBLAS_INLINE
1345        const_iterator1 end1 () const {
1346            return find1 (0, size1 (), 0);
1347        }
1348
1349#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1350        class iterator1:
1351            public container_reference<triangular_adaptor>,
1352            public random_access_iterator_base<typename iterator_restrict_traits<
1353                                                   typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1354                                               iterator1, value_type> {
1355        public:
1356            typedef typename subiterator1_type::value_type value_type;
1357            typedef typename subiterator1_type::difference_type difference_type;
1358            typedef typename subiterator1_type::reference reference;
1359            typedef typename subiterator1_type::pointer pointer;
1360
1361            typedef iterator2 dual_iterator_type;
1362            typedef reverse_iterator2 dual_reverse_iterator_type;
1363
1364            // Construction and destruction
1365            BOOST_UBLAS_INLINE
1366            iterator1 ():
1367                container_reference<self_type> (), it1_ () {}
1368            BOOST_UBLAS_INLINE
1369            iterator1 (self_type &m, const subiterator1_type &it1):
1370                container_reference<self_type> (m), it1_ (it1) {}
1371
1372            // Arithmetic
1373            BOOST_UBLAS_INLINE
1374            iterator1 &operator ++ () {
1375                ++ it1_;
1376                return *this;
1377            }
1378            BOOST_UBLAS_INLINE
1379            iterator1 &operator -- () {
1380                -- it1_;
1381                return *this;
1382            }
1383            BOOST_UBLAS_INLINE
1384            iterator1 &operator += (difference_type n) {
1385                it1_ += n;
1386                return *this;
1387            }
1388            BOOST_UBLAS_INLINE
1389            iterator1 &operator -= (difference_type n) {
1390                it1_ -= n;
1391                return *this;
1392            }
1393            BOOST_UBLAS_INLINE
1394            difference_type operator - (const iterator1 &it) const {
1395                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1396                return it1_ - it.it1_;
1397            }
1398
1399            // Dereference
1400            BOOST_UBLAS_INLINE
1401            reference operator * () const {
1402                size_type i = index1 ();
1403                size_type j = index2 ();
1404                BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
1405                BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
1406                if (triangular_type::other (i, j))
1407                    return *it1_;
1408                else
1409                    return (*this) () (i, j);
1410            }
1411            BOOST_UBLAS_INLINE
1412            reference operator [] (difference_type n) const {
1413                return *(*this + n);
1414            }
1415
1416#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1417            BOOST_UBLAS_INLINE
1418#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1419            typename self_type::
1420#endif
1421            iterator2 begin () const {
1422                return (*this) ().find2 (1, index1 (), 0);
1423            }
1424            BOOST_UBLAS_INLINE
1425#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1426            typename self_type::
1427#endif
1428            iterator2 end () const {
1429                return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1430            }
1431            BOOST_UBLAS_INLINE
1432#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1433            typename self_type::
1434#endif
1435            reverse_iterator2 rbegin () const {
1436                return reverse_iterator2 (end ());
1437            }
1438            BOOST_UBLAS_INLINE
1439#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1440            typename self_type::
1441#endif
1442            reverse_iterator2 rend () const {
1443                return reverse_iterator2 (begin ());
1444            }
1445#endif
1446
1447            // Indices
1448            BOOST_UBLAS_INLINE
1449            size_type index1 () const {
1450                return it1_.index1 ();
1451            }
1452            BOOST_UBLAS_INLINE
1453            size_type index2 () const {
1454                return it1_.index2 ();
1455            }
1456
1457            // Assignment
1458            BOOST_UBLAS_INLINE
1459            iterator1 &operator = (const iterator1 &it) {
1460                container_reference<self_type>::assign (&it ());
1461                it1_ = it.it1_;
1462                return *this;
1463            }
1464
1465            // Comparison
1466            BOOST_UBLAS_INLINE
1467            bool operator == (const iterator1 &it) const {
1468                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1469                return it1_ == it.it1_;
1470            }
1471            BOOST_UBLAS_INLINE
1472            bool operator < (const iterator1 &it) const {
1473                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1474                return it1_ < it.it1_;
1475            }
1476
1477        private:
1478            subiterator1_type it1_;
1479
1480            friend class const_iterator1;
1481        };
1482#endif
1483
1484        BOOST_UBLAS_INLINE
1485        iterator1 begin1 () {
1486            return find1 (0, 0, 0);
1487        }
1488        BOOST_UBLAS_INLINE
1489        iterator1 end1 () {
1490            return find1 (0, size1 (), 0);
1491        }
1492
1493#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1494        class const_iterator2:
1495            public container_const_reference<triangular_adaptor>,
1496            public random_access_iterator_base<typename iterator_restrict_traits<
1497                                                   typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1498                                               const_iterator2, value_type> {
1499        public:
1500            typedef typename const_subiterator2_type::value_type value_type;
1501            typedef typename const_subiterator2_type::difference_type difference_type;
1502            typedef typename const_subiterator2_type::reference reference;
1503            typedef typename const_subiterator2_type::pointer pointer;
1504
1505            typedef const_iterator1 dual_iterator_type;
1506            typedef const_reverse_iterator1 dual_reverse_iterator_type;
1507
1508            // Construction and destruction
1509            BOOST_UBLAS_INLINE
1510            const_iterator2 ():
1511                container_const_reference<self_type> (), it2_ () {}
1512            BOOST_UBLAS_INLINE
1513            const_iterator2 (const self_type &m, const const_subiterator2_type &it2):
1514                container_const_reference<self_type> (m), it2_ (it2) {}
1515            BOOST_UBLAS_INLINE
1516            const_iterator2 (const iterator2 &it):
1517                container_const_reference<self_type> (it ()), it2_ (it.it2_) {}
1518
1519            // Arithmetic
1520            BOOST_UBLAS_INLINE
1521            const_iterator2 &operator ++ () {
1522                ++ it2_;
1523                return *this;
1524            }
1525            BOOST_UBLAS_INLINE
1526            const_iterator2 &operator -- () {
1527                -- it2_;
1528                return *this;
1529            }
1530            BOOST_UBLAS_INLINE
1531            const_iterator2 &operator += (difference_type n) {
1532                it2_ += n;
1533                return *this;
1534            }
1535            BOOST_UBLAS_INLINE
1536            const_iterator2 &operator -= (difference_type n) {
1537                it2_ -= n;
1538                return *this;
1539            }
1540            BOOST_UBLAS_INLINE
1541            difference_type operator - (const const_iterator2 &it) const {
1542                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1543                return it2_ - it.it2_;
1544            }
1545
1546            // Dereference
1547            BOOST_UBLAS_INLINE
1548            const_reference operator * () const {
1549                size_type i = index1 ();
1550                size_type j = index2 ();
1551                BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
1552                BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
1553                if (triangular_type::other (i, j))
1554                    return *it2_;
1555                else
1556                    return (*this) () (i, j);
1557            }
1558            BOOST_UBLAS_INLINE
1559            const_reference operator [] (difference_type n) const {
1560                return *(*this + n);
1561            }
1562
1563#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1564            BOOST_UBLAS_INLINE
1565#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1566            typename self_type::
1567#endif
1568            const_iterator1 begin () const {
1569                return (*this) ().find1 (1, 0, index2 ());
1570            }
1571            BOOST_UBLAS_INLINE
1572#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1573            typename self_type::
1574#endif
1575            const_iterator1 end () const {
1576                return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1577            }
1578            BOOST_UBLAS_INLINE
1579#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1580            typename self_type::
1581#endif
1582            const_reverse_iterator1 rbegin () const {
1583                return const_reverse_iterator1 (end ());
1584            }
1585            BOOST_UBLAS_INLINE
1586#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1587            typename self_type::
1588#endif
1589            const_reverse_iterator1 rend () const {
1590                return const_reverse_iterator1 (begin ());
1591            }
1592#endif
1593
1594            // Indices
1595            BOOST_UBLAS_INLINE
1596            size_type index1 () const {
1597                return it2_.index1 ();
1598            }
1599            BOOST_UBLAS_INLINE
1600            size_type index2 () const {
1601                return it2_.index2 ();
1602            }
1603
1604            // Assignment
1605            BOOST_UBLAS_INLINE
1606            const_iterator2 &operator = (const const_iterator2 &it) {
1607                container_const_reference<self_type>::assign (&it ());
1608                it2_ = it.it2_;
1609                return *this;
1610            }
1611
1612            // Comparison
1613            BOOST_UBLAS_INLINE
1614            bool operator == (const const_iterator2 &it) const {
1615                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1616                return it2_ == it.it2_;
1617            }
1618            BOOST_UBLAS_INLINE
1619            bool operator < (const const_iterator2 &it) const {
1620                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1621                return it2_ < it.it2_;
1622            }
1623
1624        private:
1625            const_subiterator2_type it2_;
1626        };
1627#endif
1628
1629        BOOST_UBLAS_INLINE
1630        const_iterator2 begin2 () const {
1631            return find2 (0, 0, 0);
1632        }
1633        BOOST_UBLAS_INLINE
1634        const_iterator2 end2 () const {
1635            return find2 (0, 0, size2 ());
1636        }
1637
1638#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1639        class iterator2:
1640            public container_reference<triangular_adaptor>,
1641            public random_access_iterator_base<typename iterator_restrict_traits<
1642                                                   typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1643                                               iterator2, value_type> {
1644        public:
1645            typedef typename subiterator2_type::value_type value_type;
1646            typedef typename subiterator2_type::difference_type difference_type;
1647            typedef typename subiterator2_type::reference reference;
1648            typedef typename subiterator2_type::pointer pointer;
1649
1650            typedef iterator1 dual_iterator_type;
1651            typedef reverse_iterator1 dual_reverse_iterator_type;
1652
1653            // Construction and destruction
1654            BOOST_UBLAS_INLINE
1655            iterator2 ():
1656                container_reference<self_type> (), it2_ () {}
1657            BOOST_UBLAS_INLINE
1658            iterator2 (self_type &m, const subiterator2_type &it2):
1659                container_reference<self_type> (m), it2_ (it2) {}
1660
1661            // Arithmetic
1662            BOOST_UBLAS_INLINE
1663            iterator2 &operator ++ () {
1664                ++ it2_;
1665                return *this;
1666            }
1667            BOOST_UBLAS_INLINE
1668            iterator2 &operator -- () {
1669                -- it2_;
1670                return *this;
1671            }
1672            BOOST_UBLAS_INLINE
1673            iterator2 &operator += (difference_type n) {
1674                it2_ += n;
1675                return *this;
1676            }
1677            BOOST_UBLAS_INLINE
1678            iterator2 &operator -= (difference_type n) {
1679                it2_ -= n;
1680                return *this;
1681            }
1682            BOOST_UBLAS_INLINE
1683            difference_type operator - (const iterator2 &it) const {
1684                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1685                return it2_ - it.it2_;
1686            }
1687
1688            // Dereference
1689            BOOST_UBLAS_INLINE
1690            reference operator * () const {
1691                size_type i = index1 ();
1692                size_type j = index2 ();
1693                BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
1694                BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
1695                if (triangular_type::other (i, j))
1696                    return *it2_;
1697                else
1698                    return (*this) () (i, j);
1699            }
1700            BOOST_UBLAS_INLINE
1701            reference operator [] (difference_type n) const {
1702                return *(*this + n);
1703            }
1704
1705#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1706            BOOST_UBLAS_INLINE
1707#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1708            typename self_type::
1709#endif
1710            iterator1 begin () const {
1711                return (*this) ().find1 (1, 0, index2 ());
1712            }
1713            BOOST_UBLAS_INLINE
1714#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1715            typename self_type::
1716#endif
1717            iterator1 end () const {
1718                return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1719            }
1720            BOOST_UBLAS_INLINE
1721#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1722            typename self_type::
1723#endif
1724            reverse_iterator1 rbegin () const {
1725                return reverse_iterator1 (end ());
1726            }
1727            BOOST_UBLAS_INLINE
1728#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1729            typename self_type::
1730#endif
1731            reverse_iterator1 rend () const {
1732                return reverse_iterator1 (begin ());
1733            }
1734#endif
1735
1736            // Indices
1737            BOOST_UBLAS_INLINE
1738            size_type index1 () const {
1739                return it2_.index1 ();
1740            }
1741            BOOST_UBLAS_INLINE
1742            size_type index2 () const {
1743                return it2_.index2 ();
1744            }
1745
1746            // Assignment
1747            BOOST_UBLAS_INLINE
1748            iterator2 &operator = (const iterator2 &it) {
1749                container_reference<self_type>::assign (&it ());
1750                it2_ = it.it2_;
1751                return *this;
1752            }
1753
1754            // Comparison
1755            BOOST_UBLAS_INLINE
1756            bool operator == (const iterator2 &it) const {
1757                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1758                return it2_ == it.it2_;
1759            }
1760            BOOST_UBLAS_INLINE
1761            bool operator < (const iterator2 &it) const {
1762                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1763                return it2_ < it.it2_;
1764            }
1765
1766        private:
1767            subiterator2_type it2_;
1768
1769            friend class const_iterator2;
1770        };
1771#endif
1772
1773        BOOST_UBLAS_INLINE
1774        iterator2 begin2 () {
1775            return find2 (0, 0, 0);
1776        }
1777        BOOST_UBLAS_INLINE
1778        iterator2 end2 () {
1779            return find2 (0, 0, size2 ());
1780        }
1781
1782        // Reverse iterators
1783
1784        BOOST_UBLAS_INLINE
1785        const_reverse_iterator1 rbegin1 () const {
1786            return const_reverse_iterator1 (end1 ());
1787        }
1788        BOOST_UBLAS_INLINE
1789        const_reverse_iterator1 rend1 () const {
1790            return const_reverse_iterator1 (begin1 ());
1791        }
1792
1793        BOOST_UBLAS_INLINE
1794        reverse_iterator1 rbegin1 () {
1795            return reverse_iterator1 (end1 ());
1796        }
1797        BOOST_UBLAS_INLINE
1798        reverse_iterator1 rend1 () {
1799            return reverse_iterator1 (begin1 ());
1800        }
1801
1802        BOOST_UBLAS_INLINE
1803        const_reverse_iterator2 rbegin2 () const {
1804            return const_reverse_iterator2 (end2 ());
1805        }
1806        BOOST_UBLAS_INLINE
1807        const_reverse_iterator2 rend2 () const {
1808            return const_reverse_iterator2 (begin2 ());
1809        }
1810
1811        BOOST_UBLAS_INLINE
1812        reverse_iterator2 rbegin2 () {
1813            return reverse_iterator2 (end2 ());
1814        }
1815        BOOST_UBLAS_INLINE
1816        reverse_iterator2 rend2 () {
1817            return reverse_iterator2 (begin2 ());
1818        }
1819
1820    private:
1821        matrix_closure_type data_;
1822        static const value_type zero_;
1823        static const value_type one_;
1824    };
1825
1826    template<class M, class TRI>
1827    const typename triangular_adaptor<M, TRI>::value_type triangular_adaptor<M, TRI>::zero_ = value_type/*zero*/();
1828    template<class M, class TRI>
1829    const typename triangular_adaptor<M, TRI>::value_type triangular_adaptor<M, TRI>::one_ (1);
1830
1831    template <class M, class TRI>
1832    struct vector_temporary_traits< triangular_adaptor<M, TRI> >
1833    : vector_temporary_traits< typename boost::remove_const<M>::type > {} ;
1834    template <class M, class TRI>
1835    struct vector_temporary_traits< const triangular_adaptor<M, TRI> >
1836    : vector_temporary_traits< typename boost::remove_const<M>::type > {} ;
1837
1838    template <class M, class TRI>
1839    struct matrix_temporary_traits< triangular_adaptor<M, TRI> >
1840    : matrix_temporary_traits< typename boost::remove_const<M>::type > {};
1841    template <class M, class TRI>
1842    struct matrix_temporary_traits< const triangular_adaptor<M, TRI> >
1843    : matrix_temporary_traits< typename boost::remove_const<M>::type > {};
1844
1845
1846    template<class E1, class E2>
1847    struct matrix_vector_solve_traits {
1848        typedef typename promote_traits<typename E1::value_type, typename E2::value_type>::promote_type promote_type;
1849        typedef vector<promote_type> result_type;
1850    };
1851
1852    // Operations:
1853    //  n * (n - 1) / 2 + n = n * (n + 1) / 2 multiplications,
1854    //  n * (n - 1) / 2 additions
1855
1856    // Dense (proxy) case
1857    template<class E1, class E2>
1858    BOOST_UBLAS_INLINE
1859    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1860                        lower_tag, column_major_tag, dense_proxy_tag) {
1861        typedef typename E2::size_type size_type;
1862        typedef typename E2::difference_type difference_type;
1863        typedef typename E2::value_type value_type;
1864
1865        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
1866        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
1867        size_type size = e2 ().size ();
1868        for (size_type n = 0; n < size; ++ n) {
1869#ifndef BOOST_UBLAS_SINGULAR_CHECK
1870            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
1871#else
1872            if (e1 () (n, n) == value_type/*zero*/())
1873                singular ().raise ();
1874#endif
1875            value_type t = e2 () (n) /= e1 () (n, n);
1876            if (t != value_type/*zero*/()) {
1877                for (size_type m = n + 1; m < size; ++ m)
1878                    e2 () (m) -= e1 () (m, n) * t;
1879            }
1880        }
1881    }
1882    // Packed (proxy) case
1883    template<class E1, class E2>
1884    BOOST_UBLAS_INLINE
1885    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1886                        lower_tag, column_major_tag, packed_proxy_tag) {
1887        typedef typename E2::size_type size_type;
1888        typedef typename E2::difference_type difference_type;
1889        typedef typename E2::value_type value_type;
1890
1891        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
1892        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
1893        size_type size = e2 ().size ();
1894        for (size_type n = 0; n < size; ++ n) {
1895#ifndef BOOST_UBLAS_SINGULAR_CHECK
1896            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
1897#else
1898            if (e1 () (n, n) == value_type/*zero*/())
1899                singular ().raise ();
1900#endif
1901            value_type t = e2 () (n) /= e1 () (n, n);
1902            if (t != value_type/*zero*/()) {
1903                typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
1904                typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
1905                difference_type m (it1e1_end - it1e1);
1906                while (-- m >= 0)
1907                    e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
1908            }
1909        }
1910    }
1911    // Sparse (proxy) case
1912    template<class E1, class E2>
1913    BOOST_UBLAS_INLINE
1914    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1915                        lower_tag, column_major_tag, unknown_storage_tag) {
1916        typedef typename E2::size_type size_type;
1917        typedef typename E2::difference_type difference_type;
1918        typedef typename E2::value_type value_type;
1919
1920        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
1921        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
1922        size_type size = e2 ().size ();
1923        for (size_type n = 0; n < size; ++ n) {
1924#ifndef BOOST_UBLAS_SINGULAR_CHECK
1925            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
1926#else
1927            if (e1 () (n, n) == value_type/*zero*/())
1928                singular ().raise ();
1929#endif
1930            value_type t = e2 () (n) /= e1 () (n, n);
1931            if (t != value_type/*zero*/()) {
1932                typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
1933                typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
1934                while (it1e1 != it1e1_end)
1935                    e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
1936            }
1937        }
1938    }
1939    // Redirectors :-)
1940    template<class E1, class E2>
1941    BOOST_UBLAS_INLINE
1942    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1943                        lower_tag, column_major_tag) {
1944        typedef typename E1::storage_category storage_category;
1945        inplace_solve (e1, e2,
1946                       lower_tag (), column_major_tag (), storage_category ());
1947    }
1948    template<class E1, class E2>
1949    BOOST_UBLAS_INLINE
1950    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1951                        lower_tag, row_major_tag) {
1952        typedef typename E1::storage_category storage_category;
1953        inplace_solve (e2, trans (e1),
1954                       upper_tag (), row_major_tag (), storage_category ());
1955    }
1956    // Dispatcher
1957    template<class E1, class E2>
1958    BOOST_UBLAS_INLINE
1959    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1960                        lower_tag) {
1961        typedef typename E1::orientation_category orientation_category;
1962        inplace_solve (e1, e2,
1963                       lower_tag (), orientation_category ());
1964    }
1965    template<class E1, class E2>
1966    BOOST_UBLAS_INLINE
1967    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1968                        unit_lower_tag) {
1969        typedef typename E1::orientation_category orientation_category;
1970        inplace_solve (triangular_adaptor<const E1, unit_lower> (e1 ()), e2,
1971                       unit_lower_tag (), orientation_category ());
1972    }
1973
1974    // Dense (proxy) case
1975    template<class E1, class E2>
1976    BOOST_UBLAS_INLINE
1977    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1978                        upper_tag, column_major_tag, dense_proxy_tag) {
1979        typedef typename E2::size_type size_type;
1980        typedef typename E2::difference_type difference_type;
1981        typedef typename E2::value_type value_type;
1982
1983        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
1984        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
1985        size_type size = e2 ().size ();
1986        for (difference_type n = size - 1; n >= 0; -- n) {
1987#ifndef BOOST_UBLAS_SINGULAR_CHECK
1988            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
1989#else
1990            if (e1 () (n, n) == value_type/*zero*/())
1991                singular ().raise ();
1992#endif
1993            value_type t = e2 () (n) /= e1 () (n, n);
1994            if (t != value_type/*zero*/()) {
1995                for (difference_type m = n - 1; m >= 0; -- m)
1996                    e2 () (m) -= e1 () (m, n) * t;
1997            }
1998        }
1999    }
2000    // Packed (proxy) case
2001    template<class E1, class E2>
2002    BOOST_UBLAS_INLINE
2003    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
2004                        upper_tag, column_major_tag, packed_proxy_tag) {
2005        typedef typename E2::size_type size_type;
2006        typedef typename E2::difference_type difference_type;
2007        typedef typename E2::value_type value_type;
2008
2009        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2010        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
2011        size_type size = e2 ().size ();
2012        for (difference_type n = size - 1; n >= 0; -- n) {
2013#ifndef BOOST_UBLAS_SINGULAR_CHECK
2014            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2015#else
2016            if (e1 () (n, n) == value_type/*zero*/())
2017                singular ().raise ();
2018#endif
2019            value_type t = e2 () (n) /= e1 () (n, n);
2020            if (t != value_type/*zero*/()) {
2021                typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
2022                typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
2023                difference_type m (it1e1_rend - it1e1);
2024                while (-- m >= 0)
2025                    e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
2026            }
2027        }
2028    }
2029    // Sparse (proxy) case
2030    template<class E1, class E2>
2031    BOOST_UBLAS_INLINE
2032    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
2033                        upper_tag, column_major_tag, unknown_storage_tag) {
2034        typedef typename E2::size_type size_type;
2035        typedef typename E2::difference_type difference_type;
2036        typedef typename E2::value_type value_type;
2037
2038        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2039        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
2040        size_type size = e2 ().size ();
2041        for (difference_type n = size - 1; n >= 0; -- n) {
2042#ifndef BOOST_UBLAS_SINGULAR_CHECK
2043            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2044#else
2045            if (e1 () (n, n) == value_type/*zero*/())
2046                singular ().raise ();
2047#endif
2048            value_type t = e2 () (n) /= e1 () (n, n);
2049            if (t != value_type/*zero*/()) {
2050                typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
2051                typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
2052                while (it1e1 != it1e1_rend)
2053                    e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
2054            }
2055        }
2056    }
2057    // Redirectors :-)
2058    template<class E1, class E2>
2059    BOOST_UBLAS_INLINE
2060    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
2061                        upper_tag, column_major_tag) {
2062        typedef typename E1::storage_category storage_category;
2063        inplace_solve (e1, e2,
2064                       upper_tag (), column_major_tag (), storage_category ());
2065    }
2066    template<class E1, class E2>
2067    BOOST_UBLAS_INLINE
2068    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
2069                        upper_tag, row_major_tag) {
2070        typedef typename E1::storage_category storage_category;
2071        inplace_solve (e2, trans (e1),
2072                       lower_tag (), row_major_tag (), storage_category ());
2073    }
2074    // Dispatcher
2075    template<class E1, class E2>
2076    BOOST_UBLAS_INLINE
2077    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
2078                        upper_tag) {
2079        typedef typename E1::orientation_category orientation_category;
2080        inplace_solve (e1, e2,
2081                       upper_tag (), orientation_category ());
2082    }
2083    template<class E1, class E2>
2084    BOOST_UBLAS_INLINE
2085    void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
2086                        unit_upper_tag) {
2087        typedef typename E1::orientation_category orientation_category;
2088        inplace_solve (triangular_adaptor<const E1, unit_upper> (e1 ()), e2,
2089                       unit_upper_tag (), orientation_category ());
2090    }
2091
2092    template<class E1, class E2, class C>
2093    BOOST_UBLAS_INLINE
2094    typename matrix_vector_solve_traits<E1, E2>::result_type
2095    solve (const matrix_expression<E1> &e1,
2096           const vector_expression<E2> &e2,
2097           C) {
2098        typename matrix_vector_solve_traits<E1, E2>::result_type r (e2);
2099        inplace_solve (e1, r, C ());
2100        return r;
2101    }
2102
2103    // Dense (proxy) case
2104    template<class E1, class E2>
2105    BOOST_UBLAS_INLINE
2106    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2107                        lower_tag, row_major_tag, dense_proxy_tag) {
2108        typedef typename E1::size_type size_type;
2109        typedef typename E1::difference_type difference_type;
2110        typedef typename E1::value_type value_type;
2111
2112        BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2113        BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2114        size_type size = e1 ().size ();
2115        for (difference_type n = size - 1; n >= 0; -- n) {
2116#ifndef BOOST_UBLAS_SINGULAR_CHECK
2117            BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2118#else
2119            if (e2 () (n, n) == value_type/*zero*/())
2120                singular ().raise ();
2121#endif
2122            value_type t = e1 () (n) /= e2 () (n, n);
2123            if (t != value_type/*zero*/()) {
2124                for (difference_type m = n - 1; m >= 0; -- m)
2125                    e1 () (m) -= t * e2 () (n, m);
2126            }
2127        }
2128    }
2129    // Packed (proxy) case
2130    template<class E1, class E2>
2131    BOOST_UBLAS_INLINE
2132    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2133                        lower_tag, row_major_tag, packed_proxy_tag) {
2134        typedef typename E1::size_type size_type;
2135        typedef typename E1::difference_type difference_type;
2136        typedef typename E1::value_type value_type;
2137
2138        BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2139        BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2140        size_type size = e1 ().size ();
2141        for (difference_type n = size - 1; n >= 0; -- n) {
2142#ifndef BOOST_UBLAS_SINGULAR_CHECK
2143            BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2144#else
2145            if (e2 () (n, n) == value_type/*zero*/())
2146                singular ().raise ();
2147#endif
2148            value_type t = e1 () (n) /= e2 () (n, n);
2149            if (t != value_type/*zero*/()) {
2150                typename E2::const_reverse_iterator2 it2e2 (e2 ().find2 (1, n, n));
2151                typename E2::const_reverse_iterator2 it2e2_rend (e2 ().find2 (1, n, 0));
2152                difference_type m (it2e2_rend - it2e2);
2153                while (-- m >= 0)
2154                    e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
2155            }
2156        }
2157    }
2158    // Sparse (proxy) case
2159    template<class E1, class E2>
2160    BOOST_UBLAS_INLINE
2161    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2162                        lower_tag, row_major_tag, unknown_storage_tag) {
2163        typedef typename E1::size_type size_type;
2164        typedef typename E1::difference_type difference_type;
2165        typedef typename E1::value_type value_type;
2166
2167        BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2168        BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2169        size_type size = e1 ().size ();
2170        for (difference_type n = size - 1; n >= 0; -- n) {
2171#ifndef BOOST_UBLAS_SINGULAR_CHECK
2172            BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2173#else
2174            if (e2 () (n, n) == value_type/*zero*/())
2175                singular ().raise ();
2176#endif
2177            value_type t = e1 () (n) /= e2 () (n, n);
2178            if (t != value_type/*zero*/()) {
2179                typename E2::const_reverse_iterator2 it2e2 (e2 ().find2 (1, n, n));
2180                typename E2::const_reverse_iterator2 it2e2_rend (e2 ().find2 (1, n, 0));
2181                while (it2e2 != it2e2_rend)
2182                    e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
2183            }
2184        }
2185    }
2186    // Redirectors :-)
2187    template<class E1, class E2>
2188    BOOST_UBLAS_INLINE
2189    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2190                        lower_tag, row_major_tag) {
2191        typedef typename E1::storage_category storage_category;
2192        inplace_solve (e1, e2,
2193                       lower_tag (), row_major_tag (), storage_category ());
2194    }
2195    template<class E1, class E2>
2196    BOOST_UBLAS_INLINE
2197    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2198                        lower_tag, column_major_tag) {
2199        typedef typename E1::storage_category storage_category;
2200        inplace_solve (trans (e2), e1,
2201                       upper_tag (), row_major_tag (), storage_category ());
2202    }
2203    // Dispatcher
2204    template<class E1, class E2>
2205    BOOST_UBLAS_INLINE
2206    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2207                        lower_tag) {
2208        typedef typename E2::orientation_category orientation_category;
2209        inplace_solve (e1, e2,
2210                       lower_tag (), orientation_category ());
2211    }
2212    template<class E1, class E2>
2213    BOOST_UBLAS_INLINE
2214    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2215                        unit_lower_tag) {
2216        typedef typename E2::orientation_category orientation_category;
2217        inplace_solve (e1, triangular_adaptor<const E2, unit_lower> (e2 ()),
2218                       unit_lower_tag (), orientation_category ());
2219    }
2220
2221    // Dense (proxy) case
2222    template<class E1, class E2>
2223    BOOST_UBLAS_INLINE
2224    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2225                        upper_tag, row_major_tag, dense_proxy_tag) {
2226        typedef typename E1::size_type size_type;
2227        typedef typename E1::difference_type difference_type;
2228        typedef typename E1::value_type value_type;
2229
2230        BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2231        BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2232        size_type size = e1 ().size ();
2233        for (size_type n = 0; n < size; ++ n) {
2234#ifndef BOOST_UBLAS_SINGULAR_CHECK
2235            BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2236#else
2237            if (e2 () (n, n) == value_type/*zero*/())
2238                singular ().raise ();
2239#endif
2240            value_type t = e1 () (n) /= e2 () (n, n);
2241            if (t != value_type/*zero*/()) {
2242                for (size_type m = n + 1; m < size; ++ m)
2243                    e1 () (m) -= t * e2 () (n, m);
2244            }
2245        }
2246    }
2247    // Packed (proxy) case
2248    template<class E1, class E2>
2249    BOOST_UBLAS_INLINE
2250    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2251                        upper_tag, row_major_tag, packed_proxy_tag) {
2252        typedef typename E1::size_type size_type;
2253        typedef typename E1::difference_type difference_type;
2254        typedef typename E1::value_type value_type;
2255
2256        BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2257        BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2258        size_type size = e1 ().size ();
2259        for (size_type n = 0; n < size; ++ n) {
2260#ifndef BOOST_UBLAS_SINGULAR_CHECK
2261            BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2262#else
2263            if (e2 () (n, n) == value_type/*zero*/())
2264                singular ().raise ();
2265#endif
2266            value_type t = e1 () (n) /= e2 () (n, n);
2267            if (t != value_type/*zero*/()) {
2268                typename E2::const_iterator2 it2e2 (e2 ().find2 (1, n, n + 1));
2269                typename E2::const_iterator2 it2e2_end (e2 ().find2 (1, n, e2 ().size2 ()));
2270                difference_type m (it2e2_end - it2e2);
2271                while (-- m >= 0)
2272                    e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
2273            }
2274        }
2275    }
2276    // Sparse (proxy) case
2277    template<class E1, class E2>
2278    BOOST_UBLAS_INLINE
2279    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2280                        upper_tag, row_major_tag, unknown_storage_tag) {
2281        typedef typename E1::size_type size_type;
2282        typedef typename E1::difference_type difference_type;
2283        typedef typename E1::value_type value_type;
2284
2285        BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2286        BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2287        size_type size = e1 ().size ();
2288        for (size_type n = 0; n < size; ++ n) {
2289#ifndef BOOST_UBLAS_SINGULAR_CHECK
2290            BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2291#else
2292            if (e2 () (n, n) == value_type/*zero*/())
2293                singular ().raise ();
2294#endif
2295            value_type t = e1 () (n) /= e2 () (n, n);
2296            if (t != value_type/*zero*/()) {
2297                typename E2::const_iterator2 it2e2 (e2 ().find2 (1, n, n + 1));
2298                typename E2::const_iterator2 it2e2_end (e2 ().find2 (1, n, e2 ().size2 ()));
2299                while (it2e2 != it2e2_end)
2300                    e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
2301            }
2302        }
2303    }
2304    // Redirectors :-)
2305    template<class E1, class E2>
2306    BOOST_UBLAS_INLINE
2307    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2308                        upper_tag, row_major_tag) {
2309        typedef typename E1::storage_category storage_category;
2310        inplace_solve (e1, e2,
2311                       upper_tag (), row_major_tag (), storage_category ());
2312    }
2313    template<class E1, class E2>
2314    BOOST_UBLAS_INLINE
2315    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2316                        upper_tag, column_major_tag) {
2317        typedef typename E1::storage_category storage_category;
2318        inplace_solve (trans (e2), e1,
2319                       lower_tag (), row_major_tag (), storage_category ());
2320    }
2321    // Dispatcher
2322    template<class E1, class E2>
2323    BOOST_UBLAS_INLINE
2324    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2325                        upper_tag) {
2326        typedef typename E2::orientation_category orientation_category;
2327        inplace_solve (e1, e2,
2328                       upper_tag (), orientation_category ());
2329    }
2330    template<class E1, class E2>
2331    BOOST_UBLAS_INLINE
2332    void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2333                        unit_upper_tag) {
2334        typedef typename E2::orientation_category orientation_category;
2335        inplace_solve (e1, triangular_adaptor<const E2, unit_upper> (e2 ()),
2336                       unit_upper_tag (), orientation_category ());
2337    }
2338
2339    template<class E1, class E2, class C>
2340    BOOST_UBLAS_INLINE
2341    typename matrix_vector_solve_traits<E1, E2>::result_type
2342    solve (const vector_expression<E1> &e1,
2343           const matrix_expression<E2> &e2,
2344           C) {
2345        typename matrix_vector_solve_traits<E1, E2>::result_type r (e1);
2346        inplace_solve (r, e2, C ());
2347        return r;
2348    }
2349
2350    template<class E1, class E2>
2351    struct matrix_matrix_solve_traits {
2352        typedef typename promote_traits<typename E1::value_type, typename E2::value_type>::promote_type promote_type;
2353        typedef matrix<promote_type> result_type;
2354    };
2355
2356    // Operations:
2357    //  k * n * (n - 1) / 2 + k * n = k * n * (n + 1) / 2 multiplications,
2358    //  k * n * (n - 1) / 2 additions
2359
2360    // Dense (proxy) case
2361    template<class E1, class E2>
2362    BOOST_UBLAS_INLINE
2363    void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2364                        lower_tag, dense_proxy_tag) {
2365        typedef typename E2::size_type size_type;
2366        typedef typename E2::difference_type difference_type;
2367        typedef typename E2::value_type value_type;
2368
2369        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2370        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2371        size_type size1 = e2 ().size1 ();
2372        size_type size2 = e2 ().size2 ();
2373        for (size_type n = 0; n < size1; ++ n) {
2374#ifndef BOOST_UBLAS_SINGULAR_CHECK
2375            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2376#else
2377            if (e1 () (n, n) == value_type/*zero*/())
2378                singular ().raise ();
2379#endif
2380            for (size_type l = 0; l < size2; ++ l) {
2381                value_type t = e2 () (n, l) /= e1 () (n, n);
2382                if (t != value_type/*zero*/()) {
2383                    for (size_type m = n + 1; m < size1; ++ m)
2384                        e2 () (m, l) -= e1 () (m, n) * t;
2385                }
2386            }
2387        }
2388    }
2389    // Packed (proxy) case
2390    template<class E1, class E2>
2391    BOOST_UBLAS_INLINE
2392    void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2393                        lower_tag, packed_proxy_tag) {
2394        typedef typename E2::size_type size_type;
2395        typedef typename E2::difference_type difference_type;
2396        typedef typename E2::value_type value_type;
2397
2398        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2399        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2400        size_type size1 = e2 ().size1 ();
2401        size_type size2 = e2 ().size2 ();
2402        for (size_type n = 0; n < size1; ++ n) {
2403#ifndef BOOST_UBLAS_SINGULAR_CHECK
2404            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2405#else
2406            if (e1 () (n, n) == value_type/*zero*/())
2407                singular ().raise ();
2408#endif
2409            for (size_type l = 0; l < size2; ++ l) {
2410                value_type t = e2 () (n, l) /= e1 () (n, n);
2411                if (t != value_type/*zero*/()) {
2412                    typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
2413                    typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
2414                    difference_type m (it1e1_end - it1e1);
2415                    while (-- m >= 0)
2416                        e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
2417                }
2418            }
2419        }
2420    }
2421    // Sparse (proxy) case
2422    template<class E1, class E2>
2423    BOOST_UBLAS_INLINE
2424    void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2425                        lower_tag, unknown_storage_tag) {
2426        typedef typename E2::size_type size_type;
2427        typedef typename E2::difference_type difference_type;
2428        typedef typename E2::value_type value_type;
2429
2430        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2431        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2432        size_type size1 = e2 ().size1 ();
2433        size_type size2 = e2 ().size2 ();
2434        for (size_type n = 0; n < size1; ++ n) {
2435#ifndef BOOST_UBLAS_SINGULAR_CHECK
2436            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2437#else
2438            if (e1 () (n, n) == value_type/*zero*/())
2439                singular ().raise ();
2440#endif
2441            for (size_type l = 0; l < size2; ++ l) {
2442                value_type t = e2 () (n, l) /= e1 () (n, n);
2443                if (t != value_type/*zero*/()) {
2444                    typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
2445                    typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
2446                    while (it1e1 != it1e1_end)
2447                        e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
2448                }
2449            }
2450        }
2451    }
2452    // Dispatcher
2453    template<class E1, class E2>
2454    BOOST_UBLAS_INLINE
2455    void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2456                        lower_tag) {
2457        typedef typename E1::storage_category dispatch_category;
2458        inplace_solve (e1, e2,
2459                       lower_tag (), dispatch_category ());
2460    }
2461    template<class E1, class E2>
2462    BOOST_UBLAS_INLINE
2463    void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2464                        unit_lower_tag) {
2465        typedef typename E1::storage_category dispatch_category;
2466        inplace_solve (triangular_adaptor<const E1, unit_lower> (e1 ()), e2,
2467                       unit_lower_tag (), dispatch_category ());
2468    }
2469
2470    // Dense (proxy) case
2471    template<class E1, class E2>
2472    BOOST_UBLAS_INLINE
2473    void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2474                        upper_tag, dense_proxy_tag) {
2475        typedef typename E2::size_type size_type;
2476        typedef typename E2::difference_type difference_type;
2477        typedef typename E2::value_type value_type;
2478
2479        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2480        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2481        size_type size1 = e2 ().size1 ();
2482        size_type size2 = e2 ().size2 ();
2483        for (difference_type n = size1 - 1; n >= 0; -- n) {
2484#ifndef BOOST_UBLAS_SINGULAR_CHECK
2485            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2486#else
2487            if (e1 () (n, n) == value_type/*zero*/())
2488                singular ().raise ();
2489#endif
2490            for (difference_type l = size2 - 1; l >= 0; -- l) {
2491                value_type t = e2 () (n, l) /= e1 () (n, n);
2492                if (t != value_type/*zero*/()) {
2493                    for (difference_type m = n - 1; m >= 0; -- m)
2494                        e2 () (m, l) -= e1 () (m, n) * t;
2495                }
2496            }
2497        }
2498    }
2499    // Packed (proxy) case
2500    template<class E1, class E2>
2501    BOOST_UBLAS_INLINE
2502    void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2503                        upper_tag, packed_proxy_tag) {
2504        typedef typename E2::size_type size_type;
2505        typedef typename E2::difference_type difference_type;
2506        typedef typename E2::value_type value_type;
2507
2508        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2509        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2510        size_type size1 = e2 ().size1 ();
2511        size_type size2 = e2 ().size2 ();
2512        for (difference_type n = size1 - 1; n >= 0; -- n) {
2513#ifndef BOOST_UBLAS_SINGULAR_CHECK
2514            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2515#else
2516            if (e1 () (n, n) == value_type/*zero*/())
2517                singular ().raise ();
2518#endif
2519            for (difference_type l = size2 - 1; l >= 0; -- l) {
2520                value_type t = e2 () (n, l) /= e1 () (n, n);
2521                if (t != value_type/*zero*/()) {
2522                    typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
2523                    typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
2524                    difference_type m (it1e1_rend - it1e1);
2525                    while (-- m >= 0)
2526                        e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
2527                }
2528            }
2529        }
2530    }
2531    // Sparse (proxy) case
2532    template<class E1, class E2>
2533    BOOST_UBLAS_INLINE
2534    void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2535                        upper_tag, unknown_storage_tag) {
2536        typedef typename E2::size_type size_type;
2537        typedef typename E2::difference_type difference_type;
2538        typedef typename E2::value_type value_type;
2539
2540        BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2541        BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2542        size_type size1 = e2 ().size1 ();
2543        size_type size2 = e2 ().size2 ();
2544        for (difference_type n = size1 - 1; n >= 0; -- n) {
2545#ifndef BOOST_UBLAS_SINGULAR_CHECK
2546            BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2547#else
2548            if (e1 () (n, n) == value_type/*zero*/())
2549                singular ().raise ();
2550#endif
2551            for (difference_type l = size2 - 1; l >= 0; -- l) {
2552                value_type t = e2 () (n, l) /= e1 () (n, n);
2553                if (t != value_type/*zero*/()) {
2554                    typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
2555                    typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
2556                    while (it1e1 != it1e1_rend)
2557                        e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
2558                }
2559            }
2560        }
2561    }
2562    // Dispatcher
2563    template<class E1, class E2>
2564    BOOST_UBLAS_INLINE
2565    void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2566                        upper_tag) {
2567        typedef typename E1::storage_category dispatch_category;
2568        inplace_solve (e1, e2,
2569                       upper_tag (), dispatch_category ());
2570    }
2571    template<class E1, class E2>
2572    BOOST_UBLAS_INLINE
2573    void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2574                        unit_upper_tag) {
2575        typedef typename E1::storage_category dispatch_category;
2576        inplace_solve (triangular_adaptor<const E1, unit_upper> (e1 ()), e2,
2577                       unit_upper_tag (), dispatch_category ());
2578    }
2579
2580    template<class E1, class E2, class C>
2581    BOOST_UBLAS_INLINE
2582    typename matrix_matrix_solve_traits<E1, E2>::result_type
2583    solve (const matrix_expression<E1> &e1,
2584           const matrix_expression<E2> &e2,
2585           C) {
2586        typename matrix_matrix_solve_traits<E1, E2>::result_type r (e2);
2587        inplace_solve (e1, r, C ());
2588        return r;
2589    }
2590
2591}}}
2592
2593#endif
Note: See TracBrowser for help on using the repository browser.