![]() |
Boost.uBlas 1.49
Linear Algebra in C++: matrices, vectors and numeric algorithms
|
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