source: XIOS/dev/dev_olga/src/extern/boost/include/boost/numeric/ublas/detail/matrix_assign.hpp @ 1022

Last change on this file since 1022 was 1022, checked in by mhnguyen, 7 years ago
File size: 76.2 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_MATRIX_ASSIGN_
14#define _BOOST_UBLAS_MATRIX_ASSIGN_
15
16// Required for make_conformant storage
17#include <vector>
18
19// Iterators based on ideas of Jeremy Siek
20
21namespace boost { namespace numeric { namespace ublas {
22namespace detail {
23   
24    // Weak equality check - useful to compare equality two arbitary matrix expression results.
25    // Since the actual expressions are unknown, we check for and arbitary error bound
26    // on the relative error.
27    // For a linear expression the infinity norm makes sense as we do not know how the elements will be
28    // combined in the expression. False positive results are inevitable for arbirary expressions!
29    template<class E1, class E2, class S>
30    BOOST_UBLAS_INLINE
31    bool equals (const matrix_expression<E1> &e1, const matrix_expression<E2> &e2, S epsilon, S min_norm) {
32        return norm_inf (e1 - e2) < epsilon *
33               std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);
34    }
35
36    template<class E1, class E2>
37    BOOST_UBLAS_INLINE
38    bool expression_type_check (const matrix_expression<E1> &e1, const matrix_expression<E2> &e2) {
39        typedef typename type_traits<typename promote_traits<typename E1::value_type,
40                                     typename E2::value_type>::promote_type>::real_type real_type;
41        return equals (e1, e2, BOOST_UBLAS_TYPE_CHECK_EPSILON, BOOST_UBLAS_TYPE_CHECK_MIN);
42    }
43
44
45    template<class M, class E, class R>
46    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
47    void make_conformant (M &m, const matrix_expression<E> &e, row_major_tag, R) {
48        BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
49        BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
50        typedef R conformant_restrict_type;
51        typedef typename M::size_type size_type;
52        typedef typename M::difference_type difference_type;
53        typedef typename M::value_type value_type;
54        // FIXME unbounded_array with push_back maybe better
55        std::vector<std::pair<size_type, size_type> > index;
56        typename M::iterator1 it1 (m.begin1 ());
57        typename M::iterator1 it1_end (m.end1 ());
58        typename E::const_iterator1 it1e (e ().begin1 ());
59        typename E::const_iterator1 it1e_end (e ().end1 ());
60        while (it1 != it1_end && it1e != it1e_end) {
61            difference_type compare = it1.index1 () - it1e.index1 ();
62            if (compare == 0) {
63#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
64                typename M::iterator2 it2 (it1.begin ());
65                typename M::iterator2 it2_end (it1.end ());
66                typename E::const_iterator2 it2e (it1e.begin ());
67                typename E::const_iterator2 it2e_end (it1e.end ());
68#else
69                typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
70                typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
71                typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
72                typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
73#endif
74                if (it2 != it2_end && it2e != it2e_end) {
75                    size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
76                    while (true) {
77                        difference_type compare = it2_index - it2e_index;
78                        if (compare == 0) {
79                            ++ it2, ++ it2e;
80                            if (it2 != it2_end && it2e != it2e_end) {
81                                it2_index = it2.index2 ();
82                                it2e_index = it2e.index2 ();
83                            } else
84                                break;
85                        } else if (compare < 0) {
86                            increment (it2, it2_end, - compare);
87                            if (it2 != it2_end)
88                                it2_index = it2.index2 ();
89                            else
90                                break;
91                        } else if (compare > 0) {
92                            if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
93                                if (*it2e != value_type/*zero*/())
94                                    index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
95                            ++ it2e;
96                            if (it2e != it2e_end)
97                                it2e_index = it2e.index2 ();
98                            else
99                                break;
100                        }
101                    }
102                }
103                while (it2e != it2e_end) {
104                    if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
105                        if (*it2e != value_type/*zero*/())
106                            index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
107                    ++ it2e;
108                }
109                ++ it1, ++ it1e;
110            } else if (compare < 0) {
111                increment (it1, it1_end, - compare);
112            } else if (compare > 0) {
113#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
114                typename E::const_iterator2 it2e (it1e.begin ());
115                typename E::const_iterator2 it2e_end (it1e.end ());
116#else
117                typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
118                typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
119#endif
120                while (it2e != it2e_end) {
121                    if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
122                        if (*it2e != value_type/*zero*/())
123                            index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
124                    ++ it2e;
125                }
126                ++ it1e;
127            }
128        }
129        while (it1e != it1e_end) {
130#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
131            typename E::const_iterator2 it2e (it1e.begin ());
132            typename E::const_iterator2 it2e_end (it1e.end ());
133#else
134            typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
135            typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
136#endif
137            while (it2e != it2e_end) {
138                if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
139                    if (*it2e != value_type/*zero*/())
140                        index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
141                ++ it2e;
142            }
143            ++ it1e;
144        }
145        // ISSUE proxies require insert_element
146        for (size_type k = 0; k < index.size (); ++ k)
147            m (index [k].first, index [k].second) = value_type/*zero*/();
148    }
149    template<class M, class E, class R>
150    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
151    void make_conformant (M &m, const matrix_expression<E> &e, column_major_tag, R) {
152        BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
153        BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
154        typedef R conformant_restrict_type;
155        typedef typename M::size_type size_type;
156        typedef typename M::difference_type difference_type;
157        typedef typename M::value_type value_type;
158        std::vector<std::pair<size_type, size_type> > index;
159        typename M::iterator2 it2 (m.begin2 ());
160        typename M::iterator2 it2_end (m.end2 ());
161        typename E::const_iterator2 it2e (e ().begin2 ());
162        typename E::const_iterator2 it2e_end (e ().end2 ());
163        while (it2 != it2_end && it2e != it2e_end) {
164            difference_type compare = it2.index2 () - it2e.index2 ();
165            if (compare == 0) {
166#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
167                typename M::iterator1 it1 (it2.begin ());
168                typename M::iterator1 it1_end (it2.end ());
169                typename E::const_iterator1 it1e (it2e.begin ());
170                typename E::const_iterator1 it1e_end (it2e.end ());
171#else
172                typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
173                typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
174                typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
175                typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
176#endif
177                if (it1 != it1_end && it1e != it1e_end) {
178                    size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
179                    while (true) {
180                        difference_type compare = it1_index - it1e_index;
181                        if (compare == 0) {
182                            ++ it1, ++ it1e;
183                            if (it1 != it1_end && it1e != it1e_end) {
184                                it1_index = it1.index1 ();
185                                it1e_index = it1e.index1 ();
186                            } else
187                                break;
188                        } else if (compare < 0) {
189                            increment (it1, it1_end, - compare);
190                            if (it1 != it1_end)
191                                it1_index = it1.index1 ();
192                            else
193                                break;
194                        } else if (compare > 0) {
195                            if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
196                                if (*it1e != value_type/*zero*/())
197                                    index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
198                            ++ it1e;
199                            if (it1e != it1e_end)
200                                it1e_index = it1e.index1 ();
201                            else
202                                break;
203                        }
204                    }
205                }
206                while (it1e != it1e_end) {
207                    if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
208                        if (*it1e != value_type/*zero*/())
209                            index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
210                    ++ it1e;
211                }
212                ++ it2, ++ it2e;
213            } else if (compare < 0) {
214                increment (it2, it2_end, - compare);
215            } else if (compare > 0) {
216#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
217                typename E::const_iterator1 it1e (it2e.begin ());
218                typename E::const_iterator1 it1e_end (it2e.end ());
219#else
220                typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
221                typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
222#endif
223                while (it1e != it1e_end) {
224                    if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
225                        if (*it1e != value_type/*zero*/())
226                            index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
227                    ++ it1e;
228                }
229                ++ it2e;
230            }
231        }
232        while (it2e != it2e_end) {
233#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
234            typename E::const_iterator1 it1e (it2e.begin ());
235            typename E::const_iterator1 it1e_end (it2e.end ());
236#else
237            typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
238            typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
239#endif
240            while (it1e != it1e_end) {
241                if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
242                    if (*it1e != value_type/*zero*/())
243                        index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
244                ++ it1e;
245            }
246            ++ it2e;
247        }
248        // ISSUE proxies require insert_element
249        for (size_type k = 0; k < index.size (); ++ k)
250            m (index [k].first, index [k].second) = value_type/*zero*/();
251    }
252
253}//namespace detail
254
255
256    // Explicitly iterating row major
257    template<template <class T1, class T2> class F, class M, class T>
258    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
259    void iterating_matrix_assign_scalar (M &m, const T &t, row_major_tag) {
260        typedef F<typename M::iterator2::reference, T> functor_type;
261        typedef typename M::difference_type difference_type;
262        difference_type size1 (m.size1 ());
263        difference_type size2 (m.size2 ());
264        typename M::iterator1 it1 (m.begin1 ());
265        BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ());
266        while (-- size1 >= 0) {
267#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
268            typename M::iterator2 it2 (it1.begin ());
269#else
270            typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
271#endif
272            BOOST_UBLAS_CHECK (it1.end () - it2 == size2, bad_size ());
273            difference_type temp_size2 (size2);
274#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
275            while (-- temp_size2 >= 0)
276                functor_type::apply (*it2, t), ++ it2;
277#else
278            DD (temp_size2, 4, r, (functor_type::apply (*it2, t), ++ it2));
279#endif
280            ++ it1;
281        }
282    }
283    // Explicitly iterating column major
284    template<template <class T1, class T2> class F, class M, class T>
285    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
286    void iterating_matrix_assign_scalar (M &m, const T &t, column_major_tag) {
287        typedef F<typename M::iterator1::reference, T> functor_type;
288        typedef typename M::difference_type difference_type;
289        difference_type size2 (m.size2 ());
290        difference_type size1 (m.size1 ());
291        typename M::iterator2 it2 (m.begin2 ());
292        BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ());
293        while (-- size2 >= 0) {
294#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
295            typename M::iterator1 it1 (it2.begin ());
296#else
297            typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
298#endif
299            BOOST_UBLAS_CHECK (it2.end () - it1 == size1, bad_size ());
300            difference_type temp_size1 (size1);
301#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
302            while (-- temp_size1 >= 0)
303                functor_type::apply (*it1, t), ++ it1;
304#else
305            DD (temp_size1, 4, r, (functor_type::apply (*it1, t), ++ it1));
306#endif
307            ++ it2;
308        }
309    }
310    // Explicitly indexing row major
311    template<template <class T1, class T2> class F, class M, class T>
312    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
313    void indexing_matrix_assign_scalar (M &m, const T &t, row_major_tag) {
314        typedef F<typename M::reference, T> functor_type;
315        typedef typename M::size_type size_type;
316        size_type size1 (m.size1 ());
317        size_type size2 (m.size2 ());
318        for (size_type i = 0; i < size1; ++ i) {
319#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
320            for (size_type j = 0; j < size2; ++ j)
321                functor_type::apply (m (i, j), t);
322#else
323            size_type j (0);
324            DD (size2, 4, r, (functor_type::apply (m (i, j), t), ++ j));
325#endif
326        }
327    }
328    // Explicitly indexing column major
329    template<template <class T1, class T2> class F, class M, class T>
330    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
331    void indexing_matrix_assign_scalar (M &m, const T &t, column_major_tag) {
332        typedef F<typename M::reference, T> functor_type;
333        typedef typename M::size_type size_type;
334        size_type size2 (m.size2 ());
335        size_type size1 (m.size1 ());
336        for (size_type j = 0; j < size2; ++ j) {
337#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
338            for (size_type i = 0; i < size1; ++ i)
339                functor_type::apply (m (i, j), t);
340#else
341            size_type i (0);
342            DD (size1, 4, r, (functor_type::apply (m (i, j), t), ++ i));
343#endif
344        }
345    }
346
347    // Dense (proxy) case
348    template<template <class T1, class T2> class F, class M, class T, class C>
349    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
350    void matrix_assign_scalar (M &m, const T &t, dense_proxy_tag, C) {
351        typedef C orientation_category;
352#ifdef BOOST_UBLAS_USE_INDEXING
353        indexing_matrix_assign_scalar<F> (m, t, orientation_category ());
354#elif BOOST_UBLAS_USE_ITERATING
355        iterating_matrix_assign_scalar<F> (m, t, orientation_category ());
356#else
357        typedef typename M::size_type size_type;
358        size_type size1 (m.size1 ());
359        size_type size2 (m.size2 ());
360        if (size1 >= BOOST_UBLAS_ITERATOR_THRESHOLD &&
361            size2 >= BOOST_UBLAS_ITERATOR_THRESHOLD)
362            iterating_matrix_assign_scalar<F> (m, t, orientation_category ());
363        else
364            indexing_matrix_assign_scalar<F> (m, t, orientation_category ());
365#endif
366    }
367    // Packed (proxy) row major case
368    template<template <class T1, class T2> class F, class M, class T>
369    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
370    void matrix_assign_scalar (M &m, const T &t, packed_proxy_tag, row_major_tag) {
371        typedef F<typename M::iterator2::reference, T> functor_type;
372        typedef typename M::difference_type difference_type;
373        typename M::iterator1 it1 (m.begin1 ());
374        difference_type size1 (m.end1 () - it1);
375        while (-- size1 >= 0) {
376#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
377            typename M::iterator2 it2 (it1.begin ());
378            difference_type size2 (it1.end () - it2);
379#else
380            typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
381            difference_type size2 (end (it1, iterator1_tag ()) - it2);
382#endif
383            while (-- size2 >= 0)
384                functor_type::apply (*it2, t), ++ it2;
385            ++ it1;
386        }
387    }
388    // Packed (proxy) column major case
389    template<template <class T1, class T2> class F, class M, class T>
390    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
391    void matrix_assign_scalar (M &m, const T &t, packed_proxy_tag, column_major_tag) {
392        typedef F<typename M::iterator1::reference, T> functor_type;
393        typedef typename M::difference_type difference_type;
394        typename M::iterator2 it2 (m.begin2 ());
395        difference_type size2 (m.end2 () - it2);
396        while (-- size2 >= 0) {
397#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
398            typename M::iterator1 it1 (it2.begin ());
399            difference_type size1 (it2.end () - it1);
400#else
401            typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
402            difference_type size1 (end (it2, iterator2_tag ()) - it1);
403#endif
404            while (-- size1 >= 0)
405                functor_type::apply (*it1, t), ++ it1;
406            ++ it2;
407        }
408    }
409    // Sparse (proxy) row major case
410    template<template <class T1, class T2> class F, class M, class T>
411    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
412    void matrix_assign_scalar (M &m, const T &t, sparse_proxy_tag, row_major_tag) {
413        typedef F<typename M::iterator2::reference, T> functor_type;
414        typename M::iterator1 it1 (m.begin1 ());
415        typename M::iterator1 it1_end (m.end1 ());
416        while (it1 != it1_end) {
417#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
418            typename M::iterator2 it2 (it1.begin ());
419            typename M::iterator2 it2_end (it1.end ());
420#else
421            typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
422            typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
423#endif
424            while (it2 != it2_end)
425                functor_type::apply (*it2, t), ++ it2;
426            ++ it1;
427        }
428    }
429    // Sparse (proxy) column major case
430    template<template <class T1, class T2> class F, class M, class T>
431    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
432    void matrix_assign_scalar (M &m, const T &t, sparse_proxy_tag, column_major_tag) {
433        typedef F<typename M::iterator1::reference, T> functor_type;
434        typename M::iterator2 it2 (m.begin2 ());
435        typename M::iterator2 it2_end (m.end2 ());
436        while (it2 != it2_end) {
437#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
438            typename M::iterator1 it1 (it2.begin ());
439            typename M::iterator1 it1_end (it2.end ());
440#else
441            typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
442            typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
443#endif
444            while (it1 != it1_end)
445                functor_type::apply (*it1, t), ++ it1;
446            ++ it2;
447        }
448    }
449
450    // Dispatcher
451    template<template <class T1, class T2> class F, class M, class T>
452    BOOST_UBLAS_INLINE
453    void matrix_assign_scalar (M &m, const T &t) {
454        typedef typename M::storage_category storage_category;
455        typedef typename M::orientation_category orientation_category;
456        matrix_assign_scalar<F> (m, t, storage_category (), orientation_category ());
457    }
458
459    template<class SC, bool COMPUTED, class RI1, class RI2>
460    struct matrix_assign_traits {
461        typedef SC storage_category;
462    };
463
464    template<bool COMPUTED>
465    struct matrix_assign_traits<dense_tag, COMPUTED, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
466        typedef packed_tag storage_category;
467    };
468    template<>
469    struct matrix_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
470        typedef sparse_tag storage_category;
471    };
472    template<>
473    struct matrix_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
474        typedef sparse_proxy_tag storage_category;
475    };
476
477    template<bool COMPUTED>
478    struct matrix_assign_traits<dense_proxy_tag, COMPUTED, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
479        typedef packed_proxy_tag storage_category;
480    };
481    template<bool COMPUTED>
482    struct matrix_assign_traits<dense_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
483        typedef sparse_proxy_tag storage_category;
484    };
485
486    template<>
487    struct matrix_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
488        typedef sparse_tag storage_category;
489    };
490    template<>
491    struct matrix_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
492        typedef sparse_proxy_tag storage_category;
493    };
494
495    template<bool COMPUTED>
496    struct matrix_assign_traits<packed_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
497        typedef sparse_proxy_tag storage_category;
498    };
499
500    template<>
501    struct matrix_assign_traits<sparse_tag, true, dense_random_access_iterator_tag, dense_random_access_iterator_tag> {
502        typedef sparse_proxy_tag storage_category;
503    };
504    template<>
505    struct matrix_assign_traits<sparse_tag, true, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
506        typedef sparse_proxy_tag storage_category;
507    };
508    template<>
509    struct matrix_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
510        typedef sparse_proxy_tag storage_category;
511    };
512
513    // Explicitly iterating row major
514    template<template <class T1, class T2> class F, class M, class E>
515    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
516    void iterating_matrix_assign (M &m, const matrix_expression<E> &e, row_major_tag) {
517        typedef F<typename M::iterator2::reference, typename E::value_type> functor_type;
518        typedef typename M::difference_type difference_type;
519        difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
520        difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
521        typename M::iterator1 it1 (m.begin1 ());
522        BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ());
523        typename E::const_iterator1 it1e (e ().begin1 ());
524        BOOST_UBLAS_CHECK (size2 == 0 || e ().end1 () - it1e == size1, bad_size ());
525        while (-- size1 >= 0) {
526#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
527            typename M::iterator2 it2 (it1.begin ());
528            typename E::const_iterator2 it2e (it1e.begin ());
529#else
530            typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
531            typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
532#endif
533            BOOST_UBLAS_CHECK (it1.end () - it2 == size2, bad_size ());
534            BOOST_UBLAS_CHECK (it1e.end () - it2e == size2, bad_size ());
535            difference_type temp_size2 (size2);
536#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
537            while (-- temp_size2 >= 0)
538                functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
539#else
540            DD (temp_size2, 2, r, (functor_type::apply (*it2, *it2e), ++ it2, ++ it2e));
541#endif
542            ++ it1, ++ it1e;
543        }
544    }
545    // Explicitly iterating column major
546    template<template <class T1, class T2> class F, class M, class E>
547    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
548    void iterating_matrix_assign (M &m, const matrix_expression<E> &e, column_major_tag) {
549        typedef F<typename M::iterator1::reference, typename E::value_type> functor_type;
550        typedef typename M::difference_type difference_type;
551        difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
552        difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
553        typename M::iterator2 it2 (m.begin2 ());
554        BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ());
555        typename E::const_iterator2 it2e (e ().begin2 ());
556        BOOST_UBLAS_CHECK (size1 == 0 || e ().end2 () - it2e == size2, bad_size ());
557        while (-- size2 >= 0) {
558#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
559            typename M::iterator1 it1 (it2.begin ());
560            typename E::const_iterator1 it1e (it2e.begin ());
561#else
562            typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
563            typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
564#endif
565            BOOST_UBLAS_CHECK (it2.end () - it1 == size1, bad_size ());
566            BOOST_UBLAS_CHECK (it2e.end () - it1e == size1, bad_size ());
567            difference_type temp_size1 (size1);
568#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
569            while (-- temp_size1 >= 0)
570                functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
571#else
572            DD (temp_size1, 2, r, (functor_type::apply (*it1, *it1e), ++ it1, ++ it1e));
573#endif
574            ++ it2, ++ it2e;
575        }
576    }
577    // Explicitly indexing row major
578    template<template <class T1, class T2> class F, class M, class E>
579    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
580    void indexing_matrix_assign (M &m, const matrix_expression<E> &e, row_major_tag) {
581        typedef F<typename M::reference, typename E::value_type> functor_type;
582        typedef typename M::size_type size_type;
583        size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
584        size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
585        for (size_type i = 0; i < size1; ++ i) {
586#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
587            for (size_type j = 0; j < size2; ++ j)
588                functor_type::apply (m (i, j), e () (i, j));
589#else
590            size_type j (0);
591            DD (size2, 2, r, (functor_type::apply (m (i, j), e () (i, j)), ++ j));
592#endif
593        }
594    }
595    // Explicitly indexing column major
596    template<template <class T1, class T2> class F, class M, class E>
597    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
598    void indexing_matrix_assign (M &m, const matrix_expression<E> &e, column_major_tag) {
599        typedef F<typename M::reference, typename E::value_type> functor_type;
600        typedef typename M::size_type size_type;
601        size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
602        size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
603        for (size_type j = 0; j < size2; ++ j) {
604#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
605            for (size_type i = 0; i < size1; ++ i)
606                functor_type::apply (m (i, j), e () (i, j));
607#else
608            size_type i (0);
609            DD (size1, 2, r, (functor_type::apply (m (i, j), e () (i, j)), ++ i));
610#endif
611        }
612    }
613
614    // Dense (proxy) case
615    template<template <class T1, class T2> class F, class R, class M, class E, class C>
616    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
617    void matrix_assign (M &m, const matrix_expression<E> &e, dense_proxy_tag, C) {
618        // R unnecessary, make_conformant not required
619        typedef C orientation_category;
620#ifdef BOOST_UBLAS_USE_INDEXING
621        indexing_matrix_assign<F> (m, e, orientation_category ());
622#elif BOOST_UBLAS_USE_ITERATING
623        iterating_matrix_assign<F> (m, e, orientation_category ());
624#else
625        typedef typename M::difference_type difference_type;
626        size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
627        size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
628        if (size1 >= BOOST_UBLAS_ITERATOR_THRESHOLD &&
629            size2 >= BOOST_UBLAS_ITERATOR_THRESHOLD)
630            iterating_matrix_assign<F> (m, e, orientation_category ());
631        else
632            indexing_matrix_assign<F> (m, e, orientation_category ());
633#endif
634    }
635    // Packed (proxy) row major case
636    template<template <class T1, class T2> class F, class R, class M, class E>
637    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
638    void matrix_assign (M &m, const matrix_expression<E> &e, packed_proxy_tag, row_major_tag) {
639        typedef F<typename M::iterator2::reference, typename E::value_type> functor_type;
640        // R unnecessary, make_conformant not required
641        typedef typename M::difference_type difference_type;
642        typedef typename M::value_type value_type;
643        BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
644        BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
645#if BOOST_UBLAS_TYPE_CHECK
646        matrix<value_type, row_major> cm (m.size1 (), m.size2 ());
647        indexing_matrix_assign<scalar_assign> (cm, m, row_major_tag ());
648        indexing_matrix_assign<F> (cm, e, row_major_tag ());
649#endif
650        typename M::iterator1 it1 (m.begin1 ());
651        typename M::iterator1 it1_end (m.end1 ());
652        typename E::const_iterator1 it1e (e ().begin1 ());
653        typename E::const_iterator1 it1e_end (e ().end1 ());
654        difference_type it1_size (it1_end - it1);
655        difference_type it1e_size (it1e_end - it1e);
656        difference_type diff1 (0);
657        if (it1_size > 0 && it1e_size > 0)
658            diff1 = it1.index1 () - it1e.index1 ();
659        if (diff1 != 0) {
660            difference_type size1 = (std::min) (diff1, it1e_size);
661            if (size1 > 0) {
662                it1e += size1;
663                it1e_size -= size1;
664                diff1 -= size1;
665            }
666            size1 = (std::min) (- diff1, it1_size);
667            if (size1 > 0) {
668                it1_size -= size1;
669                if (!functor_type::computed) {
670                    while (-- size1 >= 0) { // zeroing
671#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
672                        typename M::iterator2 it2 (it1.begin ());
673                        typename M::iterator2 it2_end (it1.end ());
674#else
675                        typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
676                        typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
677#endif
678                        difference_type size2 (it2_end - it2);
679                        while (-- size2 >= 0)
680                            functor_type::apply (*it2, value_type/*zero*/()), ++ it2;
681                        ++ it1;
682                    }
683                } else {
684                    it1 += size1;
685                }
686                diff1 += size1;
687            }
688        }
689        difference_type size1 ((std::min) (it1_size, it1e_size));
690        it1_size -= size1;
691        it1e_size -= size1;
692        while (-- size1 >= 0) {
693#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
694            typename M::iterator2 it2 (it1.begin ());
695            typename M::iterator2 it2_end (it1.end ());
696            typename E::const_iterator2 it2e (it1e.begin ());
697            typename E::const_iterator2 it2e_end (it1e.end ());
698#else
699            typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
700            typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
701            typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
702            typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
703#endif
704            difference_type it2_size (it2_end - it2);
705            difference_type it2e_size (it2e_end - it2e);
706            difference_type diff2 (0);
707            if (it2_size > 0 && it2e_size > 0) {
708                diff2 = it2.index2 () - it2e.index2 ();
709                difference_type size2 = (std::min) (diff2, it2e_size);
710                if (size2 > 0) {
711                    it2e += size2;
712                    it2e_size -= size2;
713                    diff2 -= size2;
714                }
715                size2 = (std::min) (- diff2, it2_size);
716                if (size2 > 0) {
717                    it2_size -= size2;
718                    if (!functor_type::computed) {
719                        while (-- size2 >= 0)   // zeroing
720                            functor_type::apply (*it2, value_type/*zero*/()), ++ it2;
721                    } else {
722                        it2 += size2;
723                    }
724                    diff2 += size2;
725                }
726            }
727            difference_type size2 ((std::min) (it2_size, it2e_size));
728            it2_size -= size2;
729            it2e_size -= size2;
730            while (-- size2 >= 0)
731                functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
732            size2 = it2_size;
733            if (!functor_type::computed) {
734                while (-- size2 >= 0)   // zeroing
735                    functor_type::apply (*it2, value_type/*zero*/()), ++ it2;
736            } else {
737                it2 += size2;
738            }
739            ++ it1, ++ it1e;
740        }
741        size1 = it1_size;
742        if (!functor_type::computed) {
743            while (-- size1 >= 0) { // zeroing
744#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
745                typename M::iterator2 it2 (it1.begin ());
746                typename M::iterator2 it2_end (it1.end ());
747#else
748                typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
749                typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
750#endif
751                difference_type size2 (it2_end - it2);
752                while (-- size2 >= 0)
753                    functor_type::apply (*it2, value_type/*zero*/()), ++ it2;
754                ++ it1;
755            }
756        } else {
757            it1 += size1;
758        }
759#if BOOST_UBLAS_TYPE_CHECK
760        if (! disable_type_check<bool>::value)
761            BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
762#endif
763    }
764    // Packed (proxy) column major case
765    template<template <class T1, class T2> class F, class R, class M, class E>
766    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
767    void matrix_assign (M &m, const matrix_expression<E> &e, packed_proxy_tag, column_major_tag) {
768        typedef F<typename M::iterator1::reference, typename E::value_type> functor_type;
769        // R unnecessary, make_conformant not required
770        typedef typename M::difference_type difference_type;
771        typedef typename M::value_type value_type;
772        BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
773        BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
774#if BOOST_UBLAS_TYPE_CHECK
775        matrix<value_type, column_major> cm (m.size1 (), m.size2 ());
776        indexing_matrix_assign<scalar_assign> (cm, m, column_major_tag ());
777        indexing_matrix_assign<F> (cm, e, column_major_tag ());
778#endif
779        typename M::iterator2 it2 (m.begin2 ());
780        typename M::iterator2 it2_end (m.end2 ());
781        typename E::const_iterator2 it2e (e ().begin2 ());
782        typename E::const_iterator2 it2e_end (e ().end2 ());
783        difference_type it2_size (it2_end - it2);
784        difference_type it2e_size (it2e_end - it2e);
785        difference_type diff2 (0);
786        if (it2_size > 0 && it2e_size > 0)
787            diff2 = it2.index2 () - it2e.index2 ();
788        if (diff2 != 0) {
789            difference_type size2 = (std::min) (diff2, it2e_size);
790            if (size2 > 0) {
791                it2e += size2;
792                it2e_size -= size2;
793                diff2 -= size2;
794            }
795            size2 = (std::min) (- diff2, it2_size);
796            if (size2 > 0) {
797                it2_size -= size2;
798                if (!functor_type::computed) {
799                    while (-- size2 >= 0) { // zeroing
800#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
801                        typename M::iterator1 it1 (it2.begin ());
802                        typename M::iterator1 it1_end (it2.end ());
803#else
804                        typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
805                        typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
806#endif
807                        difference_type size1 (it1_end - it1);
808                        while (-- size1 >= 0)
809                            functor_type::apply (*it1, value_type/*zero*/()), ++ it1;
810                        ++ it2;
811                    }
812                } else {
813                    it2 += size2;
814                }
815                diff2 += size2;
816            }
817        }
818        difference_type size2 ((std::min) (it2_size, it2e_size));
819        it2_size -= size2;
820        it2e_size -= size2;
821        while (-- size2 >= 0) {
822#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
823            typename M::iterator1 it1 (it2.begin ());
824            typename M::iterator1 it1_end (it2.end ());
825            typename E::const_iterator1 it1e (it2e.begin ());
826            typename E::const_iterator1 it1e_end (it2e.end ());
827#else
828            typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
829            typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
830            typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
831            typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
832#endif
833            difference_type it1_size (it1_end - it1);
834            difference_type it1e_size (it1e_end - it1e);
835            difference_type diff1 (0);
836            if (it1_size > 0 && it1e_size > 0) {
837                diff1 = it1.index1 () - it1e.index1 ();
838                difference_type size1 = (std::min) (diff1, it1e_size);
839                if (size1 > 0) {
840                    it1e += size1;
841                    it1e_size -= size1;
842                    diff1 -= size1;
843                }
844                size1 = (std::min) (- diff1, it1_size);
845                if (size1 > 0) {
846                    it1_size -= size1;
847                    if (!functor_type::computed) {
848                        while (-- size1 >= 0)   // zeroing
849                            functor_type::apply (*it1, value_type/*zero*/()), ++ it1;
850                    } else {
851                        it1 += size1;
852                    }
853                    diff1 += size1;
854                }
855            }
856            difference_type size1 ((std::min) (it1_size, it1e_size));
857            it1_size -= size1;
858            it1e_size -= size1;
859            while (-- size1 >= 0)
860                functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
861            size1 = it1_size;
862            if (!functor_type::computed) {
863                while (-- size1 >= 0)   // zeroing
864                    functor_type::apply (*it1, value_type/*zero*/()), ++ it1;
865            } else {
866                it1 += size1;
867            }
868            ++ it2, ++ it2e;
869        }
870        size2 = it2_size;
871        if (!functor_type::computed) {
872            while (-- size2 >= 0) { // zeroing
873#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
874                typename M::iterator1 it1 (it2.begin ());
875                typename M::iterator1 it1_end (it2.end ());
876#else
877                typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
878                typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
879#endif
880                difference_type size1 (it1_end - it1);
881                while (-- size1 >= 0)
882                    functor_type::apply (*it1, value_type/*zero*/()), ++ it1;
883                ++ it2;
884            }
885        } else {
886            it2 += size2;
887        }
888#if BOOST_UBLAS_TYPE_CHECK
889        if (! disable_type_check<bool>::value)
890            BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
891#endif
892    }
893    // Sparse row major case
894    template<template <class T1, class T2> class F, class R, class M, class E>
895    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
896    void matrix_assign (M &m, const matrix_expression<E> &e, sparse_tag, row_major_tag) {
897        typedef F<typename M::iterator2::reference, typename E::value_type> functor_type;
898        // R unnecessary, make_conformant not required
899        BOOST_STATIC_ASSERT ((!functor_type::computed));
900        BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
901        BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
902        typedef typename M::value_type value_type;
903        // Sparse type has no numeric constraints to check
904
905        m.clear ();
906        typename E::const_iterator1 it1e (e ().begin1 ());
907        typename E::const_iterator1 it1e_end (e ().end1 ());
908        while (it1e != it1e_end) {
909#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
910            typename E::const_iterator2 it2e (it1e.begin ());
911            typename E::const_iterator2 it2e_end (it1e.end ());
912#else
913            typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
914            typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
915#endif
916            while (it2e != it2e_end) {
917                value_type t (*it2e);
918                if (t != value_type/*zero*/())
919                    m.insert_element (it2e.index1 (), it2e.index2 (), t);
920                ++ it2e;
921            }
922            ++ it1e;
923        }
924    }
925    // Sparse column major case
926    template<template <class T1, class T2> class F, class R, class M, class E>
927    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
928    void matrix_assign (M &m, const matrix_expression<E> &e, sparse_tag, column_major_tag) {
929        typedef F<typename M::iterator1::reference, typename E::value_type> functor_type;
930        // R unnecessary, make_conformant not required
931        BOOST_STATIC_ASSERT ((!functor_type::computed));
932        BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
933        BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
934        typedef typename M::value_type value_type;
935        // Sparse type has no numeric constraints to check
936
937        m.clear ();
938        typename E::const_iterator2 it2e (e ().begin2 ());
939        typename E::const_iterator2 it2e_end (e ().end2 ());
940        while (it2e != it2e_end) {
941#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
942            typename E::const_iterator1 it1e (it2e.begin ());
943            typename E::const_iterator1 it1e_end (it2e.end ());
944#else
945            typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
946            typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
947#endif
948            while (it1e != it1e_end) {
949                value_type t (*it1e);
950                if (t != value_type/*zero*/())
951                    m.insert_element (it1e.index1 (), it1e.index2 (), t);
952                ++ it1e;
953            }
954            ++ it2e;
955        }
956    }
957    // Sparse proxy or functional row major case
958    template<template <class T1, class T2> class F, class R, class M, class E>
959    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
960    void matrix_assign (M &m, const matrix_expression<E> &e, sparse_proxy_tag, row_major_tag) {
961        typedef F<typename M::iterator2::reference, typename E::value_type> functor_type;
962        typedef R conformant_restrict_type;
963        typedef typename M::size_type size_type;
964        typedef typename M::difference_type difference_type;
965        typedef typename M::value_type value_type;
966        BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
967        BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
968#if BOOST_UBLAS_TYPE_CHECK
969        matrix<value_type, row_major> cm (m.size1 (), m.size2 ());
970        indexing_matrix_assign<scalar_assign> (cm, m, row_major_tag ());
971        indexing_matrix_assign<F> (cm, e, row_major_tag ());
972#endif
973        detail::make_conformant (m, e, row_major_tag (), conformant_restrict_type ());
974
975        typename M::iterator1 it1 (m.begin1 ());
976        typename M::iterator1 it1_end (m.end1 ());
977        typename E::const_iterator1 it1e (e ().begin1 ());
978        typename E::const_iterator1 it1e_end (e ().end1 ());
979        while (it1 != it1_end && it1e != it1e_end) {
980            difference_type compare = it1.index1 () - it1e.index1 ();
981            if (compare == 0) {
982#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
983                typename M::iterator2 it2 (it1.begin ());
984                typename M::iterator2 it2_end (it1.end ());
985                typename E::const_iterator2 it2e (it1e.begin ());
986                typename E::const_iterator2 it2e_end (it1e.end ());
987#else
988                typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
989                typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
990                typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
991                typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
992#endif
993                if (it2 != it2_end && it2e != it2e_end) {
994                    size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
995                    while (true) {
996                        difference_type compare = it2_index - it2e_index;
997                        if (compare == 0) {
998                            functor_type::apply (*it2, *it2e);
999                            ++ it2, ++ it2e;
1000                            if (it2 != it2_end && it2e != it2e_end) {
1001                                it2_index = it2.index2 ();
1002                                it2e_index = it2e.index2 ();
1003                            } else
1004                                break;
1005                        } else if (compare < 0) {
1006                            if (!functor_type::computed) {
1007                                functor_type::apply (*it2, value_type/*zero*/());
1008                                ++ it2;
1009                            } else
1010                                increment (it2, it2_end, - compare);
1011                            if (it2 != it2_end)
1012                                it2_index = it2.index2 ();
1013                            else
1014                                break;
1015                        } else if (compare > 0) {
1016                            increment (it2e, it2e_end, compare);
1017                            if (it2e != it2e_end)
1018                                it2e_index = it2e.index2 ();
1019                            else
1020                                break;
1021                        }
1022                    }
1023                }
1024                if (!functor_type::computed) {
1025                    while (it2 != it2_end) {    // zeroing
1026                        functor_type::apply (*it2, value_type/*zero*/());
1027                        ++ it2;
1028                    }
1029                } else {
1030                    it2 = it2_end;
1031                }
1032                ++ it1, ++ it1e;
1033            } else if (compare < 0) {
1034                if (!functor_type::computed) {
1035#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1036                    typename M::iterator2 it2 (it1.begin ());
1037                    typename M::iterator2 it2_end (it1.end ());
1038#else
1039                    typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1040                    typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1041#endif
1042                    while (it2 != it2_end) {    // zeroing
1043                        functor_type::apply (*it2, value_type/*zero*/());
1044                        ++ it2;
1045                    }
1046                    ++ it1;
1047                } else {
1048                    increment (it1, it1_end, - compare);
1049                }
1050            } else if (compare > 0) {
1051                increment (it1e, it1e_end, compare);
1052            }
1053        }
1054        if (!functor_type::computed) {
1055            while (it1 != it1_end) {
1056#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1057                typename M::iterator2 it2 (it1.begin ());
1058                typename M::iterator2 it2_end (it1.end ());
1059#else
1060                typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1061                typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1062#endif
1063                while (it2 != it2_end) {    // zeroing
1064                    functor_type::apply (*it2, value_type/*zero*/());
1065                    ++ it2;
1066                }
1067                ++ it1;
1068            }
1069        } else {
1070            it1 = it1_end;
1071        }
1072#if BOOST_UBLAS_TYPE_CHECK
1073        if (! disable_type_check<bool>::value)
1074            BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
1075#endif
1076    }
1077    // Sparse proxy or functional column major case
1078    template<template <class T1, class T2> class F, class R, class M, class E>
1079    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1080    void matrix_assign (M &m, const matrix_expression<E> &e, sparse_proxy_tag, column_major_tag) {
1081        typedef F<typename M::iterator1::reference, typename E::value_type> functor_type;
1082        typedef R conformant_restrict_type;
1083        typedef typename M::size_type size_type;
1084        typedef typename M::difference_type difference_type;
1085        typedef typename M::value_type value_type;
1086        BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1087        BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1088#if BOOST_UBLAS_TYPE_CHECK
1089        matrix<value_type, column_major> cm (m.size1 (), m.size2 ());
1090        indexing_matrix_assign<scalar_assign> (cm, m, column_major_tag ());
1091        indexing_matrix_assign<F> (cm, e, column_major_tag ());
1092#endif
1093        detail::make_conformant (m, e, column_major_tag (), conformant_restrict_type ());
1094
1095        typename M::iterator2 it2 (m.begin2 ());
1096        typename M::iterator2 it2_end (m.end2 ());
1097        typename E::const_iterator2 it2e (e ().begin2 ());
1098        typename E::const_iterator2 it2e_end (e ().end2 ());
1099        while (it2 != it2_end && it2e != it2e_end) {
1100            difference_type compare = it2.index2 () - it2e.index2 ();
1101            if (compare == 0) {
1102#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1103                typename M::iterator1 it1 (it2.begin ());
1104                typename M::iterator1 it1_end (it2.end ());
1105                typename E::const_iterator1 it1e (it2e.begin ());
1106                typename E::const_iterator1 it1e_end (it2e.end ());
1107#else
1108                typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1109                typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1110                typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
1111                typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
1112#endif
1113                if (it1 != it1_end && it1e != it1e_end) {
1114                    size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
1115                    while (true) {
1116                        difference_type compare = it1_index - it1e_index;
1117                        if (compare == 0) {
1118                            functor_type::apply (*it1, *it1e);
1119                            ++ it1, ++ it1e;
1120                            if (it1 != it1_end && it1e != it1e_end) {
1121                                it1_index = it1.index1 ();
1122                                it1e_index = it1e.index1 ();
1123                            } else
1124                                break;
1125                        } else if (compare < 0) {
1126                            if (!functor_type::computed) {
1127                                functor_type::apply (*it1, value_type/*zero*/()); // zeroing
1128                                ++ it1;
1129                            } else
1130                                increment (it1, it1_end, - compare);
1131                            if (it1 != it1_end)
1132                                it1_index = it1.index1 ();
1133                            else
1134                                break;
1135                        } else if (compare > 0) {
1136                            increment (it1e, it1e_end, compare);
1137                            if (it1e != it1e_end)
1138                                it1e_index = it1e.index1 ();
1139                            else
1140                                break;
1141                        }
1142                    }
1143                }
1144                if (!functor_type::computed) {
1145                    while (it1 != it1_end) {    // zeroing
1146                        functor_type::apply (*it1, value_type/*zero*/());
1147                        ++ it1;
1148                    }
1149                } else {
1150                    it1 = it1_end;
1151                }
1152                ++ it2, ++ it2e;
1153            } else if (compare < 0) {
1154                if (!functor_type::computed) {
1155#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1156                    typename M::iterator1 it1 (it2.begin ());
1157                    typename M::iterator1 it1_end (it2.end ());
1158#else
1159                    typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1160                    typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1161#endif
1162                    while (it1 != it1_end) {    // zeroing
1163                        functor_type::apply (*it1, value_type/*zero*/());
1164                        ++ it1;
1165                    }
1166                    ++ it2;
1167                } else {
1168                    increment (it2, it2_end, - compare);
1169                }
1170            } else if (compare > 0) {
1171                increment (it2e, it2e_end, compare);
1172            }
1173        }
1174        if (!functor_type::computed) {
1175            while (it2 != it2_end) {
1176#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1177                typename M::iterator1 it1 (it2.begin ());
1178                typename M::iterator1 it1_end (it2.end ());
1179#else
1180                typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1181                typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1182#endif
1183                while (it1 != it1_end) {    // zeroing
1184                    functor_type::apply (*it1, value_type/*zero*/());
1185                    ++ it1;
1186                }
1187                ++ it2;
1188            }
1189        } else {
1190            it2 = it2_end;
1191        }
1192#if BOOST_UBLAS_TYPE_CHECK
1193        if (! disable_type_check<bool>::value)
1194            BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
1195#endif
1196    }
1197
1198    // Dispatcher
1199    template<template <class T1, class T2> class F, class M, class E>
1200    BOOST_UBLAS_INLINE
1201    void matrix_assign (M &m, const matrix_expression<E> &e) {
1202        typedef typename matrix_assign_traits<typename M::storage_category,
1203                                              F<typename M::reference, typename E::value_type>::computed,
1204                                              typename E::const_iterator1::iterator_category,
1205                                              typename E::const_iterator2::iterator_category>::storage_category storage_category;
1206        // give preference to matrix M's orientation if known
1207        typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1208                                          typename E::orientation_category ,
1209                                          typename M::orientation_category >::type orientation_category;
1210        typedef basic_full<typename M::size_type> unrestricted;
1211        matrix_assign<F, unrestricted> (m, e, storage_category (), orientation_category ());
1212    }
1213    template<template <class T1, class T2> class F, class R, class M, class E>
1214    BOOST_UBLAS_INLINE
1215    void matrix_assign (M &m, const matrix_expression<E> &e) {
1216        typedef R conformant_restrict_type;
1217        typedef typename matrix_assign_traits<typename M::storage_category,
1218                                              F<typename M::reference, typename E::value_type>::computed,
1219                                              typename E::const_iterator1::iterator_category,
1220                                              typename E::const_iterator2::iterator_category>::storage_category storage_category;
1221        // give preference to matrix M's orientation if known
1222        typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1223                                          typename E::orientation_category ,
1224                                          typename M::orientation_category >::type orientation_category;
1225        matrix_assign<F, conformant_restrict_type> (m, e, storage_category (), orientation_category ());
1226    }
1227
1228    template<class SC, class RI1, class RI2>
1229    struct matrix_swap_traits {
1230        typedef SC storage_category;
1231    };
1232
1233    template<>
1234    struct matrix_swap_traits<dense_proxy_tag, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
1235        typedef sparse_proxy_tag storage_category;
1236    };
1237
1238    template<>
1239    struct matrix_swap_traits<packed_proxy_tag, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
1240        typedef sparse_proxy_tag storage_category;
1241    };
1242
1243    // Dense (proxy) row major case
1244    template<template <class T1, class T2> class F, class R, class M, class E>
1245    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1246    void matrix_swap (M &m, matrix_expression<E> &e, dense_proxy_tag, row_major_tag) {
1247        typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
1248        // R unnecessary, make_conformant not required
1249        typedef typename M::size_type size_type;
1250        typedef typename M::difference_type difference_type;
1251        typename M::iterator1 it1 (m.begin1 ());
1252        typename E::iterator1 it1e (e ().begin1 ());
1253        difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type (e ().end1 () - it1e)));
1254        while (-- size1 >= 0) {
1255#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1256            typename M::iterator2 it2 (it1.begin ());
1257            typename E::iterator2 it2e (it1e.begin ());
1258            difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type (it1e.end () - it2e)));
1259#else
1260            typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1261            typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1262            difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type (end (it1e, iterator1_tag ()) - it2e)));
1263#endif
1264            while (-- size2 >= 0)
1265                functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
1266            ++ it1, ++ it1e;
1267        }
1268    }
1269    // Dense (proxy) column major case
1270    template<template <class T1, class T2> class F, class R, class M, class E>
1271    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1272    void matrix_swap (M &m, matrix_expression<E> &e, dense_proxy_tag, column_major_tag) {
1273        typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
1274        // R unnecessary, make_conformant not required
1275        typedef typename M::size_type size_type;
1276        typedef typename M::difference_type difference_type;
1277        typename M::iterator2 it2 (m.begin2 ());
1278        typename E::iterator2 it2e (e ().begin2 ());
1279        difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), size_type (e ().end2 () - it2e)));
1280        while (-- size2 >= 0) {
1281#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1282            typename M::iterator1 it1 (it2.begin ());
1283            typename E::iterator1 it1e (it2e.begin ());
1284            difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type (it2e.end () - it1e)));
1285#else
1286            typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1287            typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1288            difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), size_type (end (it2e, iterator2_tag ()) - it1e)));
1289#endif
1290            while (-- size1 >= 0)
1291                functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
1292            ++ it2, ++ it2e;
1293        }
1294    }
1295    // Packed (proxy) row major case
1296    template<template <class T1, class T2> class F, class R, class M, class E>
1297    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1298    void matrix_swap (M &m, matrix_expression<E> &e, packed_proxy_tag, row_major_tag) {
1299        typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
1300        // R unnecessary, make_conformant not required
1301        typedef typename M::size_type size_type;
1302        typedef typename M::difference_type difference_type;
1303        typename M::iterator1 it1 (m.begin1 ());
1304        typename E::iterator1 it1e (e ().begin1 ());
1305        difference_type size1 (BOOST_UBLAS_SAME (m.end1 () - it1, e ().end1 () - it1e));
1306        while (-- size1 >= 0) {
1307#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1308            typename M::iterator2 it2 (it1.begin ());
1309            typename E::iterator2 it2e (it1e.begin ());
1310            difference_type size2 (BOOST_UBLAS_SAME (it1.end () - it2, it1e.end () - it2e));
1311#else
1312            typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1313            typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1314            difference_type size2 (BOOST_UBLAS_SAME (end (it1, iterator1_tag ()) - it2, end (it1e, iterator1_tag ()) - it2e));
1315#endif
1316            while (-- size2 >= 0)
1317                functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
1318            ++ it1, ++ it1e;
1319        }
1320    }
1321    // Packed (proxy) column major case
1322    template<template <class T1, class T2> class F, class R, class M, class E>
1323    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1324    void matrix_swap (M &m, matrix_expression<E> &e, packed_proxy_tag, column_major_tag) {
1325        typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
1326        // R unnecessary, make_conformant not required
1327        typedef typename M::size_type size_type;
1328        typedef typename M::difference_type difference_type;
1329        typename M::iterator2 it2 (m.begin2 ());
1330        typename E::iterator2 it2e (e ().begin2 ());
1331        difference_type size2 (BOOST_UBLAS_SAME (m.end2 () - it2, e ().end2 () - it2e));
1332        while (-- size2 >= 0) {
1333#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1334            typename M::iterator1 it1 (it2.begin ());
1335            typename E::iterator1 it1e (it2e.begin ());
1336            difference_type size1 (BOOST_UBLAS_SAME (it2.end () - it1, it2e.end () - it1e));
1337#else
1338            typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1339            typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1340            difference_type size1 (BOOST_UBLAS_SAME (end (it2, iterator2_tag ()) - it1, end (it2e, iterator2_tag ()) - it1e));
1341#endif
1342            while (-- size1 >= 0)
1343                functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
1344            ++ it2, ++ it2e;
1345        }
1346    }
1347    // Sparse (proxy) row major case
1348    template<template <class T1, class T2> class F, class R, class M, class E>
1349    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1350    void matrix_swap (M &m, matrix_expression<E> &e, sparse_proxy_tag, row_major_tag) {
1351        typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
1352        typedef R conformant_restrict_type;
1353        typedef typename M::size_type size_type;
1354        typedef typename M::difference_type difference_type;
1355        typedef typename M::value_type value_type;
1356        BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1357        BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1358
1359        detail::make_conformant (m, e, row_major_tag (), conformant_restrict_type ());
1360        // FIXME should be a seperate restriction for E
1361        detail::make_conformant (e (), m, row_major_tag (), conformant_restrict_type ());
1362
1363        typename M::iterator1 it1 (m.begin1 ());
1364        typename M::iterator1 it1_end (m.end1 ());
1365        typename E::iterator1 it1e (e ().begin1 ());
1366        typename E::iterator1 it1e_end (e ().end1 ());
1367        while (it1 != it1_end && it1e != it1e_end) {
1368            difference_type compare = it1.index1 () - it1e.index1 ();
1369            if (compare == 0) {
1370#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1371                typename M::iterator2 it2 (it1.begin ());
1372                typename M::iterator2 it2_end (it1.end ());
1373                typename E::iterator2 it2e (it1e.begin ());
1374                typename E::iterator2 it2e_end (it1e.end ());
1375#else
1376                typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1377                typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1378                typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1379                typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
1380#endif
1381                if (it2 != it2_end && it2e != it2e_end) {
1382                    size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
1383                    while (true) {
1384                        difference_type compare = it2_index - it2e_index;
1385                        if (compare == 0) {
1386                            functor_type::apply (*it2, *it2e);
1387                            ++ it2, ++ it2e;
1388                            if (it2 != it2_end && it2e != it2e_end) {
1389                                it2_index = it2.index2 ();
1390                                it2e_index = it2e.index2 ();
1391                            } else
1392                                break;
1393                        } else if (compare < 0) {
1394                            increment (it2, it2_end, - compare);
1395                            if (it2 != it2_end)
1396                                it2_index = it2.index2 ();
1397                            else
1398                                break;
1399                        } else if (compare > 0) {
1400                            increment (it2e, it2e_end, compare);
1401                            if (it2e != it2e_end)
1402                                it2e_index = it2e.index2 ();
1403                            else
1404                                break;
1405                        }
1406                    }
1407                }
1408#if BOOST_UBLAS_TYPE_CHECK
1409                increment (it2e, it2e_end);
1410                increment (it2, it2_end);
1411#endif
1412                ++ it1, ++ it1e;
1413            } else if (compare < 0) {
1414#if BOOST_UBLAS_TYPE_CHECK
1415                while (it1.index1 () < it1e.index1 ()) {
1416#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1417                    typename M::iterator2 it2 (it1.begin ());
1418                    typename M::iterator2 it2_end (it1.end ());
1419#else
1420                    typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1421                    typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1422#endif
1423                    increment (it2, it2_end);
1424                    ++ it1;
1425                }
1426#else
1427                increment (it1, it1_end, - compare);
1428#endif
1429            } else if (compare > 0) {
1430#if BOOST_UBLAS_TYPE_CHECK
1431                while (it1e.index1 () < it1.index1 ()) {
1432#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1433                    typename E::iterator2 it2e (it1e.begin ());
1434                    typename E::iterator2 it2e_end (it1e.end ());
1435#else
1436                    typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1437                    typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
1438#endif
1439                    increment (it2e, it2e_end);
1440                    ++ it1e;
1441                }
1442#else
1443                increment (it1e, it1e_end, compare);
1444#endif
1445            }
1446        }
1447#if BOOST_UBLAS_TYPE_CHECK
1448        while (it1e != it1e_end) {
1449#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1450            typename E::iterator2 it2e (it1e.begin ());
1451            typename E::iterator2 it2e_end (it1e.end ());
1452#else
1453            typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1454            typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
1455#endif
1456            increment (it2e, it2e_end);
1457            ++ it1e;
1458        }
1459        while (it1 != it1_end) {
1460#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1461            typename M::iterator2 it2 (it1.begin ());
1462            typename M::iterator2 it2_end (it1.end ());
1463#else
1464            typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1465            typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1466#endif
1467            increment (it2, it2_end);
1468            ++ it1;
1469        }
1470#endif
1471    }
1472    // Sparse (proxy) column major case
1473    template<template <class T1, class T2> class F, class R, class M, class E>
1474    // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1475    void matrix_swap (M &m, matrix_expression<E> &e, sparse_proxy_tag, column_major_tag) {
1476        typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
1477        typedef R conformant_restrict_type;
1478        typedef typename M::size_type size_type;
1479        typedef typename M::difference_type difference_type;
1480        typedef typename M::value_type value_type;
1481        BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1482        BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1483
1484        detail::make_conformant (m, e, column_major_tag (), conformant_restrict_type ());
1485        // FIXME should be a seperate restriction for E
1486        detail::make_conformant (e (), m, column_major_tag (), conformant_restrict_type ());
1487
1488        typename M::iterator2 it2 (m.begin2 ());
1489        typename M::iterator2 it2_end (m.end2 ());
1490        typename E::iterator2 it2e (e ().begin2 ());
1491        typename E::iterator2 it2e_end (e ().end2 ());
1492        while (it2 != it2_end && it2e != it2e_end) {
1493            difference_type compare = it2.index2 () - it2e.index2 ();
1494            if (compare == 0) {
1495#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1496                typename M::iterator1 it1 (it2.begin ());
1497                typename M::iterator1 it1_end (it2.end ());
1498                typename E::iterator1 it1e (it2e.begin ());
1499                typename E::iterator1 it1e_end (it2e.end ());
1500#else
1501                typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1502                typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1503                typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1504                typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
1505#endif
1506                if (it1 != it1_end && it1e != it1e_end) {
1507                    size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
1508                    while (true) {
1509                        difference_type compare = it1_index - it1e_index;
1510                        if (compare == 0) {
1511                            functor_type::apply (*it1, *it1e);
1512                            ++ it1, ++ it1e;
1513                            if (it1 != it1_end && it1e != it1e_end) {
1514                                it1_index = it1.index1 ();
1515                                it1e_index = it1e.index1 ();
1516                            } else
1517                                break;
1518                        }  else if (compare < 0) {
1519                            increment (it1, it1_end, - compare);
1520                            if (it1 != it1_end)
1521                                it1_index = it1.index1 ();
1522                            else
1523                                break;
1524                        } else if (compare > 0) {
1525                            increment (it1e, it1e_end, compare);
1526                            if (it1e != it1e_end)
1527                                it1e_index = it1e.index1 ();
1528                            else
1529                                break;
1530                        }
1531                    }
1532                }
1533#if BOOST_UBLAS_TYPE_CHECK
1534                increment (it1e, it1e_end);
1535                increment (it1, it1_end);
1536#endif
1537                ++ it2, ++ it2e;
1538            } else if (compare < 0) {
1539#if BOOST_UBLAS_TYPE_CHECK
1540                while (it2.index2 () < it2e.index2 ()) {
1541#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1542                    typename M::iterator1 it1 (it2.begin ());
1543                    typename M::iterator1 it1_end (it2.end ());
1544#else
1545                    typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1546                    typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1547#endif
1548                    increment (it1, it1_end);
1549                    ++ it2;
1550                }
1551#else
1552                increment (it2, it2_end, - compare);
1553#endif
1554            } else if (compare > 0) {
1555#if BOOST_UBLAS_TYPE_CHECK
1556                while (it2e.index2 () < it2.index2 ()) {
1557#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1558                    typename E::iterator1 it1e (it2e.begin ());
1559                    typename E::iterator1 it1e_end (it2e.end ());
1560#else
1561                    typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1562                    typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
1563#endif
1564                    increment (it1e, it1e_end);
1565                    ++ it2e;
1566                }
1567#else
1568                increment (it2e, it2e_end, compare);
1569#endif
1570            }
1571        }
1572#if BOOST_UBLAS_TYPE_CHECK
1573        while (it2e != it2e_end) {
1574#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1575            typename E::iterator1 it1e (it2e.begin ());
1576            typename E::iterator1 it1e_end (it2e.end ());
1577#else
1578            typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1579            typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
1580#endif
1581            increment (it1e, it1e_end);
1582            ++ it2e;
1583        }
1584        while (it2 != it2_end) {
1585#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1586            typename M::iterator1 it1 (it2.begin ());
1587            typename M::iterator1 it1_end (it2.end ());
1588#else
1589            typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1590            typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1591#endif
1592            increment (it1, it1_end);
1593            ++ it2;
1594        }
1595#endif
1596    }
1597
1598    // Dispatcher
1599    template<template <class T1, class T2> class F, class M, class E>
1600    BOOST_UBLAS_INLINE
1601    void matrix_swap (M &m, matrix_expression<E> &e) {
1602        typedef typename matrix_swap_traits<typename M::storage_category,
1603                                            typename E::const_iterator1::iterator_category,
1604                                            typename E::const_iterator2::iterator_category>::storage_category storage_category;
1605        // give preference to matrix M's orientation if known
1606        typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1607                                          typename E::orientation_category ,
1608                                          typename M::orientation_category >::type orientation_category;
1609        typedef basic_full<typename M::size_type> unrestricted;
1610        matrix_swap<F, unrestricted> (m, e, storage_category (), orientation_category ());
1611    }
1612    template<template <class T1, class T2> class F, class R, class M, class E>
1613    BOOST_UBLAS_INLINE
1614    void matrix_swap (M &m, matrix_expression<E> &e) {
1615        typedef R conformant_restrict_type;
1616        typedef typename matrix_swap_traits<typename M::storage_category,
1617                                            typename E::const_iterator1::iterator_category,
1618                                            typename E::const_iterator2::iterator_category>::storage_category storage_category;
1619        // give preference to matrix M's orientation if known
1620        typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1621                                          typename E::orientation_category ,
1622                                          typename M::orientation_category >::type orientation_category;
1623        matrix_swap<F, conformant_restrict_type> (m, e, storage_category (), orientation_category ());
1624    }
1625
1626}}}
1627
1628#endif
Note: See TracBrowser for help on using the repository browser.