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
13#ifndef _BOOST_UBLAS_MATRIX_ASSIGN_
14#define _BOOST_UBLAS_MATRIX_ASSIGN_
15
16#include <boost/numeric/ublas/traits.hpp>
17// Required for make_conformant storage
18#include <vector>
19
20// Iterators based on ideas of Jeremy Siek
21
22namespace boost { namespace numeric { namespace ublas {
23namespace detail {
24
25 // Weak equality check - useful to compare equality two arbitary matrix expression results.
26 // Since the actual expressions are unknown, we check for and arbitary error bound
27 // on the relative error.
28 // For a linear expression the infinity norm makes sense as we do not know how the elements will be
29 // combined in the expression. False positive results are inevitable for arbirary expressions!
30 template<class E1, class E2, class S>
31 BOOST_UBLAS_INLINE
32 bool equals (const matrix_expression<E1> &e1, const matrix_expression<E2> &e2, S epsilon, S min_norm) {
33 return norm_inf (e1 - e2) <= epsilon *
34 std::max<S> (std::max<S> (norm_inf (e1), norm_inf (e2)), min_norm);
35 }
36
37 template<class E1, class E2>
38 BOOST_UBLAS_INLINE
39 bool expression_type_check (const matrix_expression<E1> &e1, const matrix_expression<E2> &e2) {
40 typedef typename type_traits<typename promote_traits<typename E1::value_type,
41 typename E2::value_type>::promote_type>::real_type real_type;
42 return equals (e1, e2, BOOST_UBLAS_TYPE_CHECK_EPSILON, BOOST_UBLAS_TYPE_CHECK_MIN);
43 }
44
45
46 template<class M, class E, class R>
47 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
48 void make_conformant (M &m, const matrix_expression<E> &e, row_major_tag, R) {
49 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
50 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
51 typedef R conformant_restrict_type;
52 typedef typename M::size_type size_type;
53 typedef typename M::difference_type difference_type;
54 typedef typename M::value_type value_type;
55 // FIXME unbounded_array with push_back maybe better
56 std::vector<std::pair<size_type, size_type> > index;
57 typename M::iterator1 it1 (m.begin1 ());
58 typename M::iterator1 it1_end (m.end1 ());
59 typename E::const_iterator1 it1e (e ().begin1 ());
60 typename E::const_iterator1 it1e_end (e ().end1 ());
61 while (it1 != it1_end && it1e != it1e_end) {
62 difference_type compare = it1.index1 () - it1e.index1 ();
63 if (compare == 0) {
64#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
65 typename M::iterator2 it2 (it1.begin ());
66 typename M::iterator2 it2_end (it1.end ());
67 typename E::const_iterator2 it2e (it1e.begin ());
68 typename E::const_iterator2 it2e_end (it1e.end ());
69#else
70 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
71 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
72 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
73 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
74#endif
75 if (it2 != it2_end && it2e != it2e_end) {
76 size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
77 for (;;) {
78 difference_type compare2 = it2_index - it2e_index;
79 if (compare2 == 0) {
80 ++ it2, ++ it2e;
81 if (it2 != it2_end && it2e != it2e_end) {
82 it2_index = it2.index2 ();
83 it2e_index = it2e.index2 ();
84 } else
85 break;
86 } else if (compare2 < 0) {
87 increment (it2, it2_end, - compare2);
88 if (it2 != it2_end)
89 it2_index = it2.index2 ();
90 else
91 break;
92 } else if (compare2 > 0) {
93 if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
94 if (static_cast<value_type>(*it2e) != value_type/*zero*/())
95 index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
96 ++ it2e;
97 if (it2e != it2e_end)
98 it2e_index = it2e.index2 ();
99 else
100 break;
101 }
102 }
103 }
104 while (it2e != it2e_end) {
105 if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
106 if (static_cast<value_type>(*it2e) != value_type/*zero*/())
107 index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
108 ++ it2e;
109 }
110 ++ it1, ++ it1e;
111 } else if (compare < 0) {
112 increment (it1, it1_end, - compare);
113 } else if (compare > 0) {
114#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
115 typename E::const_iterator2 it2e (it1e.begin ());
116 typename E::const_iterator2 it2e_end (it1e.end ());
117#else
118 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
119 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
120#endif
121 while (it2e != it2e_end) {
122 if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
123 if (static_cast<value_type>(*it2e) != value_type/*zero*/())
124 index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
125 ++ it2e;
126 }
127 ++ it1e;
128 }
129 }
130 while (it1e != it1e_end) {
131#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
132 typename E::const_iterator2 it2e (it1e.begin ());
133 typename E::const_iterator2 it2e_end (it1e.end ());
134#else
135 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
136 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
137#endif
138 while (it2e != it2e_end) {
139 if (conformant_restrict_type::other (it2e.index1 (), it2e.index2 ()))
140 if (static_cast<value_type>(*it2e) != value_type/*zero*/())
141 index.push_back (std::pair<size_type, size_type> (it2e.index1 (), it2e.index2 ()));
142 ++ it2e;
143 }
144 ++ it1e;
145 }
146 // ISSUE proxies require insert_element
147 for (size_type k = 0; k < index.size (); ++ k)
148 m (index [k].first, index [k].second) = value_type/*zero*/();
149 }
150 template<class M, class E, class R>
151 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
152 void make_conformant (M &m, const matrix_expression<E> &e, column_major_tag, R) {
153 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
154 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
155 typedef R conformant_restrict_type;
156 typedef typename M::size_type size_type;
157 typedef typename M::difference_type difference_type;
158 typedef typename M::value_type value_type;
159 std::vector<std::pair<size_type, size_type> > index;
160 typename M::iterator2 it2 (m.begin2 ());
161 typename M::iterator2 it2_end (m.end2 ());
162 typename E::const_iterator2 it2e (e ().begin2 ());
163 typename E::const_iterator2 it2e_end (e ().end2 ());
164 while (it2 != it2_end && it2e != it2e_end) {
165 difference_type compare = it2.index2 () - it2e.index2 ();
166 if (compare == 0) {
167#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
168 typename M::iterator1 it1 (it2.begin ());
169 typename M::iterator1 it1_end (it2.end ());
170 typename E::const_iterator1 it1e (it2e.begin ());
171 typename E::const_iterator1 it1e_end (it2e.end ());
172#else
173 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
174 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
175 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
176 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
177#endif
178 if (it1 != it1_end && it1e != it1e_end) {
179 size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
180 for (;;) {
181 difference_type compare2 = it1_index - it1e_index;
182 if (compare2 == 0) {
183 ++ it1, ++ it1e;
184 if (it1 != it1_end && it1e != it1e_end) {
185 it1_index = it1.index1 ();
186 it1e_index = it1e.index1 ();
187 } else
188 break;
189 } else if (compare2 < 0) {
190 increment (it1, it1_end, - compare2);
191 if (it1 != it1_end)
192 it1_index = it1.index1 ();
193 else
194 break;
195 } else if (compare2 > 0) {
196 if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
197 if (static_cast<value_type>(*it1e) != value_type/*zero*/())
198 index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
199 ++ it1e;
200 if (it1e != it1e_end)
201 it1e_index = it1e.index1 ();
202 else
203 break;
204 }
205 }
206 }
207 while (it1e != it1e_end) {
208 if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
209 if (static_cast<value_type>(*it1e) != value_type/*zero*/())
210 index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
211 ++ it1e;
212 }
213 ++ it2, ++ it2e;
214 } else if (compare < 0) {
215 increment (it2, it2_end, - compare);
216 } else if (compare > 0) {
217#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
218 typename E::const_iterator1 it1e (it2e.begin ());
219 typename E::const_iterator1 it1e_end (it2e.end ());
220#else
221 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
222 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
223#endif
224 while (it1e != it1e_end) {
225 if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
226 if (static_cast<value_type>(*it1e) != value_type/*zero*/())
227 index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
228 ++ it1e;
229 }
230 ++ it2e;
231 }
232 }
233 while (it2e != it2e_end) {
234#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
235 typename E::const_iterator1 it1e (it2e.begin ());
236 typename E::const_iterator1 it1e_end (it2e.end ());
237#else
238 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
239 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
240#endif
241 while (it1e != it1e_end) {
242 if (conformant_restrict_type::other (it1e.index1 (), it1e.index2 ()))
243 if (static_cast<value_type>(*it1e) != value_type/*zero*/())
244 index.push_back (std::pair<size_type, size_type> (it1e.index1 (), it1e.index2 ()));
245 ++ it1e;
246 }
247 ++ it2e;
248 }
249 // ISSUE proxies require insert_element
250 for (size_type k = 0; k < index.size (); ++ k)
251 m (index [k].first, index [k].second) = value_type/*zero*/();
252 }
253
254}//namespace detail
255
256
257 // Explicitly iterating row major
258 template<template <class T1, class T2> class F, class M, class T>
259 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
260 void iterating_matrix_assign_scalar (M &m, const T &t, row_major_tag) {
261 typedef F<typename M::iterator2::reference, T> functor_type;
262 typedef typename M::difference_type difference_type;
263 difference_type size1 (m.size1 ());
264 difference_type size2 (m.size2 ());
265 typename M::iterator1 it1 (m.begin1 ());
266 BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ());
267 while (-- size1 >= 0) {
268#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
269 typename M::iterator2 it2 (it1.begin ());
270#else
271 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
272#endif
273 BOOST_UBLAS_CHECK (it1.end () - it2 == size2, bad_size ());
274 difference_type temp_size2 (size2);
275#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
276 while (-- temp_size2 >= 0)
277 functor_type::apply (*it2, t), ++ it2;
278#else
279 DD (temp_size2, 4, r, (functor_type::apply (*it2, t), ++ it2));
280#endif
281 ++ it1;
282 }
283 }
284 // Explicitly iterating column major
285 template<template <class T1, class T2> class F, class M, class T>
286 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
287 void iterating_matrix_assign_scalar (M &m, const T &t, column_major_tag) {
288 typedef F<typename M::iterator1::reference, T> functor_type;
289 typedef typename M::difference_type difference_type;
290 difference_type size2 (m.size2 ());
291 difference_type size1 (m.size1 ());
292 typename M::iterator2 it2 (m.begin2 ());
293 BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ());
294 while (-- size2 >= 0) {
295#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
296 typename M::iterator1 it1 (it2.begin ());
297#else
298 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
299#endif
300 BOOST_UBLAS_CHECK (it2.end () - it1 == size1, bad_size ());
301 difference_type temp_size1 (size1);
302#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
303 while (-- temp_size1 >= 0)
304 functor_type::apply (*it1, t), ++ it1;
305#else
306 DD (temp_size1, 4, r, (functor_type::apply (*it1, t), ++ it1));
307#endif
308 ++ it2;
309 }
310 }
311 // Explicitly indexing row major
312 template<template <class T1, class T2> class F, class M, class T>
313 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
314 void indexing_matrix_assign_scalar (M &m, const T &t, row_major_tag) {
315 typedef F<typename M::reference, T> functor_type;
316 typedef typename M::size_type size_type;
317 size_type size1 (m.size1 ());
318 size_type size2 (m.size2 ());
319 for (size_type i = 0; i < size1; ++ i) {
320#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
321 for (size_type j = 0; j < size2; ++ j)
322 functor_type::apply (m (i, j), t);
323#else
324 size_type j (0);
325 DD (size2, 4, r, (functor_type::apply (m (i, j), t), ++ j));
326#endif
327 }
328 }
329 // Explicitly indexing column major
330 template<template <class T1, class T2> class F, class M, class T>
331 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
332 void indexing_matrix_assign_scalar (M &m, const T &t, column_major_tag) {
333 typedef F<typename M::reference, T> functor_type;
334 typedef typename M::size_type size_type;
335 size_type size2 (m.size2 ());
336 size_type size1 (m.size1 ());
337 for (size_type j = 0; j < size2; ++ j) {
338#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
339 for (size_type i = 0; i < size1; ++ i)
340 functor_type::apply (m (i, j), t);
341#else
342 size_type i (0);
343 DD (size1, 4, r, (functor_type::apply (m (i, j), t), ++ i));
344#endif
345 }
346 }
347
348 // Dense (proxy) case
349 template<template <class T1, class T2> class F, class M, class T, class C>
350 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
351 void matrix_assign_scalar (M &m, const T &t, dense_proxy_tag, C) {
352 typedef C orientation_category;
353#ifdef BOOST_UBLAS_USE_INDEXING
354 indexing_matrix_assign_scalar<F> (m, t, orientation_category ());
355#elif BOOST_UBLAS_USE_ITERATING
356 iterating_matrix_assign_scalar<F> (m, t, orientation_category ());
357#else
358 typedef typename M::size_type size_type;
359 size_type size1 (m.size1 ());
360 size_type size2 (m.size2 ());
361 if (size1 >= BOOST_UBLAS_ITERATOR_THRESHOLD &&
362 size2 >= BOOST_UBLAS_ITERATOR_THRESHOLD)
363 iterating_matrix_assign_scalar<F> (m, t, orientation_category ());
364 else
365 indexing_matrix_assign_scalar<F> (m, t, orientation_category ());
366#endif
367 }
368 // Packed (proxy) row major case
369 template<template <class T1, class T2> class F, class M, class T>
370 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
371 void matrix_assign_scalar (M &m, const T &t, packed_proxy_tag, row_major_tag) {
372 typedef F<typename M::iterator2::reference, T> functor_type;
373 typedef typename M::difference_type difference_type;
374 typename M::iterator1 it1 (m.begin1 ());
375 difference_type size1 (m.end1 () - it1);
376 while (-- size1 >= 0) {
377#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
378 typename M::iterator2 it2 (it1.begin ());
379 difference_type size2 (it1.end () - it2);
380#else
381 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
382 difference_type size2 (end (it1, iterator1_tag ()) - it2);
383#endif
384 while (-- size2 >= 0)
385 functor_type::apply (*it2, t), ++ it2;
386 ++ it1;
387 }
388 }
389 // Packed (proxy) column major case
390 template<template <class T1, class T2> class F, class M, class T>
391 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
392 void matrix_assign_scalar (M &m, const T &t, packed_proxy_tag, column_major_tag) {
393 typedef F<typename M::iterator1::reference, T> functor_type;
394 typedef typename M::difference_type difference_type;
395 typename M::iterator2 it2 (m.begin2 ());
396 difference_type size2 (m.end2 () - it2);
397 while (-- size2 >= 0) {
398#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
399 typename M::iterator1 it1 (it2.begin ());
400 difference_type size1 (it2.end () - it1);
401#else
402 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
403 difference_type size1 (end (it2, iterator2_tag ()) - it1);
404#endif
405 while (-- size1 >= 0)
406 functor_type::apply (*it1, t), ++ it1;
407 ++ it2;
408 }
409 }
410 // Sparse (proxy) row major case
411 template<template <class T1, class T2> class F, class M, class T>
412 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
413 void matrix_assign_scalar (M &m, const T &t, sparse_proxy_tag, row_major_tag) {
414 typedef F<typename M::iterator2::reference, T> functor_type;
415 typename M::iterator1 it1 (m.begin1 ());
416 typename M::iterator1 it1_end (m.end1 ());
417 while (it1 != it1_end) {
418#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
419 typename M::iterator2 it2 (it1.begin ());
420 typename M::iterator2 it2_end (it1.end ());
421#else
422 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
423 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
424#endif
425 while (it2 != it2_end)
426 functor_type::apply (*it2, t), ++ it2;
427 ++ it1;
428 }
429 }
430 // Sparse (proxy) column major case
431 template<template <class T1, class T2> class F, class M, class T>
432 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
433 void matrix_assign_scalar (M &m, const T &t, sparse_proxy_tag, column_major_tag) {
434 typedef F<typename M::iterator1::reference, T> functor_type;
435 typename M::iterator2 it2 (m.begin2 ());
436 typename M::iterator2 it2_end (m.end2 ());
437 while (it2 != it2_end) {
438#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
439 typename M::iterator1 it1 (it2.begin ());
440 typename M::iterator1 it1_end (it2.end ());
441#else
442 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
443 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
444#endif
445 while (it1 != it1_end)
446 functor_type::apply (*it1, t), ++ it1;
447 ++ it2;
448 }
449 }
450
451 // Dispatcher
452 template<template <class T1, class T2> class F, class M, class T>
453 BOOST_UBLAS_INLINE
454 void matrix_assign_scalar (M &m, const T &t) {
455 typedef typename M::storage_category storage_category;
456 typedef typename M::orientation_category orientation_category;
457 matrix_assign_scalar<F> (m, t, storage_category (), orientation_category ());
458 }
459
460 template<class SC, bool COMPUTED, class RI1, class RI2>
461 struct matrix_assign_traits {
462 typedef SC storage_category;
463 };
464
465 template<bool COMPUTED>
466 struct matrix_assign_traits<dense_tag, COMPUTED, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
467 typedef packed_tag storage_category;
468 };
469 template<>
470 struct matrix_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
471 typedef sparse_tag storage_category;
472 };
473 template<>
474 struct matrix_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
475 typedef sparse_proxy_tag storage_category;
476 };
477
478 template<bool COMPUTED>
479 struct matrix_assign_traits<dense_proxy_tag, COMPUTED, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
480 typedef packed_proxy_tag storage_category;
481 };
482 template<bool COMPUTED>
483 struct matrix_assign_traits<dense_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
484 typedef sparse_proxy_tag storage_category;
485 };
486
487 template<>
488 struct matrix_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
489 typedef sparse_tag storage_category;
490 };
491 template<>
492 struct matrix_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
493 typedef sparse_proxy_tag storage_category;
494 };
495
496 template<bool COMPUTED>
497 struct matrix_assign_traits<packed_proxy_tag, COMPUTED, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
498 typedef sparse_proxy_tag storage_category;
499 };
500
501 template<>
502 struct matrix_assign_traits<sparse_tag, true, dense_random_access_iterator_tag, dense_random_access_iterator_tag> {
503 typedef sparse_proxy_tag storage_category;
504 };
505 template<>
506 struct matrix_assign_traits<sparse_tag, true, packed_random_access_iterator_tag, packed_random_access_iterator_tag> {
507 typedef sparse_proxy_tag storage_category;
508 };
509 template<>
510 struct matrix_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
511 typedef sparse_proxy_tag storage_category;
512 };
513
514 // Explicitly iterating row major
515 template<template <class T1, class T2> class F, class M, class E>
516 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
517 void iterating_matrix_assign (M &m, const matrix_expression<E> &e, row_major_tag) {
518 typedef F<typename M::iterator2::reference, typename E::value_type> functor_type;
519 typedef typename M::difference_type difference_type;
520 difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
521 difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
522 typename M::iterator1 it1 (m.begin1 ());
523 BOOST_UBLAS_CHECK (size2 == 0 || m.end1 () - it1 == size1, bad_size ());
524 typename E::const_iterator1 it1e (e ().begin1 ());
525 BOOST_UBLAS_CHECK (size2 == 0 || e ().end1 () - it1e == size1, bad_size ());
526 while (-- size1 >= 0) {
527#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
528 typename M::iterator2 it2 (it1.begin ());
529 typename E::const_iterator2 it2e (it1e.begin ());
530#else
531 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
532 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
533#endif
534 BOOST_UBLAS_CHECK (it1.end () - it2 == size2, bad_size ());
535 BOOST_UBLAS_CHECK (it1e.end () - it2e == size2, bad_size ());
536 difference_type temp_size2 (size2);
537#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
538 while (-- temp_size2 >= 0)
539 functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
540#else
541 DD (temp_size2, 2, r, (functor_type::apply (*it2, *it2e), ++ it2, ++ it2e));
542#endif
543 ++ it1, ++ it1e;
544 }
545 }
546 // Explicitly iterating column major
547 template<template <class T1, class T2> class F, class M, class E>
548 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
549 void iterating_matrix_assign (M &m, const matrix_expression<E> &e, column_major_tag) {
550 typedef F<typename M::iterator1::reference, typename E::value_type> functor_type;
551 typedef typename M::difference_type difference_type;
552 difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
553 difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
554 typename M::iterator2 it2 (m.begin2 ());
555 BOOST_UBLAS_CHECK (size1 == 0 || m.end2 () - it2 == size2, bad_size ());
556 typename E::const_iterator2 it2e (e ().begin2 ());
557 BOOST_UBLAS_CHECK (size1 == 0 || e ().end2 () - it2e == size2, bad_size ());
558 while (-- size2 >= 0) {
559#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
560 typename M::iterator1 it1 (it2.begin ());
561 typename E::const_iterator1 it1e (it2e.begin ());
562#else
563 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
564 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
565#endif
566 BOOST_UBLAS_CHECK (it2.end () - it1 == size1, bad_size ());
567 BOOST_UBLAS_CHECK (it2e.end () - it1e == size1, bad_size ());
568 difference_type temp_size1 (size1);
569#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
570 while (-- temp_size1 >= 0)
571 functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
572#else
573 DD (temp_size1, 2, r, (functor_type::apply (*it1, *it1e), ++ it1, ++ it1e));
574#endif
575 ++ it2, ++ it2e;
576 }
577 }
578 // Explicitly indexing row major
579 template<template <class T1, class T2> class F, class M, class E>
580 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
581 void indexing_matrix_assign (M &m, const matrix_expression<E> &e, row_major_tag) {
582 typedef F<typename M::reference, typename E::value_type> functor_type;
583 typedef typename M::size_type size_type;
584 size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
585 size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
586 for (size_type i = 0; i < size1; ++ i) {
587#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
588 for (size_type j = 0; j < size2; ++ j)
589 functor_type::apply (m (i, j), e () (i, j));
590#else
591 size_type j (0);
592 DD (size2, 2, r, (functor_type::apply (m (i, j), e () (i, j)), ++ j));
593#endif
594 }
595 }
596 // Explicitly indexing column major
597 template<template <class T1, class T2> class F, class M, class E>
598 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
599 void indexing_matrix_assign (M &m, const matrix_expression<E> &e, column_major_tag) {
600 typedef F<typename M::reference, typename E::value_type> functor_type;
601 typedef typename M::size_type size_type;
602 size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
603 size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
604 for (size_type j = 0; j < size2; ++ j) {
605#ifndef BOOST_UBLAS_USE_DUFF_DEVICE
606 for (size_type i = 0; i < size1; ++ i)
607 functor_type::apply (m (i, j), e () (i, j));
608#else
609 size_type i (0);
610 DD (size1, 2, r, (functor_type::apply (m (i, j), e () (i, j)), ++ i));
611#endif
612 }
613 }
614
615 // Dense (proxy) case
616 template<template <class T1, class T2> class F, class R, class M, class E, class C>
617 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
618 void matrix_assign (M &m, const matrix_expression<E> &e, dense_proxy_tag, C) {
619 // R unnecessary, make_conformant not required
620 typedef C orientation_category;
621#ifdef BOOST_UBLAS_USE_INDEXING
622 indexing_matrix_assign<F> (m, e, orientation_category ());
623#elif BOOST_UBLAS_USE_ITERATING
624 iterating_matrix_assign<F> (m, e, orientation_category ());
625#else
626 typedef typename M::difference_type difference_type;
627 size_type size1 (BOOST_UBLAS_SAME (m.size1 (), e ().size1 ()));
628 size_type size2 (BOOST_UBLAS_SAME (m.size2 (), e ().size2 ()));
629 if (size1 >= BOOST_UBLAS_ITERATOR_THRESHOLD &&
630 size2 >= BOOST_UBLAS_ITERATOR_THRESHOLD)
631 iterating_matrix_assign<F> (m, e, orientation_category ());
632 else
633 indexing_matrix_assign<F> (m, e, orientation_category ());
634#endif
635 }
636 // Packed (proxy) row major case
637 template<template <class T1, class T2> class F, class R, class M, class E>
638 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
639 void matrix_assign (M &m, const matrix_expression<E> &e, packed_proxy_tag, row_major_tag) {
640 typedef typename matrix_traits<E>::value_type expr_value_type;
641 typedef F<typename M::iterator2::reference, expr_value_type> functor_type;
642 // R unnecessary, make_conformant not required
643 typedef typename M::difference_type difference_type;
644
645 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
646 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
647
648#if BOOST_UBLAS_TYPE_CHECK
649 typedef typename M::value_type value_type;
650 matrix<value_type, row_major> cm (m.size1 (), m.size2 ());
651 indexing_matrix_assign<scalar_assign> (cm, m, row_major_tag ());
652 indexing_matrix_assign<F> (cm, e, row_major_tag ());
653#endif
654 typename M::iterator1 it1 (m.begin1 ());
655 typename M::iterator1 it1_end (m.end1 ());
656 typename E::const_iterator1 it1e (e ().begin1 ());
657 typename E::const_iterator1 it1e_end (e ().end1 ());
658 difference_type it1_size (it1_end - it1);
659 difference_type it1e_size (it1e_end - it1e);
660 difference_type diff1 (0);
661 if (it1_size > 0 && it1e_size > 0)
662 diff1 = it1.index1 () - it1e.index1 ();
663 if (diff1 != 0) {
664 difference_type size1 = (std::min) (diff1, it1e_size);
665 if (size1 > 0) {
666 it1e += size1;
667 it1e_size -= size1;
668 diff1 -= size1;
669 }
670 size1 = (std::min) (- diff1, it1_size);
671 if (size1 > 0) {
672 it1_size -= size1;
673//Disabled warning C4127 because the conditional expression is constant
674#ifdef _MSC_VER
675#pragma warning(push)
676#pragma warning(disable: 4127)
677#endif
678 if (!functor_type::computed) {
679#ifdef _MSC_VER
680#pragma warning(pop)
681#endif
682 while (-- size1 >= 0) { // zeroing
683#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
684 typename M::iterator2 it2 (it1.begin ());
685 typename M::iterator2 it2_end (it1.end ());
686#else
687 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
688 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
689#endif
690 difference_type size2 (it2_end - it2);
691 while (-- size2 >= 0)
692 functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
693 ++ it1;
694 }
695 } else {
696 it1 += size1;
697 }
698 diff1 += size1;
699 }
700 }
701 difference_type size1 ((std::min) (it1_size, it1e_size));
702 it1_size -= size1;
703 it1e_size -= size1;
704 while (-- size1 >= 0) {
705#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
706 typename M::iterator2 it2 (it1.begin ());
707 typename M::iterator2 it2_end (it1.end ());
708 typename E::const_iterator2 it2e (it1e.begin ());
709 typename E::const_iterator2 it2e_end (it1e.end ());
710#else
711 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
712 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
713 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
714 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
715#endif
716 difference_type it2_size (it2_end - it2);
717 difference_type it2e_size (it2e_end - it2e);
718 difference_type diff2 (0);
719 if (it2_size > 0 && it2e_size > 0) {
720 diff2 = it2.index2 () - it2e.index2 ();
721 difference_type size2 = (std::min) (diff2, it2e_size);
722 if (size2 > 0) {
723 it2e += size2;
724 it2e_size -= size2;
725 diff2 -= size2;
726 }
727 size2 = (std::min) (- diff2, it2_size);
728 if (size2 > 0) {
729 it2_size -= size2;
730//Disabled warning C4127 because the conditional expression is constant
731#ifdef _MSC_VER
732#pragma warning(push)
733#pragma warning(disable: 4127)
734#endif
735 if (!functor_type::computed) {
736#ifdef _MSC_VER
737#pragma warning(pop)
738#endif
739 while (-- size2 >= 0) // zeroing
740 functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
741 } else {
742 it2 += size2;
743 }
744 diff2 += size2;
745 }
746 }
747 difference_type size2 ((std::min) (it2_size, it2e_size));
748 it2_size -= size2;
749 it2e_size -= size2;
750 while (-- size2 >= 0)
751 functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
752 size2 = it2_size;
753//Disabled warning C4127 because the conditional expression is constant
754#ifdef _MSC_VER
755#pragma warning(push)
756#pragma warning(disable: 4127)
757#endif
758 if (!functor_type::computed) {
759#ifdef _MSC_VER
760#pragma warning(pop)
761#endif
762 while (-- size2 >= 0) // zeroing
763 functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
764 } else {
765 it2 += size2;
766 }
767 ++ it1, ++ it1e;
768 }
769 size1 = it1_size;
770//Disabled warning C4127 because the conditional expression is constant
771#ifdef _MSC_VER
772#pragma warning(push)
773#pragma warning(disable: 4127)
774#endif
775 if (!functor_type::computed) {
776#ifdef _MSC_VER
777#pragma warning(pop)
778#endif
779 while (-- size1 >= 0) { // zeroing
780#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
781 typename M::iterator2 it2 (it1.begin ());
782 typename M::iterator2 it2_end (it1.end ());
783#else
784 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
785 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
786#endif
787 difference_type size2 (it2_end - it2);
788 while (-- size2 >= 0)
789 functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
790 ++ it1;
791 }
792 } else {
793 it1 += size1;
794 }
795#if BOOST_UBLAS_TYPE_CHECK
796 if (! disable_type_check<bool>::value)
797 BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
798#endif
799 }
800 // Packed (proxy) column major case
801 template<template <class T1, class T2> class F, class R, class M, class E>
802 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
803 void matrix_assign (M &m, const matrix_expression<E> &e, packed_proxy_tag, column_major_tag) {
804 typedef typename matrix_traits<E>::value_type expr_value_type;
805 typedef F<typename M::iterator1::reference, expr_value_type> functor_type;
806 // R unnecessary, make_conformant not required
807 typedef typename M::difference_type difference_type;
808
809 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
810 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
811
812#if BOOST_UBLAS_TYPE_CHECK
813 typedef typename M::value_type value_type;
814 matrix<value_type, column_major> cm (m.size1 (), m.size2 ());
815 indexing_matrix_assign<scalar_assign> (cm, m, column_major_tag ());
816 indexing_matrix_assign<F> (cm, e, column_major_tag ());
817#endif
818 typename M::iterator2 it2 (m.begin2 ());
819 typename M::iterator2 it2_end (m.end2 ());
820 typename E::const_iterator2 it2e (e ().begin2 ());
821 typename E::const_iterator2 it2e_end (e ().end2 ());
822 difference_type it2_size (it2_end - it2);
823 difference_type it2e_size (it2e_end - it2e);
824 difference_type diff2 (0);
825 if (it2_size > 0 && it2e_size > 0)
826 diff2 = it2.index2 () - it2e.index2 ();
827 if (diff2 != 0) {
828 difference_type size2 = (std::min) (diff2, it2e_size);
829 if (size2 > 0) {
830 it2e += size2;
831 it2e_size -= size2;
832 diff2 -= size2;
833 }
834 size2 = (std::min) (- diff2, it2_size);
835 if (size2 > 0) {
836 it2_size -= size2;
837//Disabled warning C4127 because the conditional expression is constant
838#ifdef _MSC_VER
839#pragma warning(push)
840#pragma warning(disable: 4127)
841#endif
842 if (!functor_type::computed) {
843#ifdef _MSC_VER
844#pragma warning(pop)
845#endif
846 while (-- size2 >= 0) { // zeroing
847#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
848 typename M::iterator1 it1 (it2.begin ());
849 typename M::iterator1 it1_end (it2.end ());
850#else
851 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
852 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
853#endif
854 difference_type size1 (it1_end - it1);
855 while (-- size1 >= 0)
856 functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
857 ++ it2;
858 }
859 } else {
860 it2 += size2;
861 }
862 diff2 += size2;
863 }
864 }
865 difference_type size2 ((std::min) (it2_size, it2e_size));
866 it2_size -= size2;
867 it2e_size -= size2;
868 while (-- size2 >= 0) {
869#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
870 typename M::iterator1 it1 (it2.begin ());
871 typename M::iterator1 it1_end (it2.end ());
872 typename E::const_iterator1 it1e (it2e.begin ());
873 typename E::const_iterator1 it1e_end (it2e.end ());
874#else
875 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
876 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
877 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
878 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
879#endif
880 difference_type it1_size (it1_end - it1);
881 difference_type it1e_size (it1e_end - it1e);
882 difference_type diff1 (0);
883 if (it1_size > 0 && it1e_size > 0) {
884 diff1 = it1.index1 () - it1e.index1 ();
885 difference_type size1 = (std::min) (diff1, it1e_size);
886 if (size1 > 0) {
887 it1e += size1;
888 it1e_size -= size1;
889 diff1 -= size1;
890 }
891 size1 = (std::min) (- diff1, it1_size);
892 if (size1 > 0) {
893 it1_size -= size1;
894//Disabled warning C4127 because the conditional expression is constant
895#ifdef _MSC_VER
896#pragma warning(push)
897#pragma warning(disable: 4127)
898#endif
899 if (!functor_type::computed) {
900#ifdef _MSC_VER
901#pragma warning(pop)
902#endif
903 while (-- size1 >= 0) // zeroing
904 functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
905 } else {
906 it1 += size1;
907 }
908 diff1 += size1;
909 }
910 }
911 difference_type size1 ((std::min) (it1_size, it1e_size));
912 it1_size -= size1;
913 it1e_size -= size1;
914 while (-- size1 >= 0)
915 functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
916 size1 = it1_size;
917//Disabled warning C4127 because the conditional expression is constant
918#ifdef _MSC_VER
919#pragma warning(push)
920#pragma warning(disable: 4127)
921#endif
922 if (!functor_type::computed) {
923
924#ifdef _MSC_VER
925#pragma warning(pop)
926#endif
927 while (-- size1 >= 0) // zeroing
928 functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
929 } else {
930 it1 += size1;
931 }
932 ++ it2, ++ it2e;
933 }
934 size2 = it2_size;
935//Disabled warning C4127 because the conditional expression is constant
936#ifdef _MSC_VER
937#pragma warning(push)
938#pragma warning(disable: 4127)
939#endif
940 if (!functor_type::computed) {
941#ifdef _MSC_VER
942#pragma warning(pop)
943#endif
944 while (-- size2 >= 0) { // zeroing
945#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
946 typename M::iterator1 it1 (it2.begin ());
947 typename M::iterator1 it1_end (it2.end ());
948#else
949 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
950 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
951#endif
952 difference_type size1 (it1_end - it1);
953 while (-- size1 >= 0)
954 functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
955 ++ it2;
956 }
957 } else {
958 it2 += size2;
959 }
960#if BOOST_UBLAS_TYPE_CHECK
961 if (! disable_type_check<bool>::value)
962 BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
963#endif
964 }
965 // Sparse row major case
966 template<template <class T1, class T2> class F, class R, class M, class E>
967 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
968 void matrix_assign (M &m, const matrix_expression<E> &e, sparse_tag, row_major_tag) {
969 typedef F<typename M::iterator2::reference, typename E::value_type> functor_type;
970 // R unnecessary, make_conformant not required
971
972//Disabled warning C4127 because the conditional expression is constant
973#ifdef _MSC_VER
974#pragma warning(push)
975#pragma warning(disable: 4127)
976#endif
977 BOOST_STATIC_ASSERT ((!functor_type::computed));
978#ifdef _MSC_VER
979#pragma warning(pop)
980#endif
981 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
982 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
983 typedef typename M::value_type value_type;
984 // Sparse type has no numeric constraints to check
985
986 m.clear ();
987 typename E::const_iterator1 it1e (e ().begin1 ());
988 typename E::const_iterator1 it1e_end (e ().end1 ());
989 while (it1e != it1e_end) {
990#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
991 typename E::const_iterator2 it2e (it1e.begin ());
992 typename E::const_iterator2 it2e_end (it1e.end ());
993#else
994 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
995 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
996#endif
997 while (it2e != it2e_end) {
998 value_type t (*it2e);
999 if (t != value_type/*zero*/())
1000 m.insert_element (it2e.index1 (), it2e.index2 (), t);
1001 ++ it2e;
1002 }
1003 ++ it1e;
1004 }
1005 }
1006 // Sparse column major case
1007 template<template <class T1, class T2> class F, class R, class M, class E>
1008 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1009 void matrix_assign (M &m, const matrix_expression<E> &e, sparse_tag, column_major_tag) {
1010 typedef F<typename M::iterator1::reference, typename E::value_type> functor_type;
1011 // R unnecessary, make_conformant not required
1012
1013//Disabled warning C4127 because the conditional expression is constant
1014#ifdef _MSC_VER
1015#pragma warning(push)
1016#pragma warning(disable: 4127)
1017#endif
1018 BOOST_STATIC_ASSERT ((!functor_type::computed));
1019#ifdef _MSC_VER
1020#pragma warning(pop)
1021#endif
1022 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1023 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1024 typedef typename M::value_type value_type;
1025 // Sparse type has no numeric constraints to check
1026
1027 m.clear ();
1028 typename E::const_iterator2 it2e (e ().begin2 ());
1029 typename E::const_iterator2 it2e_end (e ().end2 ());
1030 while (it2e != it2e_end) {
1031#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1032 typename E::const_iterator1 it1e (it2e.begin ());
1033 typename E::const_iterator1 it1e_end (it2e.end ());
1034#else
1035 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
1036 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
1037#endif
1038 while (it1e != it1e_end) {
1039 value_type t (*it1e);
1040 if (t != value_type/*zero*/())
1041 m.insert_element (it1e.index1 (), it1e.index2 (), t);
1042 ++ it1e;
1043 }
1044 ++ it2e;
1045 }
1046 }
1047 // Sparse proxy or functional row major case
1048 template<template <class T1, class T2> class F, class R, class M, class E>
1049 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1050 void matrix_assign (M &m, const matrix_expression<E> &e, sparse_proxy_tag, row_major_tag) {
1051 typedef typename matrix_traits<E>::value_type expr_value_type;
1052 typedef F<typename M::iterator2::reference, expr_value_type> functor_type;
1053 typedef R conformant_restrict_type;
1054 typedef typename M::size_type size_type;
1055 typedef typename M::difference_type difference_type;
1056
1057 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1058 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1059
1060#if BOOST_UBLAS_TYPE_CHECK
1061 typedef typename M::value_type value_type;
1062 matrix<value_type, row_major> cm (m.size1 (), m.size2 ());
1063 indexing_matrix_assign<scalar_assign> (cm, m, row_major_tag ());
1064 indexing_matrix_assign<F> (cm, e, row_major_tag ());
1065#endif
1066 detail::make_conformant (m, e, row_major_tag (), conformant_restrict_type ());
1067
1068 typename M::iterator1 it1 (m.begin1 ());
1069 typename M::iterator1 it1_end (m.end1 ());
1070 typename E::const_iterator1 it1e (e ().begin1 ());
1071 typename E::const_iterator1 it1e_end (e ().end1 ());
1072 while (it1 != it1_end && it1e != it1e_end) {
1073 difference_type compare = it1.index1 () - it1e.index1 ();
1074 if (compare == 0) {
1075#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1076 typename M::iterator2 it2 (it1.begin ());
1077 typename M::iterator2 it2_end (it1.end ());
1078 typename E::const_iterator2 it2e (it1e.begin ());
1079 typename E::const_iterator2 it2e_end (it1e.end ());
1080#else
1081 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1082 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1083 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
1084 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
1085#endif
1086 if (it2 != it2_end && it2e != it2e_end) {
1087 size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
1088 for (;;) {
1089 difference_type compare2 = it2_index - it2e_index;
1090 if (compare2 == 0) {
1091 functor_type::apply (*it2, *it2e);
1092 ++ it2, ++ it2e;
1093 if (it2 != it2_end && it2e != it2e_end) {
1094 it2_index = it2.index2 ();
1095 it2e_index = it2e.index2 ();
1096 } else
1097 break;
1098 } else if (compare2 < 0) {
1099//Disabled warning C4127 because the conditional expression is constant
1100#ifdef _MSC_VER
1101#pragma warning(push)
1102#pragma warning(disable: 4127)
1103#endif
1104 if (!functor_type::computed) {
1105#ifdef _MSC_VER
1106#pragma warning(pop)
1107#endif
1108 functor_type::apply (*it2, expr_value_type/*zero*/());
1109 ++ it2;
1110 } else
1111 increment (it2, it2_end, - compare2);
1112 if (it2 != it2_end)
1113 it2_index = it2.index2 ();
1114 else
1115 break;
1116 } else if (compare2 > 0) {
1117 increment (it2e, it2e_end, compare2);
1118 if (it2e != it2e_end)
1119 it2e_index = it2e.index2 ();
1120 else
1121 break;
1122 }
1123 }
1124 }
1125//Disabled warning C4127 because the conditional expression is constant
1126#ifdef _MSC_VER
1127#pragma warning(push)
1128#pragma warning(disable: 4127)
1129#endif
1130 if (!functor_type::computed) {
1131#ifdef _MSC_VER
1132#pragma warning(pop)
1133#endif
1134 while (it2 != it2_end) { // zeroing
1135 functor_type::apply (*it2, expr_value_type/*zero*/());
1136 ++ it2;
1137 }
1138 } else {
1139 it2 = it2_end;
1140 }
1141 ++ it1, ++ it1e;
1142 } else if (compare < 0) {
1143//Disabled warning C4127 because the conditional expression is constant
1144#ifdef _MSC_VER
1145#pragma warning(push)
1146#pragma warning(disable: 4127)
1147#endif
1148 if (!functor_type::computed) {
1149#ifdef _MSC_VER
1150#pragma warning(pop)
1151#endif
1152#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1153 typename M::iterator2 it2 (it1.begin ());
1154 typename M::iterator2 it2_end (it1.end ());
1155#else
1156 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1157 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1158#endif
1159 while (it2 != it2_end) { // zeroing
1160 functor_type::apply (*it2, expr_value_type/*zero*/());
1161 ++ it2;
1162 }
1163 ++ it1;
1164 } else {
1165 increment (it1, it1_end, - compare);
1166 }
1167 } else if (compare > 0) {
1168 increment (it1e, it1e_end, compare);
1169 }
1170 }
1171//Disabled warning C4127 because the conditional expression is constant
1172#ifdef _MSC_VER
1173#pragma warning(push)
1174#pragma warning(disable: 4127)
1175#endif
1176 if (!functor_type::computed) {
1177#ifdef _MSC_VER
1178#pragma warning(pop)
1179#endif
1180 while (it1 != it1_end) {
1181#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1182 typename M::iterator2 it2 (it1.begin ());
1183 typename M::iterator2 it2_end (it1.end ());
1184#else
1185 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1186 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1187#endif
1188 while (it2 != it2_end) { // zeroing
1189 functor_type::apply (*it2, expr_value_type/*zero*/());
1190 ++ it2;
1191 }
1192 ++ it1;
1193 }
1194 } else {
1195 it1 = it1_end;
1196 }
1197#if BOOST_UBLAS_TYPE_CHECK
1198 if (! disable_type_check<bool>::value)
1199 BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
1200#endif
1201 }
1202 // Sparse proxy or functional column major case
1203 template<template <class T1, class T2> class F, class R, class M, class E>
1204 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1205 void matrix_assign (M &m, const matrix_expression<E> &e, sparse_proxy_tag, column_major_tag) {
1206 typedef typename matrix_traits<E>::value_type expr_value_type;
1207 typedef F<typename M::iterator1::reference, expr_value_type> functor_type;
1208 typedef R conformant_restrict_type;
1209 typedef typename M::size_type size_type;
1210 typedef typename M::difference_type difference_type;
1211
1212 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1213 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1214
1215#if BOOST_UBLAS_TYPE_CHECK
1216 typedef typename M::value_type value_type;
1217 matrix<value_type, column_major> cm (m.size1 (), m.size2 ());
1218 indexing_matrix_assign<scalar_assign> (cm, m, column_major_tag ());
1219 indexing_matrix_assign<F> (cm, e, column_major_tag ());
1220#endif
1221 detail::make_conformant (m, e, column_major_tag (), conformant_restrict_type ());
1222
1223 typename M::iterator2 it2 (m.begin2 ());
1224 typename M::iterator2 it2_end (m.end2 ());
1225 typename E::const_iterator2 it2e (e ().begin2 ());
1226 typename E::const_iterator2 it2e_end (e ().end2 ());
1227 while (it2 != it2_end && it2e != it2e_end) {
1228 difference_type compare = it2.index2 () - it2e.index2 ();
1229 if (compare == 0) {
1230#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1231 typename M::iterator1 it1 (it2.begin ());
1232 typename M::iterator1 it1_end (it2.end ());
1233 typename E::const_iterator1 it1e (it2e.begin ());
1234 typename E::const_iterator1 it1e_end (it2e.end ());
1235#else
1236 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1237 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1238 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
1239 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
1240#endif
1241 if (it1 != it1_end && it1e != it1e_end) {
1242 size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
1243 for (;;) {
1244 difference_type compare2 = it1_index - it1e_index;
1245 if (compare2 == 0) {
1246 functor_type::apply (*it1, *it1e);
1247 ++ it1, ++ it1e;
1248 if (it1 != it1_end && it1e != it1e_end) {
1249 it1_index = it1.index1 ();
1250 it1e_index = it1e.index1 ();
1251 } else
1252 break;
1253 } else if (compare2 < 0) {
1254//Disabled warning C4127 because the conditional expression is constant
1255#ifdef _MSC_VER
1256#pragma warning(push)
1257#pragma warning(disable: 4127)
1258#endif
1259 if (!functor_type::computed) {
1260#ifdef _MSC_VER
1261#pragma warning(pop)
1262#endif
1263 functor_type::apply (*it1, expr_value_type/*zero*/()); // zeroing
1264 ++ it1;
1265 } else
1266 increment (it1, it1_end, - compare2);
1267 if (it1 != it1_end)
1268 it1_index = it1.index1 ();
1269 else
1270 break;
1271 } else if (compare2 > 0) {
1272 increment (it1e, it1e_end, compare2);
1273 if (it1e != it1e_end)
1274 it1e_index = it1e.index1 ();
1275 else
1276 break;
1277 }
1278 }
1279 }
1280//Disabled warning C4127 because the conditional expression is constant
1281#ifdef _MSC_VER
1282#pragma warning(push)
1283#pragma warning(disable: 4127)
1284#endif
1285 if (!functor_type::computed) {
1286#ifdef _MSC_VER
1287#pragma warning(pop)
1288#endif
1289 while (it1 != it1_end) { // zeroing
1290 functor_type::apply (*it1, expr_value_type/*zero*/());
1291 ++ it1;
1292 }
1293 } else {
1294 it1 = it1_end;
1295 }
1296 ++ it2, ++ it2e;
1297 } else if (compare < 0) {
1298//Disabled warning C4127 because the conditional expression is constant
1299#ifdef _MSC_VER
1300#pragma warning(push)
1301#pragma warning(disable: 4127)
1302#endif
1303 if (!functor_type::computed) {
1304#ifdef _MSC_VER
1305#pragma warning(pop)
1306#endif
1307#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1308 typename M::iterator1 it1 (it2.begin ());
1309 typename M::iterator1 it1_end (it2.end ());
1310#else
1311 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1312 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1313#endif
1314 while (it1 != it1_end) { // zeroing
1315 functor_type::apply (*it1, expr_value_type/*zero*/());
1316 ++ it1;
1317 }
1318 ++ it2;
1319 } else {
1320 increment (it2, it2_end, - compare);
1321 }
1322 } else if (compare > 0) {
1323 increment (it2e, it2e_end, compare);
1324 }
1325 }
1326//Disabled warning C4127 because the conditional expression is constant
1327#ifdef _MSC_VER
1328#pragma warning(push)
1329#pragma warning(disable: 4127)
1330#endif
1331 if (!functor_type::computed) {
1332#ifdef _MSC_VER
1333#pragma warning(pop)
1334#endif
1335 while (it2 != it2_end) {
1336#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1337 typename M::iterator1 it1 (it2.begin ());
1338 typename M::iterator1 it1_end (it2.end ());
1339#else
1340 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1341 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1342#endif
1343 while (it1 != it1_end) { // zeroing
1344 functor_type::apply (*it1, expr_value_type/*zero*/());
1345 ++ it1;
1346 }
1347 ++ it2;
1348 }
1349 } else {
1350 it2 = it2_end;
1351 }
1352#if BOOST_UBLAS_TYPE_CHECK
1353 if (! disable_type_check<bool>::value)
1354 BOOST_UBLAS_CHECK (detail::expression_type_check (m, cm), external_logic ());
1355#endif
1356 }
1357
1358 // Dispatcher
1359 template<template <class T1, class T2> class F, class M, class E>
1360 BOOST_UBLAS_INLINE
1361 void matrix_assign (M &m, const matrix_expression<E> &e) {
1362 typedef typename matrix_assign_traits<typename M::storage_category,
1363 F<typename M::reference, typename E::value_type>::computed,
1364 typename E::const_iterator1::iterator_category,
1365 typename E::const_iterator2::iterator_category>::storage_category storage_category;
1366 // give preference to matrix M's orientation if known
1367 typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1368 typename E::orientation_category ,
1369 typename M::orientation_category >::type orientation_category;
1370 typedef basic_full<typename M::size_type> unrestricted;
1371 matrix_assign<F, unrestricted> (m, e, storage_category (), orientation_category ());
1372 }
1373 template<template <class T1, class T2> class F, class R, class M, class E>
1374 BOOST_UBLAS_INLINE
1375 void matrix_assign (M &m, const matrix_expression<E> &e) {
1376 typedef R conformant_restrict_type;
1377 typedef typename matrix_assign_traits<typename M::storage_category,
1378 F<typename M::reference, typename E::value_type>::computed,
1379 typename E::const_iterator1::iterator_category,
1380 typename E::const_iterator2::iterator_category>::storage_category storage_category;
1381 // give preference to matrix M's orientation if known
1382 typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1383 typename E::orientation_category ,
1384 typename M::orientation_category >::type orientation_category;
1385 matrix_assign<F, conformant_restrict_type> (m, e, storage_category (), orientation_category ());
1386 }
1387
1388 template<class SC, class RI1, class RI2>
1389 struct matrix_swap_traits {
1390 typedef SC storage_category;
1391 };
1392
1393 template<>
1394 struct matrix_swap_traits<dense_proxy_tag, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
1395 typedef sparse_proxy_tag storage_category;
1396 };
1397
1398 template<>
1399 struct matrix_swap_traits<packed_proxy_tag, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
1400 typedef sparse_proxy_tag storage_category;
1401 };
1402
1403 // Dense (proxy) row major case
1404 template<template <class T1, class T2> class F, class R, class M, class E>
1405 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1406 void matrix_swap (M &m, matrix_expression<E> &e, dense_proxy_tag, row_major_tag) {
1407 typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
1408 // R unnecessary, make_conformant not required
1409 //typedef typename M::size_type size_type; // gcc is complaining that this is not used, although this is not right
1410 typedef typename M::difference_type difference_type;
1411 typename M::iterator1 it1 (m.begin1 ());
1412 typename E::iterator1 it1e (e ().begin1 ());
1413 difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), typename M::size_type (e ().end1 () - it1e)));
1414 while (-- size1 >= 0) {
1415#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1416 typename M::iterator2 it2 (it1.begin ());
1417 typename E::iterator2 it2e (it1e.begin ());
1418 difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), typename M::size_type (it1e.end () - it2e)));
1419#else
1420 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1421 typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1422 difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), typename M::size_type (end (it1e, iterator1_tag ()) - it2e)));
1423#endif
1424 while (-- size2 >= 0)
1425 functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
1426 ++ it1, ++ it1e;
1427 }
1428 }
1429 // Dense (proxy) column major case
1430 template<template <class T1, class T2> class F, class R, class M, class E>
1431 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1432 void matrix_swap (M &m, matrix_expression<E> &e, dense_proxy_tag, column_major_tag) {
1433 typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
1434 // R unnecessary, make_conformant not required
1435 // typedef typename M::size_type size_type; // gcc is complaining that this is not used, although this is not right
1436 typedef typename M::difference_type difference_type;
1437 typename M::iterator2 it2 (m.begin2 ());
1438 typename E::iterator2 it2e (e ().begin2 ());
1439 difference_type size2 (BOOST_UBLAS_SAME (m.size2 (), typename M::size_type (e ().end2 () - it2e)));
1440 while (-- size2 >= 0) {
1441#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1442 typename M::iterator1 it1 (it2.begin ());
1443 typename E::iterator1 it1e (it2e.begin ());
1444 difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), typename M::size_type (it2e.end () - it1e)));
1445#else
1446 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1447 typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1448 difference_type size1 (BOOST_UBLAS_SAME (m.size1 (), typename M::size_type (end (it2e, iterator2_tag ()) - it1e)));
1449#endif
1450 while (-- size1 >= 0)
1451 functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
1452 ++ it2, ++ it2e;
1453 }
1454 }
1455 // Packed (proxy) row major case
1456 template<template <class T1, class T2> class F, class R, class M, class E>
1457 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1458 void matrix_swap (M &m, matrix_expression<E> &e, packed_proxy_tag, row_major_tag) {
1459 typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
1460 // R unnecessary, make_conformant not required
1461 typedef typename M::difference_type difference_type;
1462 typename M::iterator1 it1 (m.begin1 ());
1463 typename E::iterator1 it1e (e ().begin1 ());
1464 difference_type size1 (BOOST_UBLAS_SAME (m.end1 () - it1, e ().end1 () - it1e));
1465 while (-- size1 >= 0) {
1466#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1467 typename M::iterator2 it2 (it1.begin ());
1468 typename E::iterator2 it2e (it1e.begin ());
1469 difference_type size2 (BOOST_UBLAS_SAME (it1.end () - it2, it1e.end () - it2e));
1470#else
1471 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1472 typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1473 difference_type size2 (BOOST_UBLAS_SAME (end (it1, iterator1_tag ()) - it2, end (it1e, iterator1_tag ()) - it2e));
1474#endif
1475 while (-- size2 >= 0)
1476 functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
1477 ++ it1, ++ it1e;
1478 }
1479 }
1480 // Packed (proxy) column major case
1481 template<template <class T1, class T2> class F, class R, class M, class E>
1482 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1483 void matrix_swap (M &m, matrix_expression<E> &e, packed_proxy_tag, column_major_tag) {
1484 typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
1485 // R unnecessary, make_conformant not required
1486 typedef typename M::difference_type difference_type;
1487 typename M::iterator2 it2 (m.begin2 ());
1488 typename E::iterator2 it2e (e ().begin2 ());
1489 difference_type size2 (BOOST_UBLAS_SAME (m.end2 () - it2, e ().end2 () - it2e));
1490 while (-- size2 >= 0) {
1491#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1492 typename M::iterator1 it1 (it2.begin ());
1493 typename E::iterator1 it1e (it2e.begin ());
1494 difference_type size1 (BOOST_UBLAS_SAME (it2.end () - it1, it2e.end () - it1e));
1495#else
1496 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1497 typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1498 difference_type size1 (BOOST_UBLAS_SAME (end (it2, iterator2_tag ()) - it1, end (it2e, iterator2_tag ()) - it1e));
1499#endif
1500 while (-- size1 >= 0)
1501 functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
1502 ++ it2, ++ it2e;
1503 }
1504 }
1505 // Sparse (proxy) row major case
1506 template<template <class T1, class T2> class F, class R, class M, class E>
1507 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1508 void matrix_swap (M &m, matrix_expression<E> &e, sparse_proxy_tag, row_major_tag) {
1509 typedef F<typename M::iterator2::reference, typename E::reference> functor_type;
1510 typedef R conformant_restrict_type;
1511 typedef typename M::size_type size_type;
1512 typedef typename M::difference_type difference_type;
1513 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1514 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1515
1516 detail::make_conformant (m, e, row_major_tag (), conformant_restrict_type ());
1517 // FIXME should be a seperate restriction for E
1518 detail::make_conformant (e (), m, row_major_tag (), conformant_restrict_type ());
1519
1520 typename M::iterator1 it1 (m.begin1 ());
1521 typename M::iterator1 it1_end (m.end1 ());
1522 typename E::iterator1 it1e (e ().begin1 ());
1523 typename E::iterator1 it1e_end (e ().end1 ());
1524 while (it1 != it1_end && it1e != it1e_end) {
1525 difference_type compare = it1.index1 () - it1e.index1 ();
1526 if (compare == 0) {
1527#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1528 typename M::iterator2 it2 (it1.begin ());
1529 typename M::iterator2 it2_end (it1.end ());
1530 typename E::iterator2 it2e (it1e.begin ());
1531 typename E::iterator2 it2e_end (it1e.end ());
1532#else
1533 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1534 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1535 typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1536 typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
1537#endif
1538 if (it2 != it2_end && it2e != it2e_end) {
1539 size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
1540 for (;;) {
1541 difference_type compare2 = it2_index - it2e_index;
1542 if (compare2 == 0) {
1543 functor_type::apply (*it2, *it2e);
1544 ++ it2, ++ it2e;
1545 if (it2 != it2_end && it2e != it2e_end) {
1546 it2_index = it2.index2 ();
1547 it2e_index = it2e.index2 ();
1548 } else
1549 break;
1550 } else if (compare2 < 0) {
1551 increment (it2, it2_end, - compare2);
1552 if (it2 != it2_end)
1553 it2_index = it2.index2 ();
1554 else
1555 break;
1556 } else if (compare2 > 0) {
1557 increment (it2e, it2e_end, compare2);
1558 if (it2e != it2e_end)
1559 it2e_index = it2e.index2 ();
1560 else
1561 break;
1562 }
1563 }
1564 }
1565#if BOOST_UBLAS_TYPE_CHECK
1566 increment (it2e, it2e_end);
1567 increment (it2, it2_end);
1568#endif
1569 ++ it1, ++ it1e;
1570 } else if (compare < 0) {
1571#if BOOST_UBLAS_TYPE_CHECK
1572 while (it1.index1 () < it1e.index1 ()) {
1573#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1574 typename M::iterator2 it2 (it1.begin ());
1575 typename M::iterator2 it2_end (it1.end ());
1576#else
1577 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1578 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1579#endif
1580 increment (it2, it2_end);
1581 ++ it1;
1582 }
1583#else
1584 increment (it1, it1_end, - compare);
1585#endif
1586 } else if (compare > 0) {
1587#if BOOST_UBLAS_TYPE_CHECK
1588 while (it1e.index1 () < it1.index1 ()) {
1589#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1590 typename E::iterator2 it2e (it1e.begin ());
1591 typename E::iterator2 it2e_end (it1e.end ());
1592#else
1593 typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1594 typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
1595#endif
1596 increment (it2e, it2e_end);
1597 ++ it1e;
1598 }
1599#else
1600 increment (it1e, it1e_end, compare);
1601#endif
1602 }
1603 }
1604#if BOOST_UBLAS_TYPE_CHECK
1605 while (it1e != it1e_end) {
1606#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1607 typename E::iterator2 it2e (it1e.begin ());
1608 typename E::iterator2 it2e_end (it1e.end ());
1609#else
1610 typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1611 typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
1612#endif
1613 increment (it2e, it2e_end);
1614 ++ it1e;
1615 }
1616 while (it1 != it1_end) {
1617#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1618 typename M::iterator2 it2 (it1.begin ());
1619 typename M::iterator2 it2_end (it1.end ());
1620#else
1621 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1622 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1623#endif
1624 increment (it2, it2_end);
1625 ++ it1;
1626 }
1627#endif
1628 }
1629 // Sparse (proxy) column major case
1630 template<template <class T1, class T2> class F, class R, class M, class E>
1631 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1632 void matrix_swap (M &m, matrix_expression<E> &e, sparse_proxy_tag, column_major_tag) {
1633 typedef F<typename M::iterator1::reference, typename E::reference> functor_type;
1634 typedef R conformant_restrict_type;
1635 typedef typename M::size_type size_type;
1636 typedef typename M::difference_type difference_type;
1637
1638 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1639 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
1640
1641 detail::make_conformant (m, e, column_major_tag (), conformant_restrict_type ());
1642 // FIXME should be a seperate restriction for E
1643 detail::make_conformant (e (), m, column_major_tag (), conformant_restrict_type ());
1644
1645 typename M::iterator2 it2 (m.begin2 ());
1646 typename M::iterator2 it2_end (m.end2 ());
1647 typename E::iterator2 it2e (e ().begin2 ());
1648 typename E::iterator2 it2e_end (e ().end2 ());
1649 while (it2 != it2_end && it2e != it2e_end) {
1650 difference_type compare = it2.index2 () - it2e.index2 ();
1651 if (compare == 0) {
1652#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1653 typename M::iterator1 it1 (it2.begin ());
1654 typename M::iterator1 it1_end (it2.end ());
1655 typename E::iterator1 it1e (it2e.begin ());
1656 typename E::iterator1 it1e_end (it2e.end ());
1657#else
1658 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1659 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1660 typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1661 typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
1662#endif
1663 if (it1 != it1_end && it1e != it1e_end) {
1664 size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
1665 for (;;) {
1666 difference_type compare2 = it1_index - it1e_index;
1667 if (compare2 == 0) {
1668 functor_type::apply (*it1, *it1e);
1669 ++ it1, ++ it1e;
1670 if (it1 != it1_end && it1e != it1e_end) {
1671 it1_index = it1.index1 ();
1672 it1e_index = it1e.index1 ();
1673 } else
1674 break;
1675 } else if (compare2 < 0) {
1676 increment (it1, it1_end, - compare2);
1677 if (it1 != it1_end)
1678 it1_index = it1.index1 ();
1679 else
1680 break;
1681 } else if (compare2 > 0) {
1682 increment (it1e, it1e_end, compare2);
1683 if (it1e != it1e_end)
1684 it1e_index = it1e.index1 ();
1685 else
1686 break;
1687 }
1688 }
1689 }
1690#if BOOST_UBLAS_TYPE_CHECK
1691 increment (it1e, it1e_end);
1692 increment (it1, it1_end);
1693#endif
1694 ++ it2, ++ it2e;
1695 } else if (compare < 0) {
1696#if BOOST_UBLAS_TYPE_CHECK
1697 while (it2.index2 () < it2e.index2 ()) {
1698#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1699 typename M::iterator1 it1 (it2.begin ());
1700 typename M::iterator1 it1_end (it2.end ());
1701#else
1702 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1703 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1704#endif
1705 increment (it1, it1_end);
1706 ++ it2;
1707 }
1708#else
1709 increment (it2, it2_end, - compare);
1710#endif
1711 } else if (compare > 0) {
1712#if BOOST_UBLAS_TYPE_CHECK
1713 while (it2e.index2 () < it2.index2 ()) {
1714#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1715 typename E::iterator1 it1e (it2e.begin ());
1716 typename E::iterator1 it1e_end (it2e.end ());
1717#else
1718 typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1719 typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
1720#endif
1721 increment (it1e, it1e_end);
1722 ++ it2e;
1723 }
1724#else
1725 increment (it2e, it2e_end, compare);
1726#endif
1727 }
1728 }
1729#if BOOST_UBLAS_TYPE_CHECK
1730 while (it2e != it2e_end) {
1731#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1732 typename E::iterator1 it1e (it2e.begin ());
1733 typename E::iterator1 it1e_end (it2e.end ());
1734#else
1735 typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1736 typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
1737#endif
1738 increment (it1e, it1e_end);
1739 ++ it2e;
1740 }
1741 while (it2 != it2_end) {
1742#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1743 typename M::iterator1 it1 (it2.begin ());
1744 typename M::iterator1 it1_end (it2.end ());
1745#else
1746 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1747 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1748#endif
1749 increment (it1, it1_end);
1750 ++ it2;
1751 }
1752#endif
1753 }
1754
1755 // Dispatcher
1756 template<template <class T1, class T2> class F, class M, class E>
1757 BOOST_UBLAS_INLINE
1758 void matrix_swap (M &m, matrix_expression<E> &e) {
1759 typedef typename matrix_swap_traits<typename M::storage_category,
1760 typename E::const_iterator1::iterator_category,
1761 typename E::const_iterator2::iterator_category>::storage_category storage_category;
1762 // give preference to matrix M's orientation if known
1763 typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1764 typename E::orientation_category ,
1765 typename M::orientation_category >::type orientation_category;
1766 typedef basic_full<typename M::size_type> unrestricted;
1767 matrix_swap<F, unrestricted> (m, e, storage_category (), orientation_category ());
1768 }
1769 template<template <class T1, class T2> class F, class R, class M, class E>
1770 BOOST_UBLAS_INLINE
1771 void matrix_swap (M &m, matrix_expression<E> &e) {
1772 typedef R conformant_restrict_type;
1773 typedef typename matrix_swap_traits<typename M::storage_category,
1774 typename E::const_iterator1::iterator_category,
1775 typename E::const_iterator2::iterator_category>::storage_category storage_category;
1776 // give preference to matrix M's orientation if known
1777 typedef typename boost::mpl::if_<boost::is_same<typename M::orientation_category, unknown_orientation_tag>,
1778 typename E::orientation_category ,
1779 typename M::orientation_category >::type orientation_category;
1780 matrix_swap<F, conformant_restrict_type> (m, e, storage_category (), orientation_category ());
1781 }
1782
1783}}}
1784
1785#endif
1786

source code of include/boost/numeric/ublas/detail/matrix_assign.hpp