Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:58:46

0001 //
0002 //  Copyright (c) 2000-2002
0003 //  Joerg Walter, Mathias Koch
0004 //
0005 //  Distributed under the Boost Software License, Version 1.0. (See
0006 //  accompanying file LICENSE_1_0.txt or copy at
0007 //  http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 //  The authors gratefully acknowledge the support of
0010 //  GeNeSys mbH & Co. KG in producing this work.
0011 //
0012 
0013 #ifndef _BOOST_UBLAS_MATRIX_ASSIGN_
0014 #define _BOOST_UBLAS_MATRIX_ASSIGN_
0015 
0016 #include <boost/numeric/ublas/traits.hpp>
0017 // Required for make_conformant storage
0018 #include <vector>
0019 
0020 // Iterators based on ideas of Jeremy Siek
0021 
0022 namespace boost { namespace numeric { namespace ublas {
0023 namespace detail {
0024     
0025     // Weak equality check - useful to compare equality two arbitary matrix expression results.
0026     // Since the actual expressions are unknown, we check for and arbitary error bound
0027     // on the relative error.
0028     // For a linear expression the infinity norm makes sense as we do not know how the elements will be
0029     // combined in the expression. False positive results are inevitable for arbirary expressions!
0030     template<class E1, class E2, class S>
0031     BOOST_UBLAS_INLINE
0032     bool equals (const matrix_expression<E1> &e1, const matrix_expression<E2> &e2, S epsilon, S min_norm) {
0033         return norm_inf (e1 - e2) <= epsilon *
0034                std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);
0035     }
0036 
0037     template<class E1, class E2>
0038     BOOST_UBLAS_INLINE
0039     bool expression_type_check (const matrix_expression<E1> &e1, const matrix_expression<E2> &e2) {
0040         typedef typename type_traits<typename promote_traits<typename E1::value_type,
0041                                      typename E2::value_type>::promote_type>::real_type real_type;
0042         return equals (e1, e2, BOOST_UBLAS_TYPE_CHECK_EPSILON, BOOST_UBLAS_TYPE_CHECK_MIN);
0043     }
0044 
0045 
0046     template<class M, class E, class R>
0047     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0048     void make_conformant (M &m, const matrix_expression<E> &e, row_major_tag, R) {
0049         BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
0050         BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
0051         typedef R conformant_restrict_type;
0052         typedef typename M::size_type size_type;
0053         typedef typename M::difference_type difference_type;
0054         typedef typename M::value_type value_type;
0055         // FIXME unbounded_array with push_back maybe better
0056         std::vector<std::pair<size_type, size_type> > index;
0057         typename M::iterator1 it1 (m.begin1 ());
0058         typename M::iterator1 it1_end (m.end1 ());
0059         typename E::const_iterator1 it1e (e ().begin1 ());
0060         typename E::const_iterator1 it1e_end (e ().end1 ());
0061         while (it1 != it1_end && it1e != it1e_end) {
0062             difference_type compare = it1.index1 () - it1e.index1 ();
0063             if (compare == 0) {
0064 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0065                 typename M::iterator2 it2 (it1.begin ());
0066                 typename M::iterator2 it2_end (it1.end ());
0067                 typename E::const_iterator2 it2e (it1e.begin ());
0068                 typename E::const_iterator2 it2e_end (it1e.end ());
0069 #else
0070                 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
0071                 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
0072                 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
0073                 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
0074 #endif
0075                 if (it2 != it2_end && it2e != it2e_end) {
0076                     size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
0077                     for (;;) {
0078                         difference_type compare2 = it2_index - it2e_index;
0079                         if (compare2 == 0) {
0080                             ++ it2, ++ it2e;
0081                             if (it2 != it2_end && it2e != it2e_end) {
0082                                 it2_index = it2.index2 ();
0083                                 it2e_index = it2e.index2 ();
0084                             } else
0085                                 break;
0086                         } else if (compare2 < 0) {
0087                             increment (it2, it2_end, - compare2);
0088                             if (it2 != it2_end)
0089                                 it2_index = it2.index2 ();
0090                             else
0091                                 break;
0092                         } else if (compare2 > 0) {
0093                             if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
0094                                 if (static_cast<value_type>(*it2e) != value_type/*zero*/())
0095                                     index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
0096                             ++ it2e;
0097                             if (it2e != it2e_end)
0098                                 it2e_index = it2e.index2 ();
0099                             else
0100                                 break;
0101                         }
0102                     }
0103                 }
0104                 while (it2e != it2e_end) {
0105                     if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
0106                         if (static_cast<value_type>(*it2e) != value_type/*zero*/())
0107                             index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
0108                     ++ it2e;
0109                 }
0110                 ++ it1, ++ it1e;
0111             } else if (compare < 0) {
0112                 increment (it1, it1_end, - compare);
0113             } else if (compare > 0) {
0114 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0115                 typename E::const_iterator2 it2e (it1e.begin ());
0116                 typename E::const_iterator2 it2e_end (it1e.end ());
0117 #else
0118                 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
0119                 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
0120 #endif
0121                 while (it2e != it2e_end) {
0122                     if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
0123                         if (static_cast<value_type>(*it2e) != value_type/*zero*/())
0124                             index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
0125                     ++ it2e;
0126                 }
0127                 ++ it1e;
0128             }
0129         }
0130         while (it1e != it1e_end) {
0131 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0132             typename E::const_iterator2 it2e (it1e.begin ());
0133             typename E::const_iterator2 it2e_end (it1e.end ());
0134 #else
0135             typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
0136             typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
0137 #endif
0138             while (it2e != it2e_end) {
0139                 if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
0140                     if (static_cast<value_type>(*it2e) != value_type/*zero*/())
0141                         index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
0142                 ++ it2e;
0143             }
0144             ++ it1e;
0145         }
0146         // ISSUE proxies require insert_element
0147         for (size_type k = 0; k < index.size (); ++ k)
0148             m (index [k].first, index [k].second) = value_type/*zero*/();
0149     }
0150     template<class M, class E, class R>
0151     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0152     void make_conformant (M &m, const matrix_expression<E> &e, column_major_tag, R) {
0153         BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
0154         BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
0155         typedef R conformant_restrict_type;
0156         typedef typename M::size_type size_type;
0157         typedef typename M::difference_type difference_type;
0158         typedef typename M::value_type value_type;
0159         std::vector<std::pair<size_type, size_type> > index;
0160         typename M::iterator2 it2 (m.begin2 ());
0161         typename M::iterator2 it2_end (m.end2 ());
0162         typename E::const_iterator2 it2e (e ().begin2 ());
0163         typename E::const_iterator2 it2e_end (e ().end2 ());
0164         while (it2 != it2_end && it2e != it2e_end) {
0165             difference_type compare = it2.index2 () - it2e.index2 ();
0166             if (compare == 0) {
0167 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0168                 typename M::iterator1 it1 (it2.begin ());
0169                 typename M::iterator1 it1_end (it2.end ());
0170                 typename E::const_iterator1 it1e (it2e.begin ());
0171                 typename E::const_iterator1 it1e_end (it2e.end ());
0172 #else
0173                 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
0174                 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
0175                 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
0176                 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
0177 #endif
0178                 if (it1 != it1_end && it1e != it1e_end) {
0179                     size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
0180                     for (;;) {
0181                         difference_type compare2 = it1_index - it1e_index;
0182                         if (compare2 == 0) {
0183                             ++ it1, ++ it1e;
0184                             if (it1 != it1_end && it1e != it1e_end) {
0185                                 it1_index = it1.index1 ();
0186                                 it1e_index = it1e.index1 ();
0187                             } else
0188                                 break;
0189                         } else if (compare2 < 0) {
0190                             increment (it1, it1_end, - compare2);
0191                             if (it1 != it1_end)
0192                                 it1_index = it1.index1 ();
0193                             else
0194                                 break;
0195                         } else if (compare2 > 0) {
0196                             if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
0197                                 if (static_cast<value_type>(*it1e) != value_type/*zero*/())
0198                                     index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
0199                             ++ it1e;
0200                             if (it1e != it1e_end)
0201                                 it1e_index = it1e.index1 ();
0202                             else
0203                                 break;
0204                         }
0205                     }
0206                 }
0207                 while (it1e != it1e_end) {
0208                     if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
0209                         if (static_cast<value_type>(*it1e) != value_type/*zero*/())
0210                             index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
0211                     ++ it1e;
0212                 }
0213                 ++ it2, ++ it2e;
0214             } else if (compare < 0) {
0215                 increment (it2, it2_end, - compare);
0216             } else if (compare > 0) {
0217 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0218                 typename E::const_iterator1 it1e (it2e.begin ());
0219                 typename E::const_iterator1 it1e_end (it2e.end ());
0220 #else
0221                 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
0222                 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
0223 #endif
0224                 while (it1e != it1e_end) {
0225                     if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
0226                         if (static_cast<value_type>(*it1e) != value_type/*zero*/())
0227                             index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
0228                     ++ it1e;
0229                 }
0230                 ++ it2e;
0231             }
0232         }
0233         while (it2e != it2e_end) {
0234 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0235             typename E::const_iterator1 it1e (it2e.begin ());
0236             typename E::const_iterator1 it1e_end (it2e.end ());
0237 #else
0238             typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
0239             typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
0240 #endif
0241             while (it1e != it1e_end) {
0242                 if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
0243                     if (static_cast<value_type>(*it1e) != value_type/*zero*/())
0244                         index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
0245                 ++ it1e;
0246             }
0247             ++ it2e;
0248         }
0249         // ISSUE proxies require insert_element
0250         for (size_type k = 0; k < index.size (); ++ k)
0251             m (index [k].first, index [k].second) = value_type/*zero*/();
0252     }
0253 
0254 }//namespace detail
0255 
0256 
0257     // Explicitly iterating row major
0258     template<template <class T1, class T2> class F, class M, class T>
0259     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0260     void iterating_matrix_assign_scalar (M &m, const T &t, row_major_tag) {
0261         typedef F<typename M::iterator2::reference, T> functor_type;
0262         typedef typename M::difference_type difference_type;
0263         difference_type size1 (m.size1 ());
0264         difference_type size2 (m.size2 ());
0265         typename M::iterator1 it1 (m.begin1 ());
0266         BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ());
0267         while (-- size1 >= 0) {
0268 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0269             typename M::iterator2 it2 (it1.begin ());
0270 #else
0271             typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
0272 #endif
0273             BOOST_UBLAS_CHECK (it1.end () - it2 == size2, bad_size ());
0274             difference_type temp_size2 (size2);
0275 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0276             while (-- temp_size2 >= 0)
0277                 functor_type::apply (*it2, t), ++ it2;
0278 #else
0279             DD (temp_size2, 4, r, (functor_type::apply (*it2, t), ++ it2));
0280 #endif
0281             ++ it1;
0282         }
0283     }
0284     // Explicitly iterating column major
0285     template<template <class T1, class T2> class F, class M, class T>
0286     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0287     void iterating_matrix_assign_scalar (M &m, const T &t, column_major_tag) {
0288         typedef F<typename M::iterator1::reference, T> functor_type;
0289         typedef typename M::difference_type difference_type;
0290         difference_type size2 (m.size2 ());
0291         difference_type size1 (m.size1 ());
0292         typename M::iterator2 it2 (m.begin2 ());
0293         BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ());
0294         while (-- size2 >= 0) {
0295 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0296             typename M::iterator1 it1 (it2.begin ());
0297 #else
0298             typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
0299 #endif
0300             BOOST_UBLAS_CHECK (it2.end () - it1 == size1, bad_size ());
0301             difference_type temp_size1 (size1);
0302 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0303             while (-- temp_size1 >= 0)
0304                 functor_type::apply (*it1, t), ++ it1;
0305 #else
0306             DD (temp_size1, 4, r, (functor_type::apply (*it1, t), ++ it1));
0307 #endif
0308             ++ it2;
0309         }
0310     }
0311     // Explicitly indexing row major
0312     template<template <class T1, class T2> class F, class M, class T>
0313     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0314     void indexing_matrix_assign_scalar (M &m, const T &t, row_major_tag) {
0315         typedef F<typename M::reference, T> functor_type;
0316         typedef typename M::size_type size_type;
0317         size_type size1 (m.size1 ());
0318         size_type size2 (m.size2 ());
0319         for (size_type i = 0; i < size1; ++ i) {
0320 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0321             for (size_type j = 0; j < size2; ++ j)
0322                 functor_type::apply (m (i, j), t);
0323 #else
0324             size_type j (0);
0325             DD (size2, 4, r, (functor_type::apply (m (i, j), t), ++ j));
0326 #endif
0327         }
0328     }
0329     // Explicitly indexing column major
0330     template<template <class T1, class T2> class F, class M, class T>
0331     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0332     void indexing_matrix_assign_scalar (M &m, const T &t, column_major_tag) {
0333         typedef F<typename M::reference, T> functor_type;
0334         typedef typename M::size_type size_type;
0335         size_type size2 (m.size2 ());
0336         size_type size1 (m.size1 ());
0337         for (size_type j = 0; j < size2; ++ j) {
0338 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0339             for (size_type i = 0; i < size1; ++ i)
0340                 functor_type::apply (m (i, j), t);
0341 #else
0342             size_type i (0);
0343             DD (size1, 4, r, (functor_type::apply (m (i, j), t), ++ i));
0344 #endif
0345         }
0346     }
0347 
0348     // Dense (proxy) case
0349     template<template <class T1, class T2> class F, class M, class T, class C>
0350     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0351     void matrix_assign_scalar (M &m, const T &t, dense_proxy_tag, C) {
0352         typedef C orientation_category;
0353 #ifdef BOOST_UBLAS_USE_INDEXING
0354         indexing_matrix_assign_scalar<F> (m, t, orientation_category ());
0355 #elif BOOST_UBLAS_USE_ITERATING
0356         iterating_matrix_assign_scalar<F> (m, t, orientation_category ());
0357 #else
0358         typedef typename M::size_type size_type;
0359         size_type size1 (m.size1 ());
0360         size_type size2 (m.size2 ());
0361         if (size1 >= BOOST_UBLAS_ITERATOR_THRESHOLD &&
0362             size2 >= BOOST_UBLAS_ITERATOR_THRESHOLD)
0363             iterating_matrix_assign_scalar<F> (m, t, orientation_category ());
0364         else
0365             indexing_matrix_assign_scalar<F> (m, t, orientation_category ());
0366 #endif
0367     }
0368     // Packed (proxy) row major case
0369     template<template <class T1, class T2> class F, class M, class T>
0370     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0371     void matrix_assign_scalar (M &m, const T &t, packed_proxy_tag, row_major_tag) {
0372         typedef F<typename M::iterator2::reference, T> functor_type;
0373         typedef typename M::difference_type difference_type;
0374         typename M::iterator1 it1 (m.begin1 ());
0375         difference_type size1 (m.end1 () - it1);
0376         while (-- size1 >= 0) {
0377 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0378             typename M::iterator2 it2 (it1.begin ());
0379             difference_type size2 (it1.end () - it2);
0380 #else
0381             typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
0382             difference_type size2 (end (it1, iterator1_tag ()) - it2);
0383 #endif
0384             while (-- size2 >= 0)
0385                 functor_type::apply (*it2, t), ++ it2;
0386             ++ it1;
0387         }
0388     }
0389     // Packed (proxy) column major case
0390     template<template <class T1, class T2> class F, class M, class T>
0391     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0392     void matrix_assign_scalar (M &m, const T &t, packed_proxy_tag, column_major_tag) {
0393         typedef F<typename M::iterator1::reference, T> functor_type;
0394         typedef typename M::difference_type difference_type;
0395         typename M::iterator2 it2 (m.begin2 ());
0396         difference_type size2 (m.end2 () - it2);
0397         while (-- size2 >= 0) {
0398 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0399             typename M::iterator1 it1 (it2.begin ());
0400             difference_type size1 (it2.end () - it1);
0401 #else
0402             typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
0403             difference_type size1 (end (it2, iterator2_tag ()) - it1);
0404 #endif
0405             while (-- size1 >= 0)
0406                 functor_type::apply (*it1, t), ++ it1;
0407             ++ it2;
0408         }
0409     }
0410     // Sparse (proxy) row major case
0411     template<template <class T1, class T2> class F, class M, class T>
0412     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0413     void matrix_assign_scalar (M &m, const T &t, sparse_proxy_tag, row_major_tag) {
0414         typedef F<typename M::iterator2::reference, T> functor_type;
0415         typename M::iterator1 it1 (m.begin1 ());
0416         typename M::iterator1 it1_end (m.end1 ());
0417         while (it1 != it1_end) {
0418 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0419             typename M::iterator2 it2 (it1.begin ());
0420             typename M::iterator2 it2_end (it1.end ());
0421 #else
0422             typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
0423             typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
0424 #endif
0425             while (it2 != it2_end)
0426                 functor_type::apply (*it2, t), ++ it2;
0427             ++ it1;
0428         }
0429     }
0430     // Sparse (proxy) column major case
0431     template<template <class T1, class T2> class F, class M, class T>
0432     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0433     void matrix_assign_scalar (M &m, const T &t, sparse_proxy_tag, column_major_tag) {
0434         typedef F<typename M::iterator1::reference, T> functor_type;
0435         typename M::iterator2 it2 (m.begin2 ());
0436         typename M::iterator2 it2_end (m.end2 ());
0437         while (it2 != it2_end) {
0438 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0439             typename M::iterator1 it1 (it2.begin ());
0440             typename M::iterator1 it1_end (it2.end ());
0441 #else
0442             typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
0443             typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
0444 #endif
0445             while (it1 != it1_end)
0446                 functor_type::apply (*it1, t), ++ it1;
0447             ++ it2;
0448         }
0449     }
0450 
0451     // Dispatcher
0452     template<template <class T1, class T2> class F, class M, class T>
0453     BOOST_UBLAS_INLINE
0454     void matrix_assign_scalar (M &m, const T &t) {
0455         typedef typename M::storage_category storage_category;
0456         typedef typename M::orientation_category orientation_category;
0457         matrix_assign_scalar<F> (m, t, storage_category (), orientation_category ());
0458     }
0459 
0460     template<class SC, bool COMPUTED, class RI1, class RI2>
0461     struct matrix_assign_traits {
0462         typedef SC storage_category;
0463     };
0464 
0465     template<bool COMPUTED>
0466     struct matrix_assign_traits<dense_tag, COMPUTED, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
0467         typedef packed_tag storage_category;
0468     };
0469     template<>
0470     struct matrix_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
0471         typedef sparse_tag storage_category;
0472     };
0473     template<>
0474     struct matrix_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
0475         typedef sparse_proxy_tag storage_category;
0476     };
0477 
0478     template<bool COMPUTED>
0479     struct matrix_assign_traits<dense_proxy_tag, COMPUTED, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
0480         typedef packed_proxy_tag storage_category;
0481     };
0482     template<bool COMPUTED>
0483     struct matrix_assign_traits<dense_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
0484         typedef sparse_proxy_tag storage_category;
0485     };
0486 
0487     template<>
0488     struct matrix_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
0489         typedef sparse_tag storage_category;
0490     };
0491     template<>
0492     struct matrix_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
0493         typedef sparse_proxy_tag storage_category;
0494     };
0495 
0496     template<bool COMPUTED>
0497     struct matrix_assign_traits<packed_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
0498         typedef sparse_proxy_tag storage_category;
0499     };
0500 
0501     template<>
0502     struct matrix_assign_traits<sparse_tag, true, dense_random_access_iterator_tag, dense_random_access_iterator_tag> {
0503         typedef sparse_proxy_tag storage_category;
0504     };
0505     template<>
0506     struct matrix_assign_traits<sparse_tag, true, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
0507         typedef sparse_proxy_tag storage_category;
0508     };
0509     template<>
0510     struct matrix_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
0511         typedef sparse_proxy_tag storage_category;
0512     };
0513 
0514     // Explicitly iterating row major
0515     template<template <class T1, class T2> class F, class M, class E>
0516     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0517     void iterating_matrix_assign (M &m, const matrix_expression<E> &e, row_major_tag) {
0518         typedef F<typename M::iterator2::reference, typename E::value_type> functor_type;
0519         typedef typename M::difference_type difference_type;
0520         difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
0521         difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
0522         typename M::iterator1 it1 (m.begin1 ());
0523         BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ());
0524         typename E::const_iterator1 it1e (e ().begin1 ());
0525         BOOST_UBLAS_CHECK (size2 == 0 || e ().end1 () - it1e == size1, bad_size ());
0526         while (-- size1 >= 0) {
0527 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0528             typename M::iterator2 it2 (it1.begin ());
0529             typename E::const_iterator2 it2e (it1e.begin ());
0530 #else
0531             typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
0532             typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
0533 #endif
0534             BOOST_UBLAS_CHECK (it1.end () - it2 == size2, bad_size ());
0535             BOOST_UBLAS_CHECK (it1e.end () - it2e == size2, bad_size ());
0536             difference_type temp_size2 (size2);
0537 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0538             while (-- temp_size2 >= 0)
0539                 functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
0540 #else
0541             DD (temp_size2, 2, r, (functor_type::apply (*it2, *it2e), ++ it2, ++ it2e));
0542 #endif
0543             ++ it1, ++ it1e;
0544         }
0545     }
0546     // Explicitly iterating column major
0547     template<template <class T1, class T2> class F, class M, class E>
0548     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0549     void iterating_matrix_assign (M &m, const matrix_expression<E> &e, column_major_tag) {
0550         typedef F<typename M::iterator1::reference, typename E::value_type> functor_type;
0551         typedef typename M::difference_type difference_type;
0552         difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
0553         difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
0554         typename M::iterator2 it2 (m.begin2 ());
0555         BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ());
0556         typename E::const_iterator2 it2e (e ().begin2 ());
0557         BOOST_UBLAS_CHECK (size1 == 0 || e ().end2 () - it2e == size2, bad_size ());
0558         while (-- size2 >= 0) {
0559 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0560             typename M::iterator1 it1 (it2.begin ());
0561             typename E::const_iterator1 it1e (it2e.begin ());
0562 #else
0563             typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
0564             typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
0565 #endif
0566             BOOST_UBLAS_CHECK (it2.end () - it1 == size1, bad_size ());
0567             BOOST_UBLAS_CHECK (it2e.end () - it1e == size1, bad_size ());
0568             difference_type temp_size1 (size1);
0569 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0570             while (-- temp_size1 >= 0)
0571                 functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
0572 #else
0573             DD (temp_size1, 2, r, (functor_type::apply (*it1, *it1e), ++ it1, ++ it1e));
0574 #endif
0575             ++ it2, ++ it2e;
0576         }
0577     }
0578     // Explicitly indexing row major
0579     template<template <class T1, class T2> class F, class M, class E>
0580     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0581     void indexing_matrix_assign (M &m, const matrix_expression<E> &e, row_major_tag) {
0582         typedef F<typename M::reference, typename E::value_type> functor_type;
0583         typedef typename M::size_type size_type;
0584         size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
0585         size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
0586         for (size_type i = 0; i < size1; ++ i) {
0587 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0588             for (size_type j = 0; j < size2; ++ j)
0589                 functor_type::apply (m (i, j), e () (i, j));
0590 #else
0591             size_type j (0);
0592             DD (size2, 2, r, (functor_type::apply (m (i, j), e () (i, j)), ++ j));
0593 #endif
0594         }
0595     }
0596     // Explicitly indexing column major
0597     template<template <class T1, class T2> class F, class M, class E>
0598     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0599     void indexing_matrix_assign (M &m, const matrix_expression<E> &e, column_major_tag) {
0600         typedef F<typename M::reference, typename E::value_type> functor_type;
0601         typedef typename M::size_type size_type;
0602         size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
0603         size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
0604         for (size_type j = 0; j < size2; ++ j) {
0605 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0606             for (size_type i = 0; i < size1; ++ i)
0607                 functor_type::apply (m (i, j), e () (i, j));
0608 #else
0609             size_type i (0);
0610             DD (size1, 2, r, (functor_type::apply (m (i, j), e () (i, j)), ++ i));
0611 #endif
0612         }
0613     }
0614 
0615     // Dense (proxy) case
0616     template<template <class T1, class T2> class F, class R, class M, class E, class C>
0617     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0618     void matrix_assign (M &m, const matrix_expression<E> &e, dense_proxy_tag, C) {
0619         // R unnecessary, make_conformant not required
0620         typedef C orientation_category;
0621 #ifdef BOOST_UBLAS_USE_INDEXING
0622         indexing_matrix_assign<F> (m, e, orientation_category ());
0623 #elif BOOST_UBLAS_USE_ITERATING
0624         iterating_matrix_assign<F> (m, e, orientation_category ());
0625 #else
0626         typedef typename M::difference_type difference_type;
0627         size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
0628         size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
0629         if (size1 >= BOOST_UBLAS_ITERATOR_THRESHOLD &&
0630             size2 >= BOOST_UBLAS_ITERATOR_THRESHOLD)
0631             iterating_matrix_assign<F> (m, e, orientation_category ());
0632         else
0633             indexing_matrix_assign<F> (m, e, orientation_category ());
0634 #endif
0635     }
0636     // Packed (proxy) row major case
0637     template<template <class T1, class T2> class F, class R, class M, class E>
0638     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0639     void matrix_assign (M &m, const matrix_expression<E> &e, packed_proxy_tag, row_major_tag) {
0640         typedef typename matrix_traits<E>::value_type expr_value_type;
0641         typedef F<typename M::iterator2::reference, expr_value_type> functor_type;
0642         // R unnecessary, make_conformant not required
0643         typedef typename M::difference_type difference_type;
0644 
0645         BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
0646         BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
0647 
0648 #if BOOST_UBLAS_TYPE_CHECK
0649         typedef typename M::value_type value_type;
0650         matrix<value_type, row_major> cm (m.size1 (), m.size2 ());
0651         indexing_matrix_assign<scalar_assign> (cm, m, row_major_tag ());
0652         indexing_matrix_assign<F> (cm, e, row_major_tag ());
0653 #endif
0654         typename M::iterator1 it1 (m.begin1 ());
0655         typename M::iterator1 it1_end (m.end1 ());
0656         typename E::const_iterator1 it1e (e ().begin1 ());
0657         typename E::const_iterator1 it1e_end (e ().end1 ());
0658         difference_type it1_size (it1_end - it1);
0659         difference_type it1e_size (it1e_end - it1e);
0660         difference_type diff1 (0);
0661         if (it1_size > 0 && it1e_size > 0)
0662             diff1 = it1.index1 () - it1e.index1 ();
0663         if (diff1 != 0) {
0664             difference_type size1 = (std::min) (diff1, it1e_size);
0665             if (size1 > 0) {
0666                 it1e += size1;
0667                 it1e_size -= size1;
0668                 diff1 -= size1;
0669             }
0670             size1 = (std::min) (- diff1, it1_size);
0671             if (size1 > 0) {
0672                 it1_size -= size1;
0673 //Disabled warning C4127 because the conditional expression is constant
0674 #ifdef _MSC_VER
0675 #pragma warning(push)
0676 #pragma warning(disable: 4127)
0677 #endif
0678                 if (!functor_type::computed) {
0679 #ifdef _MSC_VER
0680 #pragma warning(pop)
0681 #endif
0682                     while (-- size1 >= 0) { // zeroing
0683 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0684                         typename M::iterator2 it2 (it1.begin ());
0685                         typename M::iterator2 it2_end (it1.end ());
0686 #else
0687                         typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
0688                         typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
0689 #endif
0690                         difference_type size2 (it2_end - it2);
0691                         while (-- size2 >= 0)
0692                             functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
0693                         ++ it1;
0694                     }
0695                 } else {
0696                     it1 += size1;
0697                 }
0698                 diff1 += size1;
0699             }
0700         }
0701         difference_type size1 ((std::min) (it1_size, it1e_size));
0702         it1_size -= size1;
0703         it1e_size -= size1;
0704         while (-- size1 >= 0) {
0705 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0706             typename M::iterator2 it2 (it1.begin ());
0707             typename M::iterator2 it2_end (it1.end ());
0708             typename E::const_iterator2 it2e (it1e.begin ());
0709             typename E::const_iterator2 it2e_end (it1e.end ());
0710 #else
0711             typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
0712             typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
0713             typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
0714             typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
0715 #endif
0716             difference_type it2_size (it2_end - it2);
0717             difference_type it2e_size (it2e_end - it2e);
0718             difference_type diff2 (0);
0719             if (it2_size > 0 && it2e_size > 0) {
0720                 diff2 = it2.index2 () - it2e.index2 ();
0721                 difference_type size2 = (std::min) (diff2, it2e_size);
0722                 if (size2 > 0) {
0723                     it2e += size2;
0724                     it2e_size -= size2;
0725                     diff2 -= size2;
0726                 }
0727                 size2 = (std::min) (- diff2, it2_size);
0728                 if (size2 > 0) {
0729                     it2_size -= size2;
0730 //Disabled warning C4127 because the conditional expression is constant
0731 #ifdef _MSC_VER
0732 #pragma warning(push)
0733 #pragma warning(disable: 4127)
0734 #endif
0735                     if (!functor_type::computed) {
0736 #ifdef _MSC_VER
0737 #pragma warning(pop)
0738 #endif
0739                         while (-- size2 >= 0)   // zeroing
0740                             functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
0741                     } else {
0742                         it2 += size2;
0743                     }
0744                     diff2 += size2;
0745                 }
0746             }
0747             difference_type size2 ((std::min) (it2_size, it2e_size));
0748             it2_size -= size2;
0749             it2e_size -= size2;
0750             while (-- size2 >= 0)
0751                 functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
0752             size2 = it2_size;
0753 //Disabled warning C4127 because the conditional expression is constant
0754 #ifdef _MSC_VER
0755 #pragma warning(push)
0756 #pragma warning(disable: 4127)
0757 #endif
0758             if (!functor_type::computed) {
0759 #ifdef _MSC_VER
0760 #pragma warning(pop)
0761 #endif
0762                 while (-- size2 >= 0)   // zeroing
0763                     functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
0764             } else {
0765                 it2 += size2;
0766             }
0767             ++ it1, ++ it1e;
0768         }
0769         size1 = it1_size;
0770 //Disabled warning C4127 because the conditional expression is constant
0771 #ifdef _MSC_VER
0772 #pragma warning(push)
0773 #pragma warning(disable: 4127)
0774 #endif
0775         if (!functor_type::computed) {
0776 #ifdef _MSC_VER
0777 #pragma warning(pop)
0778 #endif
0779             while (-- size1 >= 0) { // zeroing
0780 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0781                 typename M::iterator2 it2 (it1.begin ());
0782                 typename M::iterator2 it2_end (it1.end ());
0783 #else
0784                 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
0785                 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
0786 #endif
0787                 difference_type size2 (it2_end - it2);
0788                 while (-- size2 >= 0)
0789                     functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
0790                 ++ it1;
0791             }
0792         } else {
0793             it1 += size1;
0794         }
0795 #if BOOST_UBLAS_TYPE_CHECK
0796         if (! disable_type_check<bool>::value)
0797             BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
0798 #endif
0799     }
0800     // Packed (proxy) column major case
0801     template<template <class T1, class T2> class F, class R, class M, class E>
0802     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0803     void matrix_assign (M &m, const matrix_expression<E> &e, packed_proxy_tag, column_major_tag) {
0804         typedef typename matrix_traits<E>::value_type expr_value_type;
0805         typedef F<typename M::iterator1::reference, expr_value_type> functor_type;
0806         // R unnecessary, make_conformant not required
0807         typedef typename M::difference_type difference_type;
0808 
0809         BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
0810         BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
0811 
0812 #if BOOST_UBLAS_TYPE_CHECK
0813         typedef typename M::value_type value_type;
0814         matrix<value_type, column_major> cm (m.size1 (), m.size2 ());
0815         indexing_matrix_assign<scalar_assign> (cm, m, column_major_tag ());
0816         indexing_matrix_assign<F> (cm, e, column_major_tag ());
0817 #endif
0818         typename M::iterator2 it2 (m.begin2 ());
0819         typename M::iterator2 it2_end (m.end2 ());
0820         typename E::const_iterator2 it2e (e ().begin2 ());
0821         typename E::const_iterator2 it2e_end (e ().end2 ());
0822         difference_type it2_size (it2_end - it2);
0823         difference_type it2e_size (it2e_end - it2e);
0824         difference_type diff2 (0);
0825         if (it2_size > 0 && it2e_size > 0)
0826             diff2 = it2.index2 () - it2e.index2 ();
0827         if (diff2 != 0) {
0828             difference_type size2 = (std::min) (diff2, it2e_size);
0829             if (size2 > 0) {
0830                 it2e += size2;
0831                 it2e_size -= size2;
0832                 diff2 -= size2;
0833             }
0834             size2 = (std::min) (- diff2, it2_size);
0835             if (size2 > 0) {
0836                 it2_size -= size2;
0837 //Disabled warning C4127 because the conditional expression is constant
0838 #ifdef _MSC_VER
0839 #pragma warning(push)
0840 #pragma warning(disable: 4127)
0841 #endif
0842                 if (!functor_type::computed) {
0843 #ifdef _MSC_VER
0844 #pragma warning(pop)
0845 #endif
0846                     while (-- size2 >= 0) { // zeroing
0847 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0848                         typename M::iterator1 it1 (it2.begin ());
0849                         typename M::iterator1 it1_end (it2.end ());
0850 #else
0851                         typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
0852                         typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
0853 #endif
0854                         difference_type size1 (it1_end - it1);
0855                         while (-- size1 >= 0)
0856                             functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
0857                         ++ it2;
0858                     }
0859                 } else {
0860                     it2 += size2;
0861                 }
0862                 diff2 += size2;
0863             }
0864         }
0865         difference_type size2 ((std::min) (it2_size, it2e_size));
0866         it2_size -= size2;
0867         it2e_size -= size2;
0868         while (-- size2 >= 0) {
0869 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0870             typename M::iterator1 it1 (it2.begin ());
0871             typename M::iterator1 it1_end (it2.end ());
0872             typename E::const_iterator1 it1e (it2e.begin ());
0873             typename E::const_iterator1 it1e_end (it2e.end ());
0874 #else
0875             typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
0876             typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
0877             typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
0878             typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
0879 #endif
0880             difference_type it1_size (it1_end - it1);
0881             difference_type it1e_size (it1e_end - it1e);
0882             difference_type diff1 (0);
0883             if (it1_size > 0 && it1e_size > 0) {
0884                 diff1 = it1.index1 () - it1e.index1 ();
0885                 difference_type size1 = (std::min) (diff1, it1e_size);
0886                 if (size1 > 0) {
0887                     it1e += size1;
0888                     it1e_size -= size1;
0889                     diff1 -= size1;
0890                 }
0891                 size1 = (std::min) (- diff1, it1_size);
0892                 if (size1 > 0) {
0893                     it1_size -= size1;
0894 //Disabled warning C4127 because the conditional expression is constant
0895 #ifdef _MSC_VER
0896 #pragma warning(push)
0897 #pragma warning(disable: 4127)
0898 #endif
0899                     if (!functor_type::computed) {
0900 #ifdef _MSC_VER
0901 #pragma warning(pop)
0902 #endif
0903                         while (-- size1 >= 0)   // zeroing
0904                             functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
0905                     } else {
0906                         it1 += size1;
0907                     }
0908                     diff1 += size1;
0909                 }
0910             }
0911             difference_type size1 ((std::min) (it1_size, it1e_size));
0912             it1_size -= size1;
0913             it1e_size -= size1;
0914             while (-- size1 >= 0)
0915                 functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
0916             size1 = it1_size;
0917 //Disabled warning C4127 because the conditional expression is constant
0918 #ifdef _MSC_VER
0919 #pragma warning(push)
0920 #pragma warning(disable: 4127)
0921 #endif
0922             if (!functor_type::computed) {
0923 
0924 #ifdef _MSC_VER
0925 #pragma warning(pop)
0926 #endif
0927                 while (-- size1 >= 0)   // zeroing
0928                     functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
0929             } else {
0930                 it1 += size1;
0931             }
0932             ++ it2, ++ it2e;
0933         }
0934         size2 = it2_size;
0935 //Disabled warning C4127 because the conditional expression is constant
0936 #ifdef _MSC_VER
0937 #pragma warning(push)
0938 #pragma warning(disable: 4127)
0939 #endif
0940         if (!functor_type::computed) {
0941 #ifdef _MSC_VER
0942 #pragma warning(pop)
0943 #endif
0944             while (-- size2 >= 0) { // zeroing
0945 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0946                 typename M::iterator1 it1 (it2.begin ());
0947                 typename M::iterator1 it1_end (it2.end ());
0948 #else
0949                 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
0950                 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
0951 #endif
0952                 difference_type size1 (it1_end - it1);
0953                 while (-- size1 >= 0)
0954                     functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
0955                 ++ it2;
0956             }
0957         } else {
0958             it2 += size2;
0959         }
0960 #if BOOST_UBLAS_TYPE_CHECK
0961         if (! disable_type_check<bool>::value)
0962             BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
0963 #endif
0964     }
0965     // Sparse row major case
0966     template<template <class T1, class T2> class F, class R, class M, class E>
0967     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0968     void matrix_assign (M &m, const matrix_expression<E> &e, sparse_tag, row_major_tag) {
0969         typedef F<typename M::iterator2::reference, typename E::value_type> functor_type;
0970         // R unnecessary, make_conformant not required
0971 
0972 //Disabled warning C4127 because the conditional expression is constant
0973 #ifdef _MSC_VER
0974 #pragma warning(push)
0975 #pragma warning(disable: 4127)
0976 #endif
0977         BOOST_STATIC_ASSERT ((!functor_type::computed));
0978 #ifdef _MSC_VER
0979 #pragma warning(pop)
0980 #endif
0981         BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
0982         BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
0983         typedef typename M::value_type value_type;
0984         // Sparse type has no numeric constraints to check
0985 
0986         m.clear ();
0987         typename E::const_iterator1 it1e (e ().begin1 ());
0988         typename E::const_iterator1 it1e_end (e ().end1 ());
0989         while (it1e != it1e_end) {
0990 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0991             typename E::const_iterator2 it2e (it1e.begin ());
0992             typename E::const_iterator2 it2e_end (it1e.end ());
0993 #else
0994             typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
0995             typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
0996 #endif
0997             while (it2e != it2e_end) {
0998                 value_type t (*it2e);
0999                 if (t != value_type/*zero*/())
1000                     m.insert_element (it2e.index1 (), it2e.index2 (), t);
1001                 ++ it2e;
1002             }
1003             ++ it1e;
1004         }
1005     }
1006     // Sparse column major case
1007     template<template <class T1, class T2> class F, class R, class M, class E>
1008     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1009     void matrix_assign (M &m, const matrix_expression<E> &e, sparse_tag, column_major_tag) {
1010         typedef F<typename M::iterator1::reference, typename E::value_type> functor_type;
1011         // R unnecessary, make_conformant not required
1012 
1013 //Disabled warning C4127 because the conditional expression is constant
1014 #ifdef _MSC_VER
1015 #pragma warning(push)
1016 #pragma warning(disable: 4127)
1017 #endif
1018         BOOST_STATIC_ASSERT ((!functor_type::computed));
1019 #ifdef _MSC_VER
1020 #pragma warning(pop)
1021 #endif
1022         BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1023         BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1024         typedef typename M::value_type value_type;
1025         // Sparse type has no numeric constraints to check
1026 
1027         m.clear ();
1028         typename E::const_iterator2 it2e (e ().begin2 ());
1029         typename E::const_iterator2 it2e_end (e ().end2 ());
1030         while (it2e != it2e_end) {
1031 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1032             typename E::const_iterator1 it1e (it2e.begin ());
1033             typename E::const_iterator1 it1e_end (it2e.end ());
1034 #else
1035             typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
1036             typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
1037 #endif
1038             while (it1e != it1e_end) {
1039                 value_type t (*it1e);
1040                 if (t != value_type/*zero*/())
1041                     m.insert_element (it1e.index1 (), it1e.index2 (), t);
1042                 ++ it1e;
1043             }
1044             ++ it2e;
1045         }
1046     }
1047     // Sparse proxy or functional row major case
1048     template<template <class T1, class T2> class F, class R, class M, class E>
1049     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1050     void matrix_assign (M &m, const matrix_expression<E> &e, sparse_proxy_tag, row_major_tag) {
1051         typedef typename matrix_traits<E>::value_type expr_value_type;
1052         typedef F<typename M::iterator2::reference, expr_value_type> functor_type;
1053         typedef R conformant_restrict_type;
1054         typedef typename M::size_type size_type;
1055         typedef typename M::difference_type difference_type;
1056 
1057         BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1058         BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1059 
1060 #if BOOST_UBLAS_TYPE_CHECK
1061         typedef typename M::value_type value_type;
1062         matrix<value_type, row_major> cm (m.size1 (), m.size2 ());
1063         indexing_matrix_assign<scalar_assign> (cm, m, row_major_tag ());
1064         indexing_matrix_assign<F> (cm, e, row_major_tag ());
1065 #endif
1066         detail::make_conformant (m, e, row_major_tag (), conformant_restrict_type ());
1067 
1068         typename M::iterator1 it1 (m.begin1 ());
1069         typename M::iterator1 it1_end (m.end1 ());
1070         typename E::const_iterator1 it1e (e ().begin1 ());
1071         typename E::const_iterator1 it1e_end (e ().end1 ());
1072         while (it1 != it1_end && it1e != it1e_end) {
1073             difference_type compare = it1.index1 () - it1e.index1 ();
1074             if (compare == 0) {
1075 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1076                 typename M::iterator2 it2 (it1.begin ());
1077                 typename M::iterator2 it2_end (it1.end ());
1078                 typename E::const_iterator2 it2e (it1e.begin ());
1079                 typename E::const_iterator2 it2e_end (it1e.end ());
1080 #else
1081                 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1082                 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1083                 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
1084                 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
1085 #endif
1086                 if (it2 != it2_end && it2e != it2e_end) {
1087                     size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
1088                     for (;;) {
1089                         difference_type compare2 = it2_index - it2e_index;
1090                         if (compare2 == 0) {
1091                             functor_type::apply (*it2, *it2e);
1092                             ++ it2, ++ it2e;
1093                             if (it2 != it2_end && it2e != it2e_end) {
1094                                 it2_index = it2.index2 ();
1095                                 it2e_index = it2e.index2 ();
1096                             } else
1097                                 break;
1098                         } else if (compare2 < 0) {
1099 //Disabled warning C4127 because the conditional expression is constant
1100 #ifdef _MSC_VER
1101 #pragma warning(push)
1102 #pragma warning(disable: 4127)
1103 #endif
1104                             if (!functor_type::computed) {
1105 #ifdef _MSC_VER
1106 #pragma warning(pop)
1107 #endif
1108                                 functor_type::apply (*it2, expr_value_type/*zero*/());
1109                                 ++ it2;
1110                             } else
1111                                 increment (it2, it2_end, - compare2);
1112                             if (it2 != it2_end)
1113                                 it2_index = it2.index2 ();
1114                             else
1115                                 break;
1116                         } else if (compare2 > 0) {
1117                             increment (it2e, it2e_end, compare2);
1118                             if (it2e != it2e_end)
1119                                 it2e_index = it2e.index2 ();
1120                             else
1121                                 break;
1122                         }
1123                     }
1124                 }
1125 //Disabled warning C4127 because the conditional expression is constant
1126 #ifdef _MSC_VER
1127 #pragma warning(push)
1128 #pragma warning(disable: 4127)
1129 #endif
1130                 if (!functor_type::computed) {
1131 #ifdef _MSC_VER
1132 #pragma warning(pop)
1133 #endif
1134                     while (it2 != it2_end) {    // zeroing
1135                         functor_type::apply (*it2, expr_value_type/*zero*/());
1136                         ++ it2;
1137                     }
1138                 } else {
1139                     it2 = it2_end;
1140                 }
1141                 ++ it1, ++ it1e;
1142             } else if (compare < 0) {
1143 //Disabled warning C4127 because the conditional expression is constant
1144 #ifdef _MSC_VER
1145 #pragma warning(push)
1146 #pragma warning(disable: 4127)
1147 #endif
1148                 if (!functor_type::computed) {
1149 #ifdef _MSC_VER
1150 #pragma warning(pop)
1151 #endif
1152 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1153                     typename M::iterator2 it2 (it1.begin ());
1154                     typename M::iterator2 it2_end (it1.end ());
1155 #else
1156                     typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1157                     typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1158 #endif
1159                     while (it2 != it2_end) {    // zeroing
1160                         functor_type::apply (*it2, expr_value_type/*zero*/());
1161                         ++ it2;
1162                     }
1163                     ++ it1;
1164                 } else {
1165                     increment (it1, it1_end, - compare);
1166                 }
1167             } else if (compare > 0) {
1168                 increment (it1e, it1e_end, compare);
1169             }
1170         }
1171 //Disabled warning C4127 because the conditional expression is constant
1172 #ifdef _MSC_VER
1173 #pragma warning(push)
1174 #pragma warning(disable: 4127)
1175 #endif
1176         if (!functor_type::computed) {
1177 #ifdef _MSC_VER
1178 #pragma warning(pop)
1179 #endif
1180             while (it1 != it1_end) {
1181 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1182                 typename M::iterator2 it2 (it1.begin ());
1183                 typename M::iterator2 it2_end (it1.end ());
1184 #else
1185                 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1186                 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1187 #endif
1188                 while (it2 != it2_end) {    // zeroing
1189                     functor_type::apply (*it2, expr_value_type/*zero*/());
1190                     ++ it2;
1191                 }
1192                 ++ it1;
1193             }
1194         } else {
1195             it1 = it1_end;
1196         }
1197 #if BOOST_UBLAS_TYPE_CHECK
1198         if (! disable_type_check<bool>::value)
1199             BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
1200 #endif
1201     }
1202     // Sparse proxy or functional column major case
1203     template<template <class T1, class T2> class F, class R, class M, class E>
1204     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1205     void matrix_assign (M &m, const matrix_expression<E> &e, sparse_proxy_tag, column_major_tag) {
1206         typedef typename matrix_traits<E>::value_type expr_value_type;
1207         typedef F<typename M::iterator1::reference, expr_value_type> functor_type;
1208         typedef R conformant_restrict_type;
1209         typedef typename M::size_type size_type;
1210         typedef typename M::difference_type difference_type;
1211 
1212         BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1213         BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1214 
1215 #if BOOST_UBLAS_TYPE_CHECK
1216         typedef typename M::value_type value_type;
1217         matrix<value_type, column_major> cm (m.size1 (), m.size2 ());
1218         indexing_matrix_assign<scalar_assign> (cm, m, column_major_tag ());
1219         indexing_matrix_assign<F> (cm, e, column_major_tag ());
1220 #endif
1221         detail::make_conformant (m, e, column_major_tag (), conformant_restrict_type ());
1222 
1223         typename M::iterator2 it2 (m.begin2 ());
1224         typename M::iterator2 it2_end (m.end2 ());
1225         typename E::const_iterator2 it2e (e ().begin2 ());
1226         typename E::const_iterator2 it2e_end (e ().end2 ());
1227         while (it2 != it2_end && it2e != it2e_end) {
1228             difference_type compare = it2.index2 () - it2e.index2 ();
1229             if (compare == 0) {
1230 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1231                 typename M::iterator1 it1 (it2.begin ());
1232                 typename M::iterator1 it1_end (it2.end ());
1233                 typename E::const_iterator1 it1e (it2e.begin ());
1234                 typename E::const_iterator1 it1e_end (it2e.end ());
1235 #else
1236                 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1237                 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1238                 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
1239                 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
1240 #endif
1241                 if (it1 != it1_end && it1e != it1e_end) {
1242                     size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
1243                     for (;;) {
1244                         difference_type compare2 = it1_index - it1e_index;
1245                         if (compare2 == 0) {
1246                             functor_type::apply (*it1, *it1e);
1247                             ++ it1, ++ it1e;
1248                             if (it1 != it1_end && it1e != it1e_end) {
1249                                 it1_index = it1.index1 ();
1250                                 it1e_index = it1e.index1 ();
1251                             } else
1252                                 break;
1253                         } else if (compare2 < 0) {
1254 //Disabled warning C4127 because the conditional expression is constant
1255 #ifdef _MSC_VER
1256 #pragma warning(push)
1257 #pragma warning(disable: 4127)
1258 #endif
1259                             if (!functor_type::computed) {
1260 #ifdef _MSC_VER
1261 #pragma warning(pop)
1262 #endif
1263                                 functor_type::apply (*it1, expr_value_type/*zero*/()); // zeroing
1264                                 ++ it1;
1265                             } else
1266                                 increment (it1, it1_end, - compare2);
1267                             if (it1 != it1_end)
1268                                 it1_index = it1.index1 ();
1269                             else
1270                                 break;
1271                         } else if (compare2 > 0) {
1272                             increment (it1e, it1e_end, compare2);
1273                             if (it1e != it1e_end)
1274                                 it1e_index = it1e.index1 ();
1275                             else
1276                                 break;
1277                         }
1278                     }
1279                 }
1280 //Disabled warning C4127 because the conditional expression is constant
1281 #ifdef _MSC_VER
1282 #pragma warning(push)
1283 #pragma warning(disable: 4127)
1284 #endif
1285                 if (!functor_type::computed) {
1286 #ifdef _MSC_VER
1287 #pragma warning(pop)
1288 #endif
1289                     while (it1 != it1_end) {    // zeroing
1290                         functor_type::apply (*it1, expr_value_type/*zero*/());
1291                         ++ it1;
1292                     }
1293                 } else {
1294                     it1 = it1_end;
1295                 }
1296                 ++ it2, ++ it2e;
1297             } else if (compare < 0) {
1298 //Disabled warning C4127 because the conditional expression is constant
1299 #ifdef _MSC_VER
1300 #pragma warning(push)
1301 #pragma warning(disable: 4127)
1302 #endif
1303                 if (!functor_type::computed) {
1304 #ifdef _MSC_VER
1305 #pragma warning(pop)
1306 #endif
1307 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1308                     typename M::iterator1 it1 (it2.begin ());
1309                     typename M::iterator1 it1_end (it2.end ());
1310 #else
1311                     typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1312                     typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1313 #endif
1314                     while (it1 != it1_end) {    // zeroing
1315                         functor_type::apply (*it1, expr_value_type/*zero*/());
1316                         ++ it1;
1317                     }
1318                     ++ it2;
1319                 } else {
1320                     increment (it2, it2_end, - compare);
1321                 }
1322             } else if (compare > 0) {
1323                 increment (it2e, it2e_end, compare);
1324             }
1325         }
1326 //Disabled warning C4127 because the conditional expression is constant
1327 #ifdef _MSC_VER
1328 #pragma warning(push)
1329 #pragma warning(disable: 4127)
1330 #endif
1331         if (!functor_type::computed) {
1332 #ifdef _MSC_VER
1333 #pragma warning(pop)
1334 #endif
1335             while (it2 != it2_end) {
1336 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1337                 typename M::iterator1 it1 (it2.begin ());
1338                 typename M::iterator1 it1_end (it2.end ());
1339 #else
1340                 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1341                 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1342 #endif
1343                 while (it1 != it1_end) {    // zeroing
1344                     functor_type::apply (*it1, expr_value_type/*zero*/());
1345                     ++ it1;
1346                 }
1347                 ++ it2;
1348             }
1349         } else {
1350             it2 = it2_end;
1351         }
1352 #if BOOST_UBLAS_TYPE_CHECK
1353         if (! disable_type_check<bool>::value)
1354             BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
1355 #endif
1356     }
1357 
1358     // Dispatcher
1359     template<template <class T1, class T2> class F, class M, class E>
1360     BOOST_UBLAS_INLINE
1361     void matrix_assign (M &m, const matrix_expression<E> &e) {
1362         typedef typename matrix_assign_traits<typename M::storage_category,
1363                                               F<typename M::reference, typename E::value_type>::computed,
1364                                               typename E::const_iterator1::iterator_category,
1365                                               typename E::const_iterator2::iterator_category>::storage_category storage_category;
1366         // give preference to matrix M's orientation if known
1367         typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1368                                           typename E::orientation_category ,
1369                                           typename M::orientation_category >::type orientation_category;
1370         typedef basic_full<typename M::size_type> unrestricted;
1371         matrix_assign<F, unrestricted> (m, e, storage_category (), orientation_category ());
1372     }
1373     template<template <class T1, class T2> class F, class R, class M, class E>
1374     BOOST_UBLAS_INLINE
1375     void matrix_assign (M &m, const matrix_expression<E> &e) {
1376         typedef R conformant_restrict_type;
1377         typedef typename matrix_assign_traits<typename M::storage_category,
1378                                               F<typename M::reference, typename E::value_type>::computed,
1379                                               typename E::const_iterator1::iterator_category,
1380                                               typename E::const_iterator2::iterator_category>::storage_category storage_category;
1381         // give preference to matrix M's orientation if known
1382         typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1383                                           typename E::orientation_category ,
1384                                           typename M::orientation_category >::type orientation_category;
1385         matrix_assign<F, conformant_restrict_type> (m, e, storage_category (), orientation_category ());
1386     }
1387 
1388     template<class SC, class RI1, class RI2>
1389     struct matrix_swap_traits {
1390         typedef SC storage_category;
1391     };
1392 
1393     template<>
1394     struct matrix_swap_traits<dense_proxy_tag, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
1395         typedef sparse_proxy_tag storage_category;
1396     };
1397 
1398     template<>
1399     struct matrix_swap_traits<packed_proxy_tag, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
1400         typedef sparse_proxy_tag storage_category;
1401     };
1402 
1403     // Dense (proxy) row major case
1404     template<template <class T1, class T2> class F, class R, class M, class E>
1405     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1406     void matrix_swap (M &m, matrix_expression<E> &e, dense_proxy_tag, row_major_tag) {
1407         typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
1408         // R unnecessary, make_conformant not required
1409         //typedef typename M::size_type size_type; // gcc is complaining that this is not used, although this is not right
1410         typedef typename M::difference_type difference_type;
1411         typename M::iterator1 it1 (m.begin1 ());
1412         typename E::iterator1 it1e (e ().begin1 ());
1413         difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), typename M::size_type (e ().end1 () - it1e)));
1414         while (-- size1 >= 0) {
1415 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1416             typename M::iterator2 it2 (it1.begin ());
1417             typename E::iterator2 it2e (it1e.begin ());
1418             difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), typename M::size_type (it1e.end () - it2e)));
1419 #else
1420             typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1421             typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1422             difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), typename M::size_type (end (it1e, iterator1_tag ()) - it2e)));
1423 #endif
1424             while (-- size2 >= 0)
1425                 functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
1426             ++ it1, ++ it1e;
1427         }
1428     }
1429     // Dense (proxy) column major case
1430     template<template <class T1, class T2> class F, class R, class M, class E>
1431     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1432     void matrix_swap (M &m, matrix_expression<E> &e, dense_proxy_tag, column_major_tag) {
1433         typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
1434         // R unnecessary, make_conformant not required
1435         // typedef typename M::size_type size_type; // gcc is complaining that this is not used, although this is not right
1436         typedef typename M::difference_type difference_type;
1437         typename M::iterator2 it2 (m.begin2 ());
1438         typename E::iterator2 it2e (e ().begin2 ());
1439         difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), typename M::size_type (e ().end2 () - it2e)));
1440         while (-- size2 >= 0) {
1441 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1442             typename M::iterator1 it1 (it2.begin ());
1443             typename E::iterator1 it1e (it2e.begin ());
1444             difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), typename M::size_type (it2e.end () - it1e)));
1445 #else
1446             typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1447             typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1448             difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), typename M::size_type (end (it2e, iterator2_tag ()) - it1e)));
1449 #endif
1450             while (-- size1 >= 0)
1451                 functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
1452             ++ it2, ++ it2e;
1453         }
1454     }
1455     // Packed (proxy) row major case
1456     template<template <class T1, class T2> class F, class R, class M, class E>
1457     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1458     void matrix_swap (M &m, matrix_expression<E> &e, packed_proxy_tag, row_major_tag) {
1459         typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
1460         // R unnecessary, make_conformant not required
1461         typedef typename M::difference_type difference_type;
1462         typename M::iterator1 it1 (m.begin1 ());
1463         typename E::iterator1 it1e (e ().begin1 ());
1464         difference_type size1 (BOOST_UBLAS_SAME (m.end1 () - it1, e ().end1 () - it1e));
1465         while (-- size1 >= 0) {
1466 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1467             typename M::iterator2 it2 (it1.begin ());
1468             typename E::iterator2 it2e (it1e.begin ());
1469             difference_type size2 (BOOST_UBLAS_SAME (it1.end () - it2, it1e.end () - it2e));
1470 #else
1471             typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1472             typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1473             difference_type size2 (BOOST_UBLAS_SAME (end (it1, iterator1_tag ()) - it2, end (it1e, iterator1_tag ()) - it2e));
1474 #endif
1475             while (-- size2 >= 0)
1476                 functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
1477             ++ it1, ++ it1e;
1478         }
1479     }
1480     // Packed (proxy) column major case
1481     template<template <class T1, class T2> class F, class R, class M, class E>
1482     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1483     void matrix_swap (M &m, matrix_expression<E> &e, packed_proxy_tag, column_major_tag) {
1484         typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
1485         // R unnecessary, make_conformant not required
1486         typedef typename M::difference_type difference_type;
1487         typename M::iterator2 it2 (m.begin2 ());
1488         typename E::iterator2 it2e (e ().begin2 ());
1489         difference_type size2 (BOOST_UBLAS_SAME (m.end2 () - it2, e ().end2 () - it2e));
1490         while (-- size2 >= 0) {
1491 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1492             typename M::iterator1 it1 (it2.begin ());
1493             typename E::iterator1 it1e (it2e.begin ());
1494             difference_type size1 (BOOST_UBLAS_SAME (it2.end () - it1, it2e.end () - it1e));
1495 #else
1496             typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1497             typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1498             difference_type size1 (BOOST_UBLAS_SAME (end (it2, iterator2_tag ()) - it1, end (it2e, iterator2_tag ()) - it1e));
1499 #endif
1500             while (-- size1 >= 0)
1501                 functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
1502             ++ it2, ++ it2e;
1503         }
1504     }
1505     // Sparse (proxy) row major case
1506     template<template <class T1, class T2> class F, class R, class M, class E>
1507     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1508     void matrix_swap (M &m, matrix_expression<E> &e, sparse_proxy_tag, row_major_tag) {
1509         typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
1510         typedef R conformant_restrict_type;
1511         typedef typename M::size_type size_type;
1512         typedef typename M::difference_type difference_type;
1513         BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1514         BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1515 
1516         detail::make_conformant (m, e, row_major_tag (), conformant_restrict_type ());
1517         // FIXME should be a seperate restriction for E
1518         detail::make_conformant (e (), m, row_major_tag (), conformant_restrict_type ());
1519 
1520         typename M::iterator1 it1 (m.begin1 ());
1521         typename M::iterator1 it1_end (m.end1 ());
1522         typename E::iterator1 it1e (e ().begin1 ());
1523         typename E::iterator1 it1e_end (e ().end1 ());
1524         while (it1 != it1_end && it1e != it1e_end) {
1525             difference_type compare = it1.index1 () - it1e.index1 ();
1526             if (compare == 0) {
1527 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1528                 typename M::iterator2 it2 (it1.begin ());
1529                 typename M::iterator2 it2_end (it1.end ());
1530                 typename E::iterator2 it2e (it1e.begin ());
1531                 typename E::iterator2 it2e_end (it1e.end ());
1532 #else
1533                 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1534                 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1535                 typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1536                 typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
1537 #endif
1538                 if (it2 != it2_end && it2e != it2e_end) {
1539                     size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
1540                     for (;;) {
1541                         difference_type compare2 = it2_index - it2e_index;
1542                         if (compare2 == 0) {
1543                             functor_type::apply (*it2, *it2e);
1544                             ++ it2, ++ it2e;
1545                             if (it2 != it2_end && it2e != it2e_end) {
1546                                 it2_index = it2.index2 ();
1547                                 it2e_index = it2e.index2 ();
1548                             } else
1549                                 break;
1550                         } else if (compare2 < 0) {
1551                             increment (it2, it2_end, - compare2);
1552                             if (it2 != it2_end)
1553                                 it2_index = it2.index2 ();
1554                             else
1555                                 break;
1556                         } else if (compare2 > 0) {
1557                             increment (it2e, it2e_end, compare2);
1558                             if (it2e != it2e_end)
1559                                 it2e_index = it2e.index2 ();
1560                             else
1561                                 break;
1562                         }
1563                     }
1564                 }
1565 #if BOOST_UBLAS_TYPE_CHECK
1566                 increment (it2e, it2e_end);
1567                 increment (it2, it2_end);
1568 #endif
1569                 ++ it1, ++ it1e;
1570             } else if (compare < 0) {
1571 #if BOOST_UBLAS_TYPE_CHECK
1572                 while (it1.index1 () < it1e.index1 ()) {
1573 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1574                     typename M::iterator2 it2 (it1.begin ());
1575                     typename M::iterator2 it2_end (it1.end ());
1576 #else
1577                     typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1578                     typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1579 #endif
1580                     increment (it2, it2_end);
1581                     ++ it1;
1582                 }
1583 #else
1584                 increment (it1, it1_end, - compare);
1585 #endif
1586             } else if (compare > 0) {
1587 #if BOOST_UBLAS_TYPE_CHECK
1588                 while (it1e.index1 () < it1.index1 ()) {
1589 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1590                     typename E::iterator2 it2e (it1e.begin ());
1591                     typename E::iterator2 it2e_end (it1e.end ());
1592 #else
1593                     typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1594                     typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
1595 #endif
1596                     increment (it2e, it2e_end);
1597                     ++ it1e;
1598                 }
1599 #else
1600                 increment (it1e, it1e_end, compare);
1601 #endif
1602             }
1603         }
1604 #if BOOST_UBLAS_TYPE_CHECK
1605         while (it1e != it1e_end) {
1606 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1607             typename E::iterator2 it2e (it1e.begin ());
1608             typename E::iterator2 it2e_end (it1e.end ());
1609 #else
1610             typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1611             typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
1612 #endif
1613             increment (it2e, it2e_end);
1614             ++ it1e;
1615         }
1616         while (it1 != it1_end) {
1617 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1618             typename M::iterator2 it2 (it1.begin ());
1619             typename M::iterator2 it2_end (it1.end ());
1620 #else
1621             typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1622             typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1623 #endif
1624             increment (it2, it2_end);
1625             ++ it1;
1626         }
1627 #endif
1628     }
1629     // Sparse (proxy) column major case
1630     template<template <class T1, class T2> class F, class R, class M, class E>
1631     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1632     void matrix_swap (M &m, matrix_expression<E> &e, sparse_proxy_tag, column_major_tag) {
1633         typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
1634         typedef R conformant_restrict_type;
1635         typedef typename M::size_type size_type;
1636         typedef typename M::difference_type difference_type;
1637 
1638         BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1639         BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1640 
1641         detail::make_conformant (m, e, column_major_tag (), conformant_restrict_type ());
1642         // FIXME should be a seperate restriction for E
1643         detail::make_conformant (e (), m, column_major_tag (), conformant_restrict_type ());
1644 
1645         typename M::iterator2 it2 (m.begin2 ());
1646         typename M::iterator2 it2_end (m.end2 ());
1647         typename E::iterator2 it2e (e ().begin2 ());
1648         typename E::iterator2 it2e_end (e ().end2 ());
1649         while (it2 != it2_end && it2e != it2e_end) {
1650             difference_type compare = it2.index2 () - it2e.index2 ();
1651             if (compare == 0) {
1652 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1653                 typename M::iterator1 it1 (it2.begin ());
1654                 typename M::iterator1 it1_end (it2.end ());
1655                 typename E::iterator1 it1e (it2e.begin ());
1656                 typename E::iterator1 it1e_end (it2e.end ());
1657 #else
1658                 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1659                 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1660                 typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1661                 typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
1662 #endif
1663                 if (it1 != it1_end && it1e != it1e_end) {
1664                     size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
1665                     for (;;) {
1666                         difference_type compare2 = it1_index - it1e_index;
1667                         if (compare2 == 0) {
1668                             functor_type::apply (*it1, *it1e);
1669                             ++ it1, ++ it1e;
1670                             if (it1 != it1_end && it1e != it1e_end) {
1671                                 it1_index = it1.index1 ();
1672                                 it1e_index = it1e.index1 ();
1673                             } else
1674                                 break;
1675                         }  else if (compare2 < 0) {
1676                             increment (it1, it1_end, - compare2);
1677                             if (it1 != it1_end)
1678                                 it1_index = it1.index1 ();
1679                             else
1680                                 break;
1681                         } else if (compare2 > 0) {
1682                             increment (it1e, it1e_end, compare2);
1683                             if (it1e != it1e_end)
1684                                 it1e_index = it1e.index1 ();
1685                             else
1686                                 break;
1687                         }
1688                     }
1689                 }
1690 #if BOOST_UBLAS_TYPE_CHECK
1691                 increment (it1e, it1e_end);
1692                 increment (it1, it1_end);
1693 #endif
1694                 ++ it2, ++ it2e;
1695             } else if (compare < 0) {
1696 #if BOOST_UBLAS_TYPE_CHECK
1697                 while (it2.index2 () < it2e.index2 ()) {
1698 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1699                     typename M::iterator1 it1 (it2.begin ());
1700                     typename M::iterator1 it1_end (it2.end ());
1701 #else
1702                     typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1703                     typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1704 #endif
1705                     increment (it1, it1_end);
1706                     ++ it2;
1707                 }
1708 #else
1709                 increment (it2, it2_end, - compare);
1710 #endif
1711             } else if (compare > 0) {
1712 #if BOOST_UBLAS_TYPE_CHECK
1713                 while (it2e.index2 () < it2.index2 ()) {
1714 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1715                     typename E::iterator1 it1e (it2e.begin ());
1716                     typename E::iterator1 it1e_end (it2e.end ());
1717 #else
1718                     typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1719                     typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
1720 #endif
1721                     increment (it1e, it1e_end);
1722                     ++ it2e;
1723                 }
1724 #else
1725                 increment (it2e, it2e_end, compare);
1726 #endif
1727             }
1728         }
1729 #if BOOST_UBLAS_TYPE_CHECK
1730         while (it2e != it2e_end) {
1731 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1732             typename E::iterator1 it1e (it2e.begin ());
1733             typename E::iterator1 it1e_end (it2e.end ());
1734 #else
1735             typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1736             typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
1737 #endif
1738             increment (it1e, it1e_end);
1739             ++ it2e;
1740         }
1741         while (it2 != it2_end) {
1742 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1743             typename M::iterator1 it1 (it2.begin ());
1744             typename M::iterator1 it1_end (it2.end ());
1745 #else
1746             typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1747             typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1748 #endif
1749             increment (it1, it1_end);
1750             ++ it2;
1751         }
1752 #endif
1753     }
1754 
1755     // Dispatcher
1756     template<template <class T1, class T2> class F, class M, class E>
1757     BOOST_UBLAS_INLINE
1758     void matrix_swap (M &m, matrix_expression<E> &e) {
1759         typedef typename matrix_swap_traits<typename M::storage_category,
1760                                             typename E::const_iterator1::iterator_category,
1761                                             typename E::const_iterator2::iterator_category>::storage_category storage_category;
1762         // give preference to matrix M's orientation if known
1763         typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1764                                           typename E::orientation_category ,
1765                                           typename M::orientation_category >::type orientation_category;
1766         typedef basic_full<typename M::size_type> unrestricted;
1767         matrix_swap<F, unrestricted> (m, e, storage_category (), orientation_category ());
1768     }
1769     template<template <class T1, class T2> class F, class R, class M, class E>
1770     BOOST_UBLAS_INLINE
1771     void matrix_swap (M &m, matrix_expression<E> &e) {
1772         typedef R conformant_restrict_type;
1773         typedef typename matrix_swap_traits<typename M::storage_category,
1774                                             typename E::const_iterator1::iterator_category,
1775                                             typename E::const_iterator2::iterator_category>::storage_category storage_category;
1776         // give preference to matrix M's orientation if known
1777         typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1778                                           typename E::orientation_category ,
1779                                           typename M::orientation_category >::type orientation_category;
1780         matrix_swap<F, conformant_restrict_type> (m, e, storage_category (), orientation_category ());
1781     }
1782 
1783 }}}
1784 
1785 #endif