Boost.uBlas 1.49
Linear Algebra in C++: matrices, vectors and numeric algorithms

vector_assign.hpp

Go to the documentation of this file.
00001 //
00002 //  Copyright (c) 2000-2002
00003 //  Joerg Walter, Mathias Koch
00004 //
00005 //  Distributed under the Boost Software License, Version 1.0. (See
00006 //  accompanying file LICENSE_1_0.txt or copy at
00007 //  http://www.boost.org/LICENSE_1_0.txt)
00008 //
00009 //  The authors gratefully acknowledge the support of
00010 //  GeNeSys mbH & Co. KG in producing this work.
00011 //
00012 
00013 #ifndef _BOOST_UBLAS_VECTOR_ASSIGN_
00014 #define _BOOST_UBLAS_VECTOR_ASSIGN_
00015 
00016 #include <boost/numeric/ublas/functional.hpp> // scalar_assign
00017 // Required for make_conformant storage
00018 #include <vector>
00019 
00020 // Iterators based on ideas of Jeremy Siek
00021 
00022 namespace boost { namespace numeric { namespace ublas {
00023 namespace detail {
00024 
00025     // Weak equality check - useful to compare equality two arbitary vector expression results.
00026     // Since the actual expressions are unknown, we check for and arbitary error bound
00027     // on the relative error.
00028     // For a linear expression the infinity norm makes sense as we do not know how the elements will be
00029     // combined in the expression. False positive results are inevitable for arbirary expressions!
00030     template<class E1, class E2, class S>
00031     BOOST_UBLAS_INLINE
00032     bool equals (const vector_expression<E1> &e1, const vector_expression<E2> &e2, S epsilon, S min_norm) {
00033         return norm_inf (e1 - e2) < epsilon *
00034                std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);
00035     }
00036 
00037     template<class E1, class E2>
00038     BOOST_UBLAS_INLINE
00039     bool expression_type_check (const vector_expression<E1> &e1, const vector_expression<E2> &e2) {
00040         typedef typename type_traits<typename promote_traits<typename E1::value_type,
00041                                      typename E2::value_type>::promote_type>::real_type real_type;
00042         return equals (e1, e2, BOOST_UBLAS_TYPE_CHECK_EPSILON, BOOST_UBLAS_TYPE_CHECK_MIN);
00043     }
00044 
00045 
00046     // Make sparse proxies conformant
00047     template<class V, class E>
00048     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00049     void make_conformant (V &v, const vector_expression<E> &e) {
00050         BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
00051         typedef typename V::size_type size_type;
00052         typedef typename V::difference_type difference_type;
00053         typedef typename V::value_type value_type;
00054         // FIXME unbounded_array with push_back maybe better
00055         std::vector<size_type> index;
00056         typename V::iterator it (v.begin ());
00057         typename V::iterator it_end (v.end ());
00058         typename E::const_iterator ite (e ().begin ());
00059         typename E::const_iterator ite_end (e ().end ());
00060         if (it != it_end && ite != ite_end) {
00061             size_type it_index = it.index (), ite_index = ite.index ();
00062             while (true) {
00063                 difference_type compare = it_index - ite_index;
00064                 if (compare == 0) {
00065                     ++ it, ++ ite;
00066                     if (it != it_end && ite != ite_end) {
00067                         it_index = it.index ();
00068                         ite_index = ite.index ();
00069                     } else
00070                         break;
00071                 } else if (compare < 0) {
00072                     increment (it, it_end, - compare);
00073                     if (it != it_end)
00074                         it_index = it.index ();
00075                     else
00076                         break;
00077                 } else if (compare > 0) {
00078                     if (*ite != value_type/*zero*/())
00079                         index.push_back (ite.index ());
00080                     ++ ite;
00081                     if (ite != ite_end)
00082                         ite_index = ite.index ();
00083                     else
00084                         break;
00085                 }
00086             }
00087         }
00088 
00089         while (ite != ite_end) {
00090             if (*ite != value_type/*zero*/())
00091                 index.push_back (ite.index ());
00092             ++ ite;
00093         }
00094         for (size_type k = 0; k < index.size (); ++ k)
00095             v (index [k]) = value_type/*zero*/();
00096     }
00097 
00098 }//namespace detail
00099 
00100 
00101     // Explicitly iterating
00102     template<template <class T1, class T2> class F, class V, class T>
00103     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00104     void iterating_vector_assign_scalar (V &v, const T &t) {
00105         typedef F<typename V::iterator::reference, T> functor_type;
00106         typedef typename V::difference_type difference_type;
00107         difference_type size (v.size ());
00108         typename V::iterator it (v.begin ());
00109         BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
00110 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
00111         while (-- size >= 0)
00112             functor_type::apply (*it, t), ++ it;
00113 #else
00114         DD (size, 4, r, (functor_type::apply (*it, t), ++ it));
00115 #endif
00116     }
00117     // Explicitly case
00118     template<template <class T1, class T2> class F, class V, class T>
00119     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00120     void indexing_vector_assign_scalar (V &v, const T &t) {
00121         typedef F<typename V::reference, T> functor_type;
00122         typedef typename V::size_type size_type;
00123         size_type size (v.size ());
00124 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
00125         for (size_type i = 0; i < size; ++ i)
00126             functor_type::apply (v (i), t);
00127 #else
00128         size_type i (0);
00129         DD (size, 4, r, (functor_type::apply (v (i), t), ++ i));
00130 #endif
00131     }
00132 
00133     // Dense (proxy) case
00134     template<template <class T1, class T2> class F, class V, class T>
00135     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00136     void vector_assign_scalar (V &v, const T &t, dense_proxy_tag) {
00137 #ifdef BOOST_UBLAS_USE_INDEXING
00138         indexing_vector_assign_scalar<F> (v, t);
00139 #elif BOOST_UBLAS_USE_ITERATING
00140         iterating_vector_assign_scalar<F> (v, t);
00141 #else
00142         typedef typename V::size_type size_type;
00143         size_type size (v.size ());
00144         if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
00145             iterating_vector_assign_scalar<F> (v, t);
00146         else
00147             indexing_vector_assign_scalar<F> (v, t);
00148 #endif
00149     }
00150     // Packed (proxy) case
00151     template<template <class T1, class T2> class F, class V, class T>
00152     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00153     void vector_assign_scalar (V &v, const T &t, packed_proxy_tag) {
00154         typedef F<typename V::iterator::reference, T> functor_type;
00155         typedef typename V::difference_type difference_type;
00156         typename V::iterator it (v.begin ());
00157         difference_type size (v.end () - it);
00158         while (-- size >= 0)
00159             functor_type::apply (*it, t), ++ it;
00160     }
00161     // Sparse (proxy) case
00162     template<template <class T1, class T2> class F, class V, class T>
00163     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00164     void vector_assign_scalar (V &v, const T &t, sparse_proxy_tag) {
00165         typedef F<typename V::iterator::reference, T> functor_type;
00166         typename V::iterator it (v.begin ());
00167         typename V::iterator it_end (v.end ());
00168         while (it != it_end)
00169             functor_type::apply (*it, t), ++ it;
00170     }
00171 
00172     // Dispatcher
00173     template<template <class T1, class T2> class F, class V, class T>
00174     BOOST_UBLAS_INLINE
00175     void vector_assign_scalar (V &v, const T &t) {
00176         typedef typename V::storage_category storage_category;
00177         vector_assign_scalar<F> (v, t, storage_category ());
00178     }
00179 
00180     template<class SC, bool COMPUTED, class RI>
00181     struct vector_assign_traits {
00182         typedef SC storage_category;
00183     };
00184 
00185     template<bool COMPUTED>
00186     struct vector_assign_traits<dense_tag, COMPUTED, packed_random_access_iterator_tag> {
00187         typedef packed_tag storage_category;
00188     };
00189     template<>
00190     struct vector_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag> {
00191         typedef sparse_tag storage_category;
00192     };
00193     template<>
00194     struct vector_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag> {
00195         typedef sparse_proxy_tag storage_category;
00196     };
00197 
00198     template<bool COMPUTED>
00199     struct vector_assign_traits<dense_proxy_tag, COMPUTED, packed_random_access_iterator_tag> {
00200         typedef packed_proxy_tag storage_category;
00201     };
00202     template<>
00203     struct vector_assign_traits<dense_proxy_tag, false, sparse_bidirectional_iterator_tag> {
00204         typedef sparse_proxy_tag storage_category;
00205     };
00206     template<>
00207     struct vector_assign_traits<dense_proxy_tag, true, sparse_bidirectional_iterator_tag> {
00208         typedef sparse_proxy_tag storage_category;
00209     };
00210 
00211     template<>
00212     struct vector_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag> {
00213         typedef sparse_tag storage_category;
00214     };
00215     template<>
00216     struct vector_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag> {
00217         typedef sparse_proxy_tag storage_category;
00218     };
00219 
00220     template<bool COMPUTED>
00221     struct vector_assign_traits<packed_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag> {
00222         typedef sparse_proxy_tag storage_category;
00223     };
00224 
00225     template<>
00226     struct vector_assign_traits<sparse_tag, true, dense_random_access_iterator_tag> {
00227         typedef sparse_proxy_tag storage_category;
00228     };
00229     template<>
00230     struct vector_assign_traits<sparse_tag, true, packed_random_access_iterator_tag> {
00231         typedef sparse_proxy_tag storage_category;
00232     };
00233     template<>
00234     struct vector_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag> {
00235         typedef sparse_proxy_tag storage_category;
00236     };
00237 
00238     // Explicitly iterating
00239     template<template <class T1, class T2> class F, class V, class E>
00240     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00241     void iterating_vector_assign (V &v, const vector_expression<E> &e) {
00242         typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
00243         typedef typename V::difference_type difference_type;
00244         difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
00245         typename V::iterator it (v.begin ());
00246         BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
00247         typename E::const_iterator ite (e ().begin ());
00248         BOOST_UBLAS_CHECK (e ().end () - ite == size, bad_size ());
00249 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
00250         while (-- size >= 0)
00251             functor_type::apply (*it, *ite), ++ it, ++ ite;
00252 #else
00253         DD (size, 2, r, (functor_type::apply (*it, *ite), ++ it, ++ ite));
00254 #endif
00255     }
00256     // Explicitly indexing
00257     template<template <class T1, class T2> class F, class V, class E>
00258     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00259     void indexing_vector_assign (V &v, const vector_expression<E> &e) {
00260         typedef F<typename V::reference, typename E::value_type> functor_type;
00261         typedef typename V::size_type size_type;
00262         size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
00263 #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
00264         for (size_type i = 0; i < size; ++ i)
00265             functor_type::apply (v (i), e () (i));
00266 #else
00267         size_type i (0);
00268         DD (size, 2, r, (functor_type::apply (v (i), e () (i)), ++ i));
00269 #endif
00270     }
00271 
00272     // Dense (proxy) case
00273     template<template <class T1, class T2> class F, class V, class E>
00274     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00275     void vector_assign (V &v, const vector_expression<E> &e, dense_proxy_tag) {
00276 #ifdef BOOST_UBLAS_USE_INDEXING
00277         indexing_vector_assign<F> (v, e);
00278 #elif BOOST_UBLAS_USE_ITERATING
00279         iterating_vector_assign<F> (v, e);
00280 #else
00281         typedef typename V::size_type size_type;
00282         size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
00283         if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
00284             iterating_vector_assign<F> (v, e);
00285         else
00286             indexing_vector_assign<F> (v, e);
00287 #endif
00288     }
00289     // Packed (proxy) case
00290     template<template <class T1, class T2> class F, class V, class E>
00291     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00292     void vector_assign (V &v, const vector_expression<E> &e, packed_proxy_tag) {
00293         BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
00294         typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
00295         typedef typename V::difference_type difference_type;
00296         typedef typename V::value_type value_type;
00297 #if BOOST_UBLAS_TYPE_CHECK
00298         vector<value_type> cv (v.size ());
00299         indexing_vector_assign<scalar_assign> (cv, v);
00300         indexing_vector_assign<F> (cv, e);
00301 #endif
00302         typename V::iterator it (v.begin ());
00303         typename V::iterator it_end (v.end ());
00304         typename E::const_iterator ite (e ().begin ());
00305         typename E::const_iterator ite_end (e ().end ());
00306         difference_type it_size (it_end - it);
00307         difference_type ite_size (ite_end - ite);
00308         if (it_size > 0 && ite_size > 0) {
00309             difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
00310             if (size > 0) {
00311                 ite += size;
00312                 ite_size -= size;
00313             }
00314         }
00315         if (it_size > 0 && ite_size > 0) {
00316             difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
00317             if (size > 0) {
00318                 it_size -= size;
00319                 if (!functor_type::computed) {
00320                     while (-- size >= 0)    // zeroing
00321                         functor_type::apply (*it, value_type/*zero*/()), ++ it;
00322                 } else {
00323                     it += size;
00324                 }
00325             }
00326         }
00327         difference_type size ((std::min) (it_size, ite_size));
00328         it_size -= size;
00329         ite_size -= size;
00330         while (-- size >= 0)
00331             functor_type::apply (*it, *ite), ++ it, ++ ite;
00332         size = it_size;
00333         if (!functor_type::computed) {
00334             while (-- size >= 0)    // zeroing
00335                 functor_type::apply (*it, value_type/*zero*/()), ++ it;
00336         } else {
00337             it += size;
00338         }
00339 #if BOOST_UBLAS_TYPE_CHECK
00340         if (! disable_type_check<bool>::value) 
00341             BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv), 
00342                                external_logic ("external logic or bad condition of inputs"));
00343 #endif
00344     }
00345     // Sparse case
00346     template<template <class T1, class T2> class F, class V, class E>
00347     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00348     void vector_assign (V &v, const vector_expression<E> &e, sparse_tag) {
00349         BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
00350         typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
00351         BOOST_STATIC_ASSERT ((!functor_type::computed));
00352         typedef typename V::value_type value_type;
00353 #if BOOST_UBLAS_TYPE_CHECK
00354         vector<value_type> cv (v.size ());
00355         indexing_vector_assign<scalar_assign> (cv, v);
00356         indexing_vector_assign<F> (cv, e);
00357 #endif
00358         v.clear ();
00359         typename E::const_iterator ite (e ().begin ());
00360         typename E::const_iterator ite_end (e ().end ());
00361         while (ite != ite_end) {
00362             value_type t (*ite);
00363             if (t != value_type/*zero*/())
00364                 v.insert_element (ite.index (), t);
00365             ++ ite;
00366         }
00367 #if BOOST_UBLAS_TYPE_CHECK
00368         if (! disable_type_check<bool>::value) 
00369             BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv), 
00370                                external_logic ("external logic or bad condition of inputs"));
00371 #endif
00372     }
00373     // Sparse proxy or functional case
00374     template<template <class T1, class T2> class F, class V, class E>
00375     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00376     void vector_assign (V &v, const vector_expression<E> &e, sparse_proxy_tag) {
00377         BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
00378         typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
00379         typedef typename V::size_type size_type;
00380         typedef typename V::difference_type difference_type;
00381         typedef typename V::value_type value_type;
00382         typedef typename V::reference reference;
00383 #if BOOST_UBLAS_TYPE_CHECK
00384         vector<value_type> cv (v.size ());
00385         indexing_vector_assign<scalar_assign> (cv, v);
00386         indexing_vector_assign<F> (cv, e);
00387 #endif
00388         detail::make_conformant (v, e);
00389 
00390         typename V::iterator it (v.begin ());
00391         typename V::iterator it_end (v.end ());
00392         typename E::const_iterator ite (e ().begin ());
00393         typename E::const_iterator ite_end (e ().end ());
00394         if (it != it_end && ite != ite_end) {
00395             size_type it_index = it.index (), ite_index = ite.index ();
00396             while (true) {
00397                 difference_type compare = it_index - ite_index;
00398                 if (compare == 0) {
00399                     functor_type::apply (*it, *ite);
00400                     ++ it, ++ ite;
00401                     if (it != it_end && ite != ite_end) {
00402                         it_index = it.index ();
00403                         ite_index = ite.index ();
00404                     } else
00405                         break;
00406                 } else if (compare < 0) {
00407                     if (!functor_type::computed) {
00408                         functor_type::apply (*it, value_type/*zero*/());
00409                         ++ it;
00410                     } else
00411                         increment (it, it_end, - compare);
00412                     if (it != it_end)
00413                         it_index = it.index ();
00414                     else
00415                         break;
00416                 } else if (compare > 0) {
00417                     increment (ite, ite_end, compare);
00418                     if (ite != ite_end)
00419                         ite_index = ite.index ();
00420                     else
00421                         break;
00422                 }
00423             }
00424         }
00425 
00426         if (!functor_type::computed) {
00427             while (it != it_end) {  // zeroing
00428                 functor_type::apply (*it, value_type/*zero*/());
00429                 ++ it;
00430             }
00431         } else {
00432             it = it_end;
00433         }
00434 #if BOOST_UBLAS_TYPE_CHECK
00435         if (! disable_type_check<bool>::value)
00436             BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv), 
00437                                external_logic ("external logic or bad condition of inputs"));
00438 #endif
00439     }
00440 
00441     // Dispatcher
00442     template<template <class T1, class T2> class F, class V, class E>
00443     BOOST_UBLAS_INLINE
00444     void vector_assign (V &v, const vector_expression<E> &e) {
00445         typedef typename vector_assign_traits<typename V::storage_category,
00446                                               F<typename V::reference, typename E::value_type>::computed,
00447                                               typename E::const_iterator::iterator_category>::storage_category storage_category;
00448         vector_assign<F> (v, e, storage_category ());
00449     }
00450 
00451     template<class SC, class RI>
00452     struct vector_swap_traits {
00453         typedef SC storage_category;
00454     };
00455 
00456     template<>
00457     struct vector_swap_traits<dense_proxy_tag, sparse_bidirectional_iterator_tag> {
00458         typedef sparse_proxy_tag storage_category;
00459     };
00460 
00461     template<>
00462     struct vector_swap_traits<packed_proxy_tag, sparse_bidirectional_iterator_tag> {
00463         typedef sparse_proxy_tag storage_category;
00464     };
00465 
00466     // Dense (proxy) case
00467     template<template <class T1, class T2> class F, class V, class E>
00468     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00469     void vector_swap (V &v, vector_expression<E> &e, dense_proxy_tag) {
00470         typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
00471         typedef typename V::difference_type difference_type;
00472         difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
00473         typename V::iterator it (v.begin ());
00474         typename E::iterator ite (e ().begin ());
00475         while (-- size >= 0)
00476             functor_type::apply (*it, *ite), ++ it, ++ ite;
00477     }
00478     // Packed (proxy) case
00479     template<template <class T1, class T2> class F, class V, class E>
00480     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00481     void vector_swap (V &v, vector_expression<E> &e, packed_proxy_tag) {
00482         typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
00483         typedef typename V::difference_type difference_type;
00484         typename V::iterator it (v.begin ());
00485         typename V::iterator it_end (v.end ());
00486         typename E::iterator ite (e ().begin ());
00487         typename E::iterator ite_end (e ().end ());
00488         difference_type it_size (it_end - it);
00489         difference_type ite_size (ite_end - ite);
00490         if (it_size > 0 && ite_size > 0) {
00491             difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
00492             if (size > 0) {
00493                 ite += size;
00494                 ite_size -= size;
00495             }
00496         }
00497         if (it_size > 0 && ite_size > 0) {
00498             difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
00499             if (size > 0)
00500                 it_size -= size;
00501         }
00502         difference_type size ((std::min) (it_size, ite_size));
00503         it_size -= size;
00504         ite_size -= size;
00505         while (-- size >= 0)
00506             functor_type::apply (*it, *ite), ++ it, ++ ite;
00507     }
00508     // Sparse proxy case
00509     template<template <class T1, class T2> class F, class V, class E>
00510     // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
00511     void vector_swap (V &v, vector_expression<E> &e, sparse_proxy_tag) {
00512         BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
00513         typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
00514         typedef typename V::size_type size_type;
00515         typedef typename V::difference_type difference_type;
00516         typedef typename V::value_type value_type;
00517 
00518         detail::make_conformant (v, e);
00519         // FIXME should be a seperate restriction for E
00520         detail::make_conformant (e (), v);
00521 
00522         typename V::iterator it (v.begin ());
00523         typename V::iterator it_end (v.end ());
00524         typename E::iterator ite (e ().begin ());
00525         typename E::iterator ite_end (e ().end ());
00526         if (it != it_end && ite != ite_end) {
00527             size_type it_index = it.index (), ite_index = ite.index ();
00528             while (true) {
00529                 difference_type compare = it_index - ite_index;
00530                 if (compare == 0) {
00531                     functor_type::apply (*it, *ite);
00532                     ++ it, ++ ite;
00533                     if (it != it_end && ite != ite_end) {
00534                         it_index = it.index ();
00535                         ite_index = ite.index ();
00536                     } else
00537                         break;
00538                 } else if (compare < 0) {
00539                     increment (it, it_end, - compare);
00540                     if (it != it_end)
00541                         it_index = it.index ();
00542                     else
00543                         break;
00544                 } else if (compare > 0) {
00545                     increment (ite, ite_end, compare);
00546                     if (ite != ite_end)
00547                         ite_index = ite.index ();
00548                     else
00549                         break;
00550                 }
00551             }
00552         }
00553 
00554 #if BOOST_UBLAS_TYPE_CHECK
00555         increment (ite, ite_end);
00556         increment (it, it_end);
00557 #endif
00558     }
00559 
00560     // Dispatcher
00561     template<template <class T1, class T2> class F, class V, class E>
00562     BOOST_UBLAS_INLINE
00563     void vector_swap (V &v, vector_expression<E> &e) {
00564         typedef typename vector_swap_traits<typename V::storage_category,
00565                                             typename E::const_iterator::iterator_category>::storage_category storage_category;
00566         vector_swap<F> (v, e, storage_category ());
00567     }
00568 
00569 }}}
00570 
00571 #endif