Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:01

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_VECTOR_ASSIGN_
0014 #define _BOOST_UBLAS_VECTOR_ASSIGN_
0015 
0016 #include <boost/numeric/ublas/functional.hpp> // scalar_assign
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 vector 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 vector_expression<E1> &e1, const vector_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 vector_expression<E1> &e1, const vector_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     // Make sparse proxies conformant
0047     template<class V, class E>
0048     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0049     void make_conformant (V &v, const vector_expression<E> &e) {
0050         BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
0051         typedef typename V::size_type size_type;
0052         typedef typename V::difference_type difference_type;
0053         typedef typename V::value_type value_type;
0054         // FIXME unbounded_array with push_back maybe better
0055         std::vector<size_type> index;
0056         typename V::iterator it (v.begin ());
0057         typename V::iterator it_end (v.end ());
0058         typename E::const_iterator ite (e ().begin ());
0059         typename E::const_iterator ite_end (e ().end ());
0060         if (it != it_end && ite != ite_end) {
0061             size_type it_index = it.index (), ite_index = ite.index ();
0062             for (;;) {
0063                 difference_type compare = it_index - ite_index;
0064                 if (compare == 0) {
0065                     ++ it, ++ ite;
0066                     if (it != it_end && ite != ite_end) {
0067                         it_index = it.index ();
0068                         ite_index = ite.index ();
0069                     } else
0070                         break;
0071                 } else if (compare < 0) {
0072                     increment (it, it_end, - compare);
0073                     if (it != it_end)
0074                         it_index = it.index ();
0075                     else
0076                         break;
0077                 } else if (compare > 0) {
0078                     if (*ite != value_type/*zero*/())
0079                         index.push_back (ite.index ());
0080                     ++ ite;
0081                     if (ite != ite_end)
0082                         ite_index = ite.index ();
0083                     else
0084                         break;
0085                 }
0086             }
0087         }
0088 
0089         while (ite != ite_end) {
0090             if (*ite != value_type/*zero*/())
0091                 index.push_back (ite.index ());
0092             ++ ite;
0093         }
0094         for (size_type k = 0; k < index.size (); ++ k)
0095             v (index [k]) = value_type/*zero*/();
0096     }
0097 
0098 }//namespace detail
0099 
0100 
0101     // Explicitly iterating
0102     template<template <class T1, class T2> class F, class V, class T>
0103     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0104     void iterating_vector_assign_scalar (V &v, const T &t) {
0105         typedef F<typename V::iterator::reference, T> functor_type;
0106         typedef typename V::difference_type difference_type;
0107         difference_type size (v.size ());
0108         typename V::iterator it (v.begin ());
0109         BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
0110 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0111         while (-- size >= 0)
0112             functor_type::apply (*it, t), ++ it;
0113 #else
0114         DD (size, 4, r, (functor_type::apply (*it, t), ++ it));
0115 #endif
0116     }
0117     // Explicitly case
0118     template<template <class T1, class T2> class F, class V, class T>
0119     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0120     void indexing_vector_assign_scalar (V &v, const T &t) {
0121         typedef F<typename V::reference, T> functor_type;
0122         typedef typename V::size_type size_type;
0123         size_type size (v.size ());
0124 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0125         for (size_type i = 0; i < size; ++ i)
0126             functor_type::apply (v (i), t);
0127 #else
0128         size_type i (0);
0129         DD (size, 4, r, (functor_type::apply (v (i), t), ++ i));
0130 #endif
0131     }
0132 
0133     // Dense (proxy) case
0134     template<template <class T1, class T2> class F, class V, class T>
0135     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0136     void vector_assign_scalar (V &v, const T &t, dense_proxy_tag) {
0137 #ifdef BOOST_UBLAS_USE_INDEXING
0138         indexing_vector_assign_scalar<F> (v, t);
0139 #elif BOOST_UBLAS_USE_ITERATING
0140         iterating_vector_assign_scalar<F> (v, t);
0141 #else
0142         typedef typename V::size_type size_type;
0143         size_type size (v.size ());
0144         if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
0145             iterating_vector_assign_scalar<F> (v, t);
0146         else
0147             indexing_vector_assign_scalar<F> (v, t);
0148 #endif
0149     }
0150     // Packed (proxy) case
0151     template<template <class T1, class T2> class F, class V, class T>
0152     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0153     void vector_assign_scalar (V &v, const T &t, packed_proxy_tag) {
0154         typedef F<typename V::iterator::reference, T> functor_type;
0155         typedef typename V::difference_type difference_type;
0156         typename V::iterator it (v.begin ());
0157         difference_type size (v.end () - it);
0158         while (-- size >= 0)
0159             functor_type::apply (*it, t), ++ it;
0160     }
0161     // Sparse (proxy) case
0162     template<template <class T1, class T2> class F, class V, class T>
0163     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0164     void vector_assign_scalar (V &v, const T &t, sparse_proxy_tag) {
0165         typedef F<typename V::iterator::reference, T> functor_type;
0166         typename V::iterator it (v.begin ());
0167         typename V::iterator it_end (v.end ());
0168         while (it != it_end)
0169             functor_type::apply (*it, t), ++ it;
0170     }
0171 
0172     // Dispatcher
0173     template<template <class T1, class T2> class F, class V, class T>
0174     BOOST_UBLAS_INLINE
0175     void vector_assign_scalar (V &v, const T &t) {
0176         typedef typename V::storage_category storage_category;
0177         vector_assign_scalar<F> (v, t, storage_category ());
0178     }
0179 
0180     template<class SC, bool COMPUTED, class RI>
0181     struct vector_assign_traits {
0182         typedef SC storage_category;
0183     };
0184 
0185     template<bool COMPUTED>
0186     struct vector_assign_traits<dense_tag, COMPUTED, packed_random_access_iterator_tag> {
0187         typedef packed_tag storage_category;
0188     };
0189     template<>
0190     struct vector_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag> {
0191         typedef sparse_tag storage_category;
0192     };
0193     template<>
0194     struct vector_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag> {
0195         typedef sparse_proxy_tag storage_category;
0196     };
0197 
0198     template<bool COMPUTED>
0199     struct vector_assign_traits<dense_proxy_tag, COMPUTED, packed_random_access_iterator_tag> {
0200         typedef packed_proxy_tag storage_category;
0201     };
0202     template<>
0203     struct vector_assign_traits<dense_proxy_tag, false, sparse_bidirectional_iterator_tag> {
0204         typedef sparse_proxy_tag storage_category;
0205     };
0206     template<>
0207     struct vector_assign_traits<dense_proxy_tag, true, sparse_bidirectional_iterator_tag> {
0208         typedef sparse_proxy_tag storage_category;
0209     };
0210 
0211     template<>
0212     struct vector_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag> {
0213         typedef sparse_tag storage_category;
0214     };
0215     template<>
0216     struct vector_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag> {
0217         typedef sparse_proxy_tag storage_category;
0218     };
0219 
0220     template<bool COMPUTED>
0221     struct vector_assign_traits<packed_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag> {
0222         typedef sparse_proxy_tag storage_category;
0223     };
0224 
0225     template<>
0226     struct vector_assign_traits<sparse_tag, true, dense_random_access_iterator_tag> {
0227         typedef sparse_proxy_tag storage_category;
0228     };
0229     template<>
0230     struct vector_assign_traits<sparse_tag, true, packed_random_access_iterator_tag> {
0231         typedef sparse_proxy_tag storage_category;
0232     };
0233     template<>
0234     struct vector_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag> {
0235         typedef sparse_proxy_tag storage_category;
0236     };
0237 
0238     // Explicitly iterating
0239     template<template <class T1, class T2> class F, class V, class E>
0240     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0241     void iterating_vector_assign (V &v, const vector_expression<E> &e) {
0242         typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
0243         typedef typename V::difference_type difference_type;
0244         difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
0245         typename V::iterator it (v.begin ());
0246         BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
0247         typename E::const_iterator ite (e ().begin ());
0248         BOOST_UBLAS_CHECK (e ().end () - ite == size, bad_size ());
0249 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0250         while (-- size >= 0)
0251             functor_type::apply (*it, *ite), ++ it, ++ ite;
0252 #else
0253         DD (size, 2, r, (functor_type::apply (*it, *ite), ++ it, ++ ite));
0254 #endif
0255     }
0256     // Explicitly indexing
0257     template<template <class T1, class T2> class F, class V, class E>
0258     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0259     void indexing_vector_assign (V &v, const vector_expression<E> &e) {
0260         typedef F<typename V::reference, typename E::value_type> functor_type;
0261         typedef typename V::size_type size_type;
0262         size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
0263 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
0264         for (size_type i = 0; i < size; ++ i)
0265             functor_type::apply (v (i), e () (i));
0266 #else
0267         size_type i (0);
0268         DD (size, 2, r, (functor_type::apply (v (i), e () (i)), ++ i));
0269 #endif
0270     }
0271 
0272     // Dense (proxy) case
0273     template<template <class T1, class T2> class F, class V, class E>
0274     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0275     void vector_assign (V &v, const vector_expression<E> &e, dense_proxy_tag) {
0276 #ifdef BOOST_UBLAS_USE_INDEXING
0277         indexing_vector_assign<F> (v, e);
0278 #elif BOOST_UBLAS_USE_ITERATING
0279         iterating_vector_assign<F> (v, e);
0280 #else
0281         typedef typename V::size_type size_type;
0282         size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
0283         if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
0284             iterating_vector_assign<F> (v, e);
0285         else
0286             indexing_vector_assign<F> (v, e);
0287 #endif
0288     }
0289     // Packed (proxy) case
0290     template<template <class T1, class T2> class F, class V, class E>
0291     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0292     void vector_assign (V &v, const vector_expression<E> &e, packed_proxy_tag) {
0293         BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
0294         typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
0295         typedef typename V::difference_type difference_type;
0296         typedef typename V::value_type value_type;
0297 #if BOOST_UBLAS_TYPE_CHECK
0298         vector<value_type> cv (v.size ());
0299         indexing_vector_assign<scalar_assign> (cv, v);
0300         indexing_vector_assign<F> (cv, e);
0301 #endif
0302         typename V::iterator it (v.begin ());
0303         typename V::iterator it_end (v.end ());
0304         typename E::const_iterator ite (e ().begin ());
0305         typename E::const_iterator ite_end (e ().end ());
0306         difference_type it_size (it_end - it);
0307         difference_type ite_size (ite_end - ite);
0308         if (it_size > 0 && ite_size > 0) {
0309             difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
0310             if (size > 0) {
0311                 ite += size;
0312                 ite_size -= size;
0313             }
0314         }
0315         if (it_size > 0 && ite_size > 0) {
0316             difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
0317             if (size > 0) {
0318                 it_size -= size;
0319 //Disabled warning C4127 because the conditional expression is constant
0320 #ifdef _MSC_VER
0321 #pragma warning(push)
0322 #pragma warning(disable: 4127)
0323 #endif
0324                 if (!functor_type::computed) {
0325 #ifdef _MSC_VER
0326 #pragma warning(pop)
0327 #endif
0328                     while (-- size >= 0)    // zeroing
0329                         functor_type::apply (*it, value_type/*zero*/()), ++ it;
0330                 } else {
0331                     it += size;
0332                 }
0333             }
0334         }
0335         difference_type size ((std::min) (it_size, ite_size));
0336         it_size -= size;
0337         ite_size -= size;
0338         while (-- size >= 0)
0339             functor_type::apply (*it, *ite), ++ it, ++ ite;
0340         size = it_size;
0341 //Disabled warning C4127 because the conditional expression is constant
0342 #ifdef _MSC_VER
0343 #pragma warning(push)
0344 #pragma warning(disable: 4127)
0345 #endif
0346         if (!functor_type::computed) {
0347 #ifdef _MSC_VER
0348 #pragma warning(pop)
0349 #endif
0350             while (-- size >= 0)    // zeroing
0351                 functor_type::apply (*it, value_type/*zero*/()), ++ it;
0352         } else {
0353             it += size;
0354         }
0355 #if BOOST_UBLAS_TYPE_CHECK
0356         if (! disable_type_check<bool>::value) 
0357             BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv), 
0358                                external_logic ("external logic or bad condition of inputs"));
0359 #endif
0360     }
0361     // Sparse case
0362     template<template <class T1, class T2> class F, class V, class E>
0363     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0364     void vector_assign (V &v, const vector_expression<E> &e, sparse_tag) {
0365         BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
0366         typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
0367 //Disabled warning C4127 because the conditional expression is constant
0368 #ifdef _MSC_VER
0369 #pragma warning(push)
0370 #pragma warning(disable: 4127)
0371 #endif
0372         BOOST_STATIC_ASSERT ((!functor_type::computed));
0373 #ifdef _MSC_VER
0374 #pragma warning(pop)
0375 #endif
0376         typedef typename V::value_type value_type;
0377 #if BOOST_UBLAS_TYPE_CHECK
0378         vector<value_type> cv (v.size ());
0379         indexing_vector_assign<scalar_assign> (cv, v);
0380         indexing_vector_assign<F> (cv, e);
0381 #endif
0382         v.clear ();
0383         typename E::const_iterator ite (e ().begin ());
0384         typename E::const_iterator ite_end (e ().end ());
0385         while (ite != ite_end) {
0386             value_type t (*ite);
0387             if (t != value_type/*zero*/())
0388                 v.insert_element (ite.index (), t);
0389             ++ ite;
0390         }
0391 #if BOOST_UBLAS_TYPE_CHECK
0392         if (! disable_type_check<bool>::value) 
0393             BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv), 
0394                                external_logic ("external logic or bad condition of inputs"));
0395 #endif
0396     }
0397     // Sparse proxy or functional case
0398     template<template <class T1, class T2> class F, class V, class E>
0399     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0400     void vector_assign (V &v, const vector_expression<E> &e, sparse_proxy_tag) {
0401         BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
0402         typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
0403         typedef typename V::size_type size_type;
0404         typedef typename V::difference_type difference_type;
0405         typedef typename V::value_type value_type;
0406 
0407 #if BOOST_UBLAS_TYPE_CHECK
0408         vector<value_type> cv (v.size ());
0409         indexing_vector_assign<scalar_assign> (cv, v);
0410         indexing_vector_assign<F> (cv, e);
0411 #endif
0412         detail::make_conformant (v, e);
0413 
0414         typename V::iterator it (v.begin ());
0415         typename V::iterator it_end (v.end ());
0416         typename E::const_iterator ite (e ().begin ());
0417         typename E::const_iterator ite_end (e ().end ());
0418         if (it != it_end && ite != ite_end) {
0419             size_type it_index = it.index (), ite_index = ite.index ();
0420             for (;;) {
0421                 difference_type compare = it_index - ite_index;
0422                 if (compare == 0) {
0423                     functor_type::apply (*it, *ite);
0424                     ++ it, ++ ite;
0425                     if (it != it_end && ite != ite_end) {
0426                         it_index = it.index ();
0427                         ite_index = ite.index ();
0428                     } else
0429                         break;
0430                 } else if (compare < 0) {
0431 //Disabled warning C4127 because the conditional expression is constant
0432 #ifdef _MSC_VER
0433 #pragma warning(push)
0434 #pragma warning(disable: 4127)
0435 #endif
0436                     if (!functor_type::computed) {
0437 #ifdef _MSC_VER
0438 #pragma warning(pop)
0439 #endif
0440                         functor_type::apply (*it, value_type/*zero*/());
0441                         ++ it;
0442                     } else
0443                         increment (it, it_end, - compare);
0444                     if (it != it_end)
0445                         it_index = it.index ();
0446                     else
0447                         break;
0448                 } else if (compare > 0) {
0449                     increment (ite, ite_end, compare);
0450                     if (ite != ite_end)
0451                         ite_index = ite.index ();
0452                     else
0453                         break;
0454                 }
0455             }
0456         }
0457 //Disabled warning C4127 because the conditional expression is constant
0458 #ifdef _MSC_VER
0459 #pragma warning(push)
0460 #pragma warning(disable: 4127)
0461 #endif
0462         if (!functor_type::computed) {
0463 #ifdef _MSC_VER
0464 #pragma warning(pop)
0465 #endif
0466             while (it != it_end) {  // zeroing
0467                 functor_type::apply (*it, value_type/*zero*/());
0468                 ++ it;
0469             }
0470         } else {
0471             it = it_end;
0472         }
0473 #if BOOST_UBLAS_TYPE_CHECK
0474         if (! disable_type_check<bool>::value)
0475             BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv), 
0476                                external_logic ("external logic or bad condition of inputs"));
0477 #endif
0478     }
0479 
0480     // Dispatcher
0481     template<template <class T1, class T2> class F, class V, class E>
0482     BOOST_UBLAS_INLINE
0483     void vector_assign (V &v, const vector_expression<E> &e) {
0484         typedef typename vector_assign_traits<typename V::storage_category,
0485                                               F<typename V::reference, typename E::value_type>::computed,
0486                                               typename E::const_iterator::iterator_category>::storage_category storage_category;
0487         vector_assign<F> (v, e, storage_category ());
0488     }
0489 
0490     template<class SC, class RI>
0491     struct vector_swap_traits {
0492         typedef SC storage_category;
0493     };
0494 
0495     template<>
0496     struct vector_swap_traits<dense_proxy_tag, sparse_bidirectional_iterator_tag> {
0497         typedef sparse_proxy_tag storage_category;
0498     };
0499 
0500     template<>
0501     struct vector_swap_traits<packed_proxy_tag, sparse_bidirectional_iterator_tag> {
0502         typedef sparse_proxy_tag storage_category;
0503     };
0504 
0505     // Dense (proxy) case
0506     template<template <class T1, class T2> class F, class V, class E>
0507     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0508     void vector_swap (V &v, vector_expression<E> &e, dense_proxy_tag) {
0509         typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
0510         typedef typename V::difference_type difference_type;
0511         difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
0512         typename V::iterator it (v.begin ());
0513         typename E::iterator ite (e ().begin ());
0514         while (-- size >= 0)
0515             functor_type::apply (*it, *ite), ++ it, ++ ite;
0516     }
0517     // Packed (proxy) case
0518     template<template <class T1, class T2> class F, class V, class E>
0519     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0520     void vector_swap (V &v, vector_expression<E> &e, packed_proxy_tag) {
0521         typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
0522         typedef typename V::difference_type difference_type;
0523         typename V::iterator it (v.begin ());
0524         typename V::iterator it_end (v.end ());
0525         typename E::iterator ite (e ().begin ());
0526         typename E::iterator ite_end (e ().end ());
0527         difference_type it_size (it_end - it);
0528         difference_type ite_size (ite_end - ite);
0529         if (it_size > 0 && ite_size > 0) {
0530             difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
0531             if (size > 0) {
0532                 ite += size;
0533                 ite_size -= size;
0534             }
0535         }
0536         if (it_size > 0 && ite_size > 0) {
0537             difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
0538             if (size > 0)
0539                 it_size -= size;
0540         }
0541         difference_type size ((std::min) (it_size, ite_size));
0542         it_size -= size;
0543         ite_size -= size;
0544         while (-- size >= 0)
0545             functor_type::apply (*it, *ite), ++ it, ++ ite;
0546     }
0547     // Sparse proxy case
0548     template<template <class T1, class T2> class F, class V, class E>
0549     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
0550     void vector_swap (V &v, vector_expression<E> &e, sparse_proxy_tag) {
0551         BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
0552         typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
0553         typedef typename V::size_type size_type;
0554         typedef typename V::difference_type difference_type;
0555 
0556         detail::make_conformant (v, e);
0557         // FIXME should be a seperate restriction for E
0558         detail::make_conformant (e (), v);
0559 
0560         typename V::iterator it (v.begin ());
0561         typename V::iterator it_end (v.end ());
0562         typename E::iterator ite (e ().begin ());
0563         typename E::iterator ite_end (e ().end ());
0564         if (it != it_end && ite != ite_end) {
0565             size_type it_index = it.index (), ite_index = ite.index ();
0566             for (;;) {
0567                 difference_type compare = it_index - ite_index;
0568                 if (compare == 0) {
0569                     functor_type::apply (*it, *ite);
0570                     ++ it, ++ ite;
0571                     if (it != it_end && ite != ite_end) {
0572                         it_index = it.index ();
0573                         ite_index = ite.index ();
0574                     } else
0575                         break;
0576                 } else if (compare < 0) {
0577                     increment (it, it_end, - compare);
0578                     if (it != it_end)
0579                         it_index = it.index ();
0580                     else
0581                         break;
0582                 } else if (compare > 0) {
0583                     increment (ite, ite_end, compare);
0584                     if (ite != ite_end)
0585                         ite_index = ite.index ();
0586                     else
0587                         break;
0588                 }
0589             }
0590         }
0591 
0592 #if BOOST_UBLAS_TYPE_CHECK
0593         increment (ite, ite_end);
0594         increment (it, it_end);
0595 #endif
0596     }
0597 
0598     // Dispatcher
0599     template<template <class T1, class T2> class F, class V, class E>
0600     BOOST_UBLAS_INLINE
0601     void vector_swap (V &v, vector_expression<E> &e) {
0602         typedef typename vector_swap_traits<typename V::storage_category,
0603                                             typename E::const_iterator::iterator_category>::storage_category storage_category;
0604         vector_swap<F> (v, e, storage_category ());
0605     }
0606 
0607 }}}
0608 
0609 #endif