vector_assign.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. //
  2. // Copyright (c) 2000-2002
  3. // Joerg Walter, Mathias Koch
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // The authors gratefully acknowledge the support of
  10. // GeNeSys mbH & Co. KG in producing this work.
  11. //
  12. #ifndef _BOOST_UBLAS_VECTOR_ASSIGN_
  13. #define _BOOST_UBLAS_VECTOR_ASSIGN_
  14. #include <boost/numeric/ublas/functional.hpp> // scalar_assign
  15. // Required for make_conformant storage
  16. #include <vector>
  17. // Iterators based on ideas of Jeremy Siek
  18. namespace boost { namespace numeric { namespace ublas {
  19. namespace detail {
  20. // Weak equality check - useful to compare equality two arbitary vector expression results.
  21. // Since the actual expressions are unknown, we check for and arbitary error bound
  22. // on the relative error.
  23. // For a linear expression the infinity norm makes sense as we do not know how the elements will be
  24. // combined in the expression. False positive results are inevitable for arbirary expressions!
  25. template<class E1, class E2, class S>
  26. BOOST_UBLAS_INLINE
  27. bool equals (const vector_expression<E1> &e1, const vector_expression<E2> &e2, S epsilon, S min_norm) {
  28. return norm_inf (e1 - e2) <= epsilon *
  29. std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);
  30. }
  31. template<class E1, class E2>
  32. BOOST_UBLAS_INLINE
  33. bool expression_type_check (const vector_expression<E1> &e1, const vector_expression<E2> &e2) {
  34. typedef typename type_traits<typename promote_traits<typename E1::value_type,
  35. typename E2::value_type>::promote_type>::real_type real_type;
  36. return equals (e1, e2, BOOST_UBLAS_TYPE_CHECK_EPSILON, BOOST_UBLAS_TYPE_CHECK_MIN);
  37. }
  38. // Make sparse proxies conformant
  39. template<class V, class E>
  40. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  41. void make_conformant (V &v, const vector_expression<E> &e) {
  42. BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
  43. typedef typename V::size_type size_type;
  44. typedef typename V::difference_type difference_type;
  45. typedef typename V::value_type value_type;
  46. // FIXME unbounded_array with push_back maybe better
  47. std::vector<size_type> index;
  48. typename V::iterator it (v.begin ());
  49. typename V::iterator it_end (v.end ());
  50. typename E::const_iterator ite (e ().begin ());
  51. typename E::const_iterator ite_end (e ().end ());
  52. if (it != it_end && ite != ite_end) {
  53. size_type it_index = it.index (), ite_index = ite.index ();
  54. for (;;) {
  55. difference_type compare = it_index - ite_index;
  56. if (compare == 0) {
  57. ++ it, ++ ite;
  58. if (it != it_end && ite != ite_end) {
  59. it_index = it.index ();
  60. ite_index = ite.index ();
  61. } else
  62. break;
  63. } else if (compare < 0) {
  64. increment (it, it_end, - compare);
  65. if (it != it_end)
  66. it_index = it.index ();
  67. else
  68. break;
  69. } else if (compare > 0) {
  70. if (*ite != value_type/*zero*/())
  71. index.push_back (ite.index ());
  72. ++ ite;
  73. if (ite != ite_end)
  74. ite_index = ite.index ();
  75. else
  76. break;
  77. }
  78. }
  79. }
  80. while (ite != ite_end) {
  81. if (*ite != value_type/*zero*/())
  82. index.push_back (ite.index ());
  83. ++ ite;
  84. }
  85. for (size_type k = 0; k < index.size (); ++ k)
  86. v (index [k]) = value_type/*zero*/();
  87. }
  88. }//namespace detail
  89. // Explicitly iterating
  90. template<template <class T1, class T2> class F, class V, class T>
  91. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  92. void iterating_vector_assign_scalar (V &v, const T &t) {
  93. typedef F<typename V::iterator::reference, T> functor_type;
  94. typedef typename V::difference_type difference_type;
  95. difference_type size (v.size ());
  96. typename V::iterator it (v.begin ());
  97. BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
  98. #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
  99. while (-- size >= 0)
  100. functor_type::apply (*it, t), ++ it;
  101. #else
  102. DD (size, 4, r, (functor_type::apply (*it, t), ++ it));
  103. #endif
  104. }
  105. // Explicitly case
  106. template<template <class T1, class T2> class F, class V, class T>
  107. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  108. void indexing_vector_assign_scalar (V &v, const T &t) {
  109. typedef F<typename V::reference, T> functor_type;
  110. typedef typename V::size_type size_type;
  111. size_type size (v.size ());
  112. #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
  113. for (size_type i = 0; i < size; ++ i)
  114. functor_type::apply (v (i), t);
  115. #else
  116. size_type i (0);
  117. DD (size, 4, r, (functor_type::apply (v (i), t), ++ i));
  118. #endif
  119. }
  120. // Dense (proxy) case
  121. template<template <class T1, class T2> class F, class V, class T>
  122. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  123. void vector_assign_scalar (V &v, const T &t, dense_proxy_tag) {
  124. #ifdef BOOST_UBLAS_USE_INDEXING
  125. indexing_vector_assign_scalar<F> (v, t);
  126. #elif BOOST_UBLAS_USE_ITERATING
  127. iterating_vector_assign_scalar<F> (v, t);
  128. #else
  129. typedef typename V::size_type size_type;
  130. size_type size (v.size ());
  131. if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
  132. iterating_vector_assign_scalar<F> (v, t);
  133. else
  134. indexing_vector_assign_scalar<F> (v, t);
  135. #endif
  136. }
  137. // Packed (proxy) case
  138. template<template <class T1, class T2> class F, class V, class T>
  139. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  140. void vector_assign_scalar (V &v, const T &t, packed_proxy_tag) {
  141. typedef F<typename V::iterator::reference, T> functor_type;
  142. typedef typename V::difference_type difference_type;
  143. typename V::iterator it (v.begin ());
  144. difference_type size (v.end () - it);
  145. while (-- size >= 0)
  146. functor_type::apply (*it, t), ++ it;
  147. }
  148. // Sparse (proxy) case
  149. template<template <class T1, class T2> class F, class V, class T>
  150. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  151. void vector_assign_scalar (V &v, const T &t, sparse_proxy_tag) {
  152. typedef F<typename V::iterator::reference, T> functor_type;
  153. typename V::iterator it (v.begin ());
  154. typename V::iterator it_end (v.end ());
  155. while (it != it_end)
  156. functor_type::apply (*it, t), ++ it;
  157. }
  158. // Dispatcher
  159. template<template <class T1, class T2> class F, class V, class T>
  160. BOOST_UBLAS_INLINE
  161. void vector_assign_scalar (V &v, const T &t) {
  162. typedef typename V::storage_category storage_category;
  163. vector_assign_scalar<F> (v, t, storage_category ());
  164. }
  165. template<class SC, bool COMPUTED, class RI>
  166. struct vector_assign_traits {
  167. typedef SC storage_category;
  168. };
  169. template<bool COMPUTED>
  170. struct vector_assign_traits<dense_tag, COMPUTED, packed_random_access_iterator_tag> {
  171. typedef packed_tag storage_category;
  172. };
  173. template<>
  174. struct vector_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag> {
  175. typedef sparse_tag storage_category;
  176. };
  177. template<>
  178. struct vector_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag> {
  179. typedef sparse_proxy_tag storage_category;
  180. };
  181. template<bool COMPUTED>
  182. struct vector_assign_traits<dense_proxy_tag, COMPUTED, packed_random_access_iterator_tag> {
  183. typedef packed_proxy_tag storage_category;
  184. };
  185. template<>
  186. struct vector_assign_traits<dense_proxy_tag, false, sparse_bidirectional_iterator_tag> {
  187. typedef sparse_proxy_tag storage_category;
  188. };
  189. template<>
  190. struct vector_assign_traits<dense_proxy_tag, true, sparse_bidirectional_iterator_tag> {
  191. typedef sparse_proxy_tag storage_category;
  192. };
  193. template<>
  194. struct vector_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag> {
  195. typedef sparse_tag storage_category;
  196. };
  197. template<>
  198. struct vector_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag> {
  199. typedef sparse_proxy_tag storage_category;
  200. };
  201. template<bool COMPUTED>
  202. struct vector_assign_traits<packed_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag> {
  203. typedef sparse_proxy_tag storage_category;
  204. };
  205. template<>
  206. struct vector_assign_traits<sparse_tag, true, dense_random_access_iterator_tag> {
  207. typedef sparse_proxy_tag storage_category;
  208. };
  209. template<>
  210. struct vector_assign_traits<sparse_tag, true, packed_random_access_iterator_tag> {
  211. typedef sparse_proxy_tag storage_category;
  212. };
  213. template<>
  214. struct vector_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag> {
  215. typedef sparse_proxy_tag storage_category;
  216. };
  217. // Explicitly iterating
  218. template<template <class T1, class T2> class F, class V, class E>
  219. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  220. void iterating_vector_assign (V &v, const vector_expression<E> &e) {
  221. typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
  222. typedef typename V::difference_type difference_type;
  223. difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
  224. typename V::iterator it (v.begin ());
  225. BOOST_UBLAS_CHECK (v.end () - it == size, bad_size ());
  226. typename E::const_iterator ite (e ().begin ());
  227. BOOST_UBLAS_CHECK (e ().end () - ite == size, bad_size ());
  228. #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
  229. while (-- size >= 0)
  230. functor_type::apply (*it, *ite), ++ it, ++ ite;
  231. #else
  232. DD (size, 2, r, (functor_type::apply (*it, *ite), ++ it, ++ ite));
  233. #endif
  234. }
  235. // Explicitly indexing
  236. template<template <class T1, class T2> class F, class V, class E>
  237. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  238. void indexing_vector_assign (V &v, const vector_expression<E> &e) {
  239. typedef F<typename V::reference, typename E::value_type> functor_type;
  240. typedef typename V::size_type size_type;
  241. size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
  242. #ifndef BOOST_UBLAS_USE_DUFF_DEVICE
  243. for (size_type i = 0; i < size; ++ i)
  244. functor_type::apply (v (i), e () (i));
  245. #else
  246. size_type i (0);
  247. DD (size, 2, r, (functor_type::apply (v (i), e () (i)), ++ i));
  248. #endif
  249. }
  250. // Dense (proxy) case
  251. template<template <class T1, class T2> class F, class V, class E>
  252. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  253. void vector_assign (V &v, const vector_expression<E> &e, dense_proxy_tag) {
  254. #ifdef BOOST_UBLAS_USE_INDEXING
  255. indexing_vector_assign<F> (v, e);
  256. #elif BOOST_UBLAS_USE_ITERATING
  257. iterating_vector_assign<F> (v, e);
  258. #else
  259. typedef typename V::size_type size_type;
  260. size_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
  261. if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
  262. iterating_vector_assign<F> (v, e);
  263. else
  264. indexing_vector_assign<F> (v, e);
  265. #endif
  266. }
  267. // Packed (proxy) case
  268. template<template <class T1, class T2> class F, class V, class E>
  269. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  270. void vector_assign (V &v, const vector_expression<E> &e, packed_proxy_tag) {
  271. BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
  272. typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
  273. typedef typename V::difference_type difference_type;
  274. typedef typename V::value_type value_type;
  275. #if BOOST_UBLAS_TYPE_CHECK
  276. vector<value_type> cv (v.size ());
  277. indexing_vector_assign<scalar_assign> (cv, v);
  278. indexing_vector_assign<F> (cv, e);
  279. #endif
  280. typename V::iterator it (v.begin ());
  281. typename V::iterator it_end (v.end ());
  282. typename E::const_iterator ite (e ().begin ());
  283. typename E::const_iterator ite_end (e ().end ());
  284. difference_type it_size (it_end - it);
  285. difference_type ite_size (ite_end - ite);
  286. if (it_size > 0 && ite_size > 0) {
  287. difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
  288. if (size > 0) {
  289. ite += size;
  290. ite_size -= size;
  291. }
  292. }
  293. if (it_size > 0 && ite_size > 0) {
  294. difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
  295. if (size > 0) {
  296. it_size -= size;
  297. //Disabled warning C4127 because the conditional expression is constant
  298. #ifdef _MSC_VER
  299. #pragma warning(push)
  300. #pragma warning(disable: 4127)
  301. #endif
  302. if (!functor_type::computed) {
  303. #ifdef _MSC_VER
  304. #pragma warning(pop)
  305. #endif
  306. while (-- size >= 0) // zeroing
  307. functor_type::apply (*it, value_type/*zero*/()), ++ it;
  308. } else {
  309. it += size;
  310. }
  311. }
  312. }
  313. difference_type size ((std::min) (it_size, ite_size));
  314. it_size -= size;
  315. ite_size -= size;
  316. while (-- size >= 0)
  317. functor_type::apply (*it, *ite), ++ it, ++ ite;
  318. size = it_size;
  319. //Disabled warning C4127 because the conditional expression is constant
  320. #ifdef _MSC_VER
  321. #pragma warning(push)
  322. #pragma warning(disable: 4127)
  323. #endif
  324. if (!functor_type::computed) {
  325. #ifdef _MSC_VER
  326. #pragma warning(pop)
  327. #endif
  328. while (-- size >= 0) // zeroing
  329. functor_type::apply (*it, value_type/*zero*/()), ++ it;
  330. } else {
  331. it += size;
  332. }
  333. #if BOOST_UBLAS_TYPE_CHECK
  334. if (! disable_type_check<bool>::value)
  335. BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
  336. external_logic ("external logic or bad condition of inputs"));
  337. #endif
  338. }
  339. // Sparse case
  340. template<template <class T1, class T2> class F, class V, class E>
  341. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  342. void vector_assign (V &v, const vector_expression<E> &e, sparse_tag) {
  343. BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
  344. typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
  345. //Disabled warning C4127 because the conditional expression is constant
  346. #ifdef _MSC_VER
  347. #pragma warning(push)
  348. #pragma warning(disable: 4127)
  349. #endif
  350. BOOST_STATIC_ASSERT ((!functor_type::computed));
  351. #ifdef _MSC_VER
  352. #pragma warning(pop)
  353. #endif
  354. typedef typename V::value_type value_type;
  355. #if BOOST_UBLAS_TYPE_CHECK
  356. vector<value_type> cv (v.size ());
  357. indexing_vector_assign<scalar_assign> (cv, v);
  358. indexing_vector_assign<F> (cv, e);
  359. #endif
  360. v.clear ();
  361. typename E::const_iterator ite (e ().begin ());
  362. typename E::const_iterator ite_end (e ().end ());
  363. while (ite != ite_end) {
  364. value_type t (*ite);
  365. if (t != value_type/*zero*/())
  366. v.insert_element (ite.index (), t);
  367. ++ ite;
  368. }
  369. #if BOOST_UBLAS_TYPE_CHECK
  370. if (! disable_type_check<bool>::value)
  371. BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
  372. external_logic ("external logic or bad condition of inputs"));
  373. #endif
  374. }
  375. // Sparse proxy or functional case
  376. template<template <class T1, class T2> class F, class V, class E>
  377. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  378. void vector_assign (V &v, const vector_expression<E> &e, sparse_proxy_tag) {
  379. BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
  380. typedef F<typename V::iterator::reference, typename E::value_type> functor_type;
  381. typedef typename V::size_type size_type;
  382. typedef typename V::difference_type difference_type;
  383. typedef typename V::value_type value_type;
  384. #if BOOST_UBLAS_TYPE_CHECK
  385. vector<value_type> cv (v.size ());
  386. indexing_vector_assign<scalar_assign> (cv, v);
  387. indexing_vector_assign<F> (cv, e);
  388. #endif
  389. detail::make_conformant (v, e);
  390. typename V::iterator it (v.begin ());
  391. typename V::iterator it_end (v.end ());
  392. typename E::const_iterator ite (e ().begin ());
  393. typename E::const_iterator ite_end (e ().end ());
  394. if (it != it_end && ite != ite_end) {
  395. size_type it_index = it.index (), ite_index = ite.index ();
  396. for (;;) {
  397. difference_type compare = it_index - ite_index;
  398. if (compare == 0) {
  399. functor_type::apply (*it, *ite);
  400. ++ it, ++ ite;
  401. if (it != it_end && ite != ite_end) {
  402. it_index = it.index ();
  403. ite_index = ite.index ();
  404. } else
  405. break;
  406. } else if (compare < 0) {
  407. //Disabled warning C4127 because the conditional expression is constant
  408. #ifdef _MSC_VER
  409. #pragma warning(push)
  410. #pragma warning(disable: 4127)
  411. #endif
  412. if (!functor_type::computed) {
  413. #ifdef _MSC_VER
  414. #pragma warning(pop)
  415. #endif
  416. functor_type::apply (*it, value_type/*zero*/());
  417. ++ it;
  418. } else
  419. increment (it, it_end, - compare);
  420. if (it != it_end)
  421. it_index = it.index ();
  422. else
  423. break;
  424. } else if (compare > 0) {
  425. increment (ite, ite_end, compare);
  426. if (ite != ite_end)
  427. ite_index = ite.index ();
  428. else
  429. break;
  430. }
  431. }
  432. }
  433. //Disabled warning C4127 because the conditional expression is constant
  434. #ifdef _MSC_VER
  435. #pragma warning(push)
  436. #pragma warning(disable: 4127)
  437. #endif
  438. if (!functor_type::computed) {
  439. #ifdef _MSC_VER
  440. #pragma warning(pop)
  441. #endif
  442. while (it != it_end) { // zeroing
  443. functor_type::apply (*it, value_type/*zero*/());
  444. ++ it;
  445. }
  446. } else {
  447. it = it_end;
  448. }
  449. #if BOOST_UBLAS_TYPE_CHECK
  450. if (! disable_type_check<bool>::value)
  451. BOOST_UBLAS_CHECK (detail::expression_type_check (v, cv),
  452. external_logic ("external logic or bad condition of inputs"));
  453. #endif
  454. }
  455. // Dispatcher
  456. template<template <class T1, class T2> class F, class V, class E>
  457. BOOST_UBLAS_INLINE
  458. void vector_assign (V &v, const vector_expression<E> &e) {
  459. typedef typename vector_assign_traits<typename V::storage_category,
  460. F<typename V::reference, typename E::value_type>::computed,
  461. typename E::const_iterator::iterator_category>::storage_category storage_category;
  462. vector_assign<F> (v, e, storage_category ());
  463. }
  464. template<class SC, class RI>
  465. struct vector_swap_traits {
  466. typedef SC storage_category;
  467. };
  468. template<>
  469. struct vector_swap_traits<dense_proxy_tag, sparse_bidirectional_iterator_tag> {
  470. typedef sparse_proxy_tag storage_category;
  471. };
  472. template<>
  473. struct vector_swap_traits<packed_proxy_tag, sparse_bidirectional_iterator_tag> {
  474. typedef sparse_proxy_tag storage_category;
  475. };
  476. // Dense (proxy) case
  477. template<template <class T1, class T2> class F, class V, class E>
  478. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  479. void vector_swap (V &v, vector_expression<E> &e, dense_proxy_tag) {
  480. typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
  481. typedef typename V::difference_type difference_type;
  482. difference_type size (BOOST_UBLAS_SAME (v.size (), e ().size ()));
  483. typename V::iterator it (v.begin ());
  484. typename E::iterator ite (e ().begin ());
  485. while (-- size >= 0)
  486. functor_type::apply (*it, *ite), ++ it, ++ ite;
  487. }
  488. // Packed (proxy) case
  489. template<template <class T1, class T2> class F, class V, class E>
  490. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  491. void vector_swap (V &v, vector_expression<E> &e, packed_proxy_tag) {
  492. typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
  493. typedef typename V::difference_type difference_type;
  494. typename V::iterator it (v.begin ());
  495. typename V::iterator it_end (v.end ());
  496. typename E::iterator ite (e ().begin ());
  497. typename E::iterator ite_end (e ().end ());
  498. difference_type it_size (it_end - it);
  499. difference_type ite_size (ite_end - ite);
  500. if (it_size > 0 && ite_size > 0) {
  501. difference_type size ((std::min) (difference_type (it.index () - ite.index ()), ite_size));
  502. if (size > 0) {
  503. ite += size;
  504. ite_size -= size;
  505. }
  506. }
  507. if (it_size > 0 && ite_size > 0) {
  508. difference_type size ((std::min) (difference_type (ite.index () - it.index ()), it_size));
  509. if (size > 0)
  510. it_size -= size;
  511. }
  512. difference_type size ((std::min) (it_size, ite_size));
  513. it_size -= size;
  514. ite_size -= size;
  515. while (-- size >= 0)
  516. functor_type::apply (*it, *ite), ++ it, ++ ite;
  517. }
  518. // Sparse proxy case
  519. template<template <class T1, class T2> class F, class V, class E>
  520. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  521. void vector_swap (V &v, vector_expression<E> &e, sparse_proxy_tag) {
  522. BOOST_UBLAS_CHECK (v.size () == e ().size (), bad_size ());
  523. typedef F<typename V::iterator::reference, typename E::iterator::reference> functor_type;
  524. typedef typename V::size_type size_type;
  525. typedef typename V::difference_type difference_type;
  526. detail::make_conformant (v, e);
  527. // FIXME should be a seperate restriction for E
  528. detail::make_conformant (e (), v);
  529. typename V::iterator it (v.begin ());
  530. typename V::iterator it_end (v.end ());
  531. typename E::iterator ite (e ().begin ());
  532. typename E::iterator ite_end (e ().end ());
  533. if (it != it_end && ite != ite_end) {
  534. size_type it_index = it.index (), ite_index = ite.index ();
  535. for (;;) {
  536. difference_type compare = it_index - ite_index;
  537. if (compare == 0) {
  538. functor_type::apply (*it, *ite);
  539. ++ it, ++ ite;
  540. if (it != it_end && ite != ite_end) {
  541. it_index = it.index ();
  542. ite_index = ite.index ();
  543. } else
  544. break;
  545. } else if (compare < 0) {
  546. increment (it, it_end, - compare);
  547. if (it != it_end)
  548. it_index = it.index ();
  549. else
  550. break;
  551. } else if (compare > 0) {
  552. increment (ite, ite_end, compare);
  553. if (ite != ite_end)
  554. ite_index = ite.index ();
  555. else
  556. break;
  557. }
  558. }
  559. }
  560. #if BOOST_UBLAS_TYPE_CHECK
  561. increment (ite, ite_end);
  562. increment (it, it_end);
  563. #endif
  564. }
  565. // Dispatcher
  566. template<template <class T1, class T2> class F, class V, class E>
  567. BOOST_UBLAS_INLINE
  568. void vector_swap (V &v, vector_expression<E> &e) {
  569. typedef typename vector_swap_traits<typename V::storage_category,
  570. typename E::const_iterator::iterator_category>::storage_category storage_category;
  571. vector_swap<F> (v, e, storage_category ());
  572. }
  573. }}}
  574. #endif