2 // Copyright (c) 2000-2002
3 // Joerg Walter, Mathias Koch
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)
9 // The authors gratefully acknowledge the support of
10 // GeNeSys mbH & Co. KG in producing this work.
13 #ifndef _BOOST_UBLAS_MATRIX_ASSIGN_
14 #define _BOOST_UBLAS_MATRIX_ASSIGN_
16 #include <boost/numeric/ublas/traits.hpp>
17 // Required for make_conformant storage
20 // Iterators based on ideas of Jeremy Siek
22 namespace boost { namespace numeric { namespace ublas {
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>
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);
37 template<class E1, class E2>
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);
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 ();
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 ());
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 ()));
75 if (it2 != it2_end && it2e != it2e_end) {
76 size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
78 difference_type compare2 = it2_index - it2e_index;
81 if (it2 != it2_end && it2e != it2e_end) {
82 it2_index = it2.index2 ();
83 it2e_index = it2e.index2 ();
86 } else if (compare2 < 0) {
87 increment (it2, it2_end, - compare2);
89 it2_index = it2.index2 ();
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 ()));
98 it2e_index = it2e.index2 ();
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 ()));
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 ());
118 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
119 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
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 ()));
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 ());
135 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
136 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
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 ()));
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*/();
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 ();
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 ());
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 ()));
178 if (it1 != it1_end && it1e != it1e_end) {
179 size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
181 difference_type compare2 = it1_index - it1e_index;
184 if (it1 != it1_end && it1e != it1e_end) {
185 it1_index = it1.index1 ();
186 it1e_index = it1e.index1 ();
189 } else if (compare2 < 0) {
190 increment (it1, it1_end, - compare2);
192 it1_index = it1.index1 ();
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 ()));
200 if (it1e != it1e_end)
201 it1e_index = it1e.index1 ();
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 ()));
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 ());
221 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
222 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
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 ()));
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 ());
238 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
239 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
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 ()));
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*/();
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 ());
271 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
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;
279 DD (temp_size2, 4, r, (functor_type::apply (*it2, t), ++ it2));
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 ());
298 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
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;
306 DD (temp_size1, 4, r, (functor_type::apply (*it1, t), ++ it1));
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);
325 DD (size2, 4, r, (functor_type::apply (m (i, j), t), ++ j));
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);
343 DD (size1, 4, r, (functor_type::apply (m (i, j), t), ++ i));
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 ());
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 ());
365 indexing_matrix_assign_scalar<F> (m, t, orientation_category ());
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);
381 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
382 difference_type size2 (end (it1, iterator1_tag ()) - it2);
384 while (-- size2 >= 0)
385 functor_type::apply (*it2, t), ++ it2;
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);
402 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
403 difference_type size1 (end (it2, iterator2_tag ()) - it1);
405 while (-- size1 >= 0)
406 functor_type::apply (*it1, t), ++ it1;
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 ());
422 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
423 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
425 while (it2 != it2_end)
426 functor_type::apply (*it2, t), ++ it2;
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 ());
442 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
443 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
445 while (it1 != it1_end)
446 functor_type::apply (*it1, t), ++ it1;
452 template<template <class T1, class T2> class F, class M, class T>
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 ());
460 template<class SC, bool COMPUTED, class RI1, class RI2>
461 struct matrix_assign_traits {
462 typedef SC storage_category;
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;
470 struct matrix_assign_traits<dense_tag, false, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
471 typedef sparse_tag storage_category;
474 struct matrix_assign_traits<dense_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
475 typedef sparse_proxy_tag storage_category;
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;
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;
488 struct matrix_assign_traits<packed_tag, false, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
489 typedef sparse_tag storage_category;
492 struct matrix_assign_traits<packed_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
493 typedef sparse_proxy_tag storage_category;
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;
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;
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;
510 struct matrix_assign_traits<sparse_tag, true, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
511 typedef sparse_proxy_tag storage_category;
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 ());
531 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
532 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
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;
541 DD (temp_size2, 2, r, (functor_type::apply (*it2, *it2e), ++ it2, ++ it2e));
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 ());
563 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
564 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
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;
573 DD (temp_size1, 2, r, (functor_type::apply (*it1, *it1e), ++ it1, ++ it1e));
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));
592 DD (size2, 2, r, (functor_type::apply (m (i, j), e () (i, j)), ++ j));
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));
610 DD (size1, 2, r, (functor_type::apply (m (i, j), e () (i, j)), ++ i));
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 ());
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 ());
633 indexing_matrix_assign<F> (m, e, orientation_category ());
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;
645 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
646 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
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 ());
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 ();
664 difference_type size1 = (std::min) (diff1, it1e_size);
670 size1 = (std::min) (- diff1, it1_size);
673 //Disabled warning C4127 because the conditional expression is constant
675 #pragma warning(push)
676 #pragma warning(disable: 4127)
678 if (!functor_type::computed) {
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 ());
687 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
688 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
690 difference_type size2 (it2_end - it2);
691 while (-- size2 >= 0)
692 functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
701 difference_type size1 ((std::min) (it1_size, it1e_size));
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 ());
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 ()));
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);
727 size2 = (std::min) (- diff2, it2_size);
730 //Disabled warning C4127 because the conditional expression is constant
732 #pragma warning(push)
733 #pragma warning(disable: 4127)
735 if (!functor_type::computed) {
739 while (-- size2 >= 0) // zeroing
740 functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
747 difference_type size2 ((std::min) (it2_size, it2e_size));
750 while (-- size2 >= 0)
751 functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
753 //Disabled warning C4127 because the conditional expression is constant
755 #pragma warning(push)
756 #pragma warning(disable: 4127)
758 if (!functor_type::computed) {
762 while (-- size2 >= 0) // zeroing
763 functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
770 //Disabled warning C4127 because the conditional expression is constant
772 #pragma warning(push)
773 #pragma warning(disable: 4127)
775 if (!functor_type::computed) {
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 ());
784 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
785 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
787 difference_type size2 (it2_end - it2);
788 while (-- size2 >= 0)
789 functor_type::apply (*it2, expr_value_type/*zero*/()), ++ it2;
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 ());
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;
809 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
810 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
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 ());
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 ();
828 difference_type size2 = (std::min) (diff2, it2e_size);
834 size2 = (std::min) (- diff2, it2_size);
837 //Disabled warning C4127 because the conditional expression is constant
839 #pragma warning(push)
840 #pragma warning(disable: 4127)
842 if (!functor_type::computed) {
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 ());
851 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
852 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
854 difference_type size1 (it1_end - it1);
855 while (-- size1 >= 0)
856 functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
865 difference_type size2 ((std::min) (it2_size, it2e_size));
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 ());
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 ()));
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);
891 size1 = (std::min) (- diff1, it1_size);
894 //Disabled warning C4127 because the conditional expression is constant
896 #pragma warning(push)
897 #pragma warning(disable: 4127)
899 if (!functor_type::computed) {
903 while (-- size1 >= 0) // zeroing
904 functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
911 difference_type size1 ((std::min) (it1_size, it1e_size));
914 while (-- size1 >= 0)
915 functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
917 //Disabled warning C4127 because the conditional expression is constant
919 #pragma warning(push)
920 #pragma warning(disable: 4127)
922 if (!functor_type::computed) {
927 while (-- size1 >= 0) // zeroing
928 functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
935 //Disabled warning C4127 because the conditional expression is constant
937 #pragma warning(push)
938 #pragma warning(disable: 4127)
940 if (!functor_type::computed) {
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 ());
949 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
950 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
952 difference_type size1 (it1_end - it1);
953 while (-- size1 >= 0)
954 functor_type::apply (*it1, expr_value_type/*zero*/()), ++ it1;
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 ());
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
972 //Disabled warning C4127 because the conditional expression is constant
974 #pragma warning(push)
975 #pragma warning(disable: 4127)
977 BOOST_STATIC_ASSERT ((!functor_type::computed));
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
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 ());
994 typename E::const_iterator2 it2e (begin (it1e, iterator1_tag ()));
995 typename E::const_iterator2 it2e_end (end (it1e, iterator1_tag ()));
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);
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
1013 //Disabled warning C4127 because the conditional expression is constant
1015 #pragma warning(push)
1016 #pragma warning(disable: 4127)
1018 BOOST_STATIC_ASSERT ((!functor_type::computed));
1020 #pragma warning(pop)
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
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 ());
1035 typename E::const_iterator1 it1e (begin (it2e, iterator2_tag ()));
1036 typename E::const_iterator1 it1e_end (end (it2e, iterator2_tag ()));
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);
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;
1057 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1058 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
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 ());
1066 detail::make_conformant (m, e, row_major_tag (), conformant_restrict_type ());
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 ();
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 ());
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 ()));
1086 if (it2 != it2_end && it2e != it2e_end) {
1087 size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
1089 difference_type compare2 = it2_index - it2e_index;
1090 if (compare2 == 0) {
1091 functor_type::apply (*it2, *it2e);
1093 if (it2 != it2_end && it2e != it2e_end) {
1094 it2_index = it2.index2 ();
1095 it2e_index = it2e.index2 ();
1098 } else if (compare2 < 0) {
1099 //Disabled warning C4127 because the conditional expression is constant
1101 #pragma warning(push)
1102 #pragma warning(disable: 4127)
1104 if (!functor_type::computed) {
1106 #pragma warning(pop)
1108 functor_type::apply (*it2, expr_value_type/*zero*/());
1111 increment (it2, it2_end, - compare2);
1113 it2_index = it2.index2 ();
1116 } else if (compare2 > 0) {
1117 increment (it2e, it2e_end, compare2);
1118 if (it2e != it2e_end)
1119 it2e_index = it2e.index2 ();
1125 //Disabled warning C4127 because the conditional expression is constant
1127 #pragma warning(push)
1128 #pragma warning(disable: 4127)
1130 if (!functor_type::computed) {
1132 #pragma warning(pop)
1134 while (it2 != it2_end) { // zeroing
1135 functor_type::apply (*it2, expr_value_type/*zero*/());
1142 } else if (compare < 0) {
1143 //Disabled warning C4127 because the conditional expression is constant
1145 #pragma warning(push)
1146 #pragma warning(disable: 4127)
1148 if (!functor_type::computed) {
1150 #pragma warning(pop)
1152 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1153 typename M::iterator2 it2 (it1.begin ());
1154 typename M::iterator2 it2_end (it1.end ());
1156 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1157 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1159 while (it2 != it2_end) { // zeroing
1160 functor_type::apply (*it2, expr_value_type/*zero*/());
1165 increment (it1, it1_end, - compare);
1167 } else if (compare > 0) {
1168 increment (it1e, it1e_end, compare);
1171 //Disabled warning C4127 because the conditional expression is constant
1173 #pragma warning(push)
1174 #pragma warning(disable: 4127)
1176 if (!functor_type::computed) {
1178 #pragma warning(pop)
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 ());
1185 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1186 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1188 while (it2 != it2_end) { // zeroing
1189 functor_type::apply (*it2, expr_value_type/*zero*/());
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 ());
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;
1212 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1213 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
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 ());
1221 detail::make_conformant (m, e, column_major_tag (), conformant_restrict_type ());
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 ();
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 ());
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 ()));
1241 if (it1 != it1_end && it1e != it1e_end) {
1242 size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
1244 difference_type compare2 = it1_index - it1e_index;
1245 if (compare2 == 0) {
1246 functor_type::apply (*it1, *it1e);
1248 if (it1 != it1_end && it1e != it1e_end) {
1249 it1_index = it1.index1 ();
1250 it1e_index = it1e.index1 ();
1253 } else if (compare2 < 0) {
1254 //Disabled warning C4127 because the conditional expression is constant
1256 #pragma warning(push)
1257 #pragma warning(disable: 4127)
1259 if (!functor_type::computed) {
1261 #pragma warning(pop)
1263 functor_type::apply (*it1, expr_value_type/*zero*/()); // zeroing
1266 increment (it1, it1_end, - compare2);
1268 it1_index = it1.index1 ();
1271 } else if (compare2 > 0) {
1272 increment (it1e, it1e_end, compare2);
1273 if (it1e != it1e_end)
1274 it1e_index = it1e.index1 ();
1280 //Disabled warning C4127 because the conditional expression is constant
1282 #pragma warning(push)
1283 #pragma warning(disable: 4127)
1285 if (!functor_type::computed) {
1287 #pragma warning(pop)
1289 while (it1 != it1_end) { // zeroing
1290 functor_type::apply (*it1, expr_value_type/*zero*/());
1297 } else if (compare < 0) {
1298 //Disabled warning C4127 because the conditional expression is constant
1300 #pragma warning(push)
1301 #pragma warning(disable: 4127)
1303 if (!functor_type::computed) {
1305 #pragma warning(pop)
1307 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1308 typename M::iterator1 it1 (it2.begin ());
1309 typename M::iterator1 it1_end (it2.end ());
1311 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1312 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1314 while (it1 != it1_end) { // zeroing
1315 functor_type::apply (*it1, expr_value_type/*zero*/());
1320 increment (it2, it2_end, - compare);
1322 } else if (compare > 0) {
1323 increment (it2e, it2e_end, compare);
1326 //Disabled warning C4127 because the conditional expression is constant
1328 #pragma warning(push)
1329 #pragma warning(disable: 4127)
1331 if (!functor_type::computed) {
1333 #pragma warning(pop)
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 ());
1340 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1341 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1343 while (it1 != it1_end) { // zeroing
1344 functor_type::apply (*it1, expr_value_type/*zero*/());
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 ());
1359 template<template <class T1, class T2> class F, class M, class E>
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 ());
1373 template<template <class T1, class T2> class F, class R, class M, class E>
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 ());
1388 template<class SC, class RI1, class RI2>
1389 struct matrix_swap_traits {
1390 typedef SC storage_category;
1394 struct matrix_swap_traits<dense_proxy_tag, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
1395 typedef sparse_proxy_tag storage_category;
1399 struct matrix_swap_traits<packed_proxy_tag, sparse_bidirectional_iterator_tag, sparse_bidirectional_iterator_tag> {
1400 typedef sparse_proxy_tag storage_category;
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)));
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)));
1424 while (-- size2 >= 0)
1425 functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
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)));
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)));
1450 while (-- size1 >= 0)
1451 functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
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));
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));
1475 while (-- size2 >= 0)
1476 functor_type::apply (*it2, *it2e), ++ it2, ++ it2e;
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));
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));
1500 while (-- size1 >= 0)
1501 functor_type::apply (*it1, *it1e), ++ it1, ++ it1e;
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 ());
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 ());
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 ();
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 ());
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 ()));
1538 if (it2 != it2_end && it2e != it2e_end) {
1539 size_type it2_index = it2.index2 (), it2e_index = it2e.index2 ();
1541 difference_type compare2 = it2_index - it2e_index;
1542 if (compare2 == 0) {
1543 functor_type::apply (*it2, *it2e);
1545 if (it2 != it2_end && it2e != it2e_end) {
1546 it2_index = it2.index2 ();
1547 it2e_index = it2e.index2 ();
1550 } else if (compare2 < 0) {
1551 increment (it2, it2_end, - compare2);
1553 it2_index = it2.index2 ();
1556 } else if (compare2 > 0) {
1557 increment (it2e, it2e_end, compare2);
1558 if (it2e != it2e_end)
1559 it2e_index = it2e.index2 ();
1565 #if BOOST_UBLAS_TYPE_CHECK
1566 increment (it2e, it2e_end);
1567 increment (it2, it2_end);
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 ());
1577 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1578 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1580 increment (it2, it2_end);
1584 increment (it1, it1_end, - compare);
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 ());
1593 typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1594 typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
1596 increment (it2e, it2e_end);
1600 increment (it1e, it1e_end, compare);
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 ());
1610 typename E::iterator2 it2e (begin (it1e, iterator1_tag ()));
1611 typename E::iterator2 it2e_end (end (it1e, iterator1_tag ()));
1613 increment (it2e, it2e_end);
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 ());
1621 typename M::iterator2 it2 (begin (it1, iterator1_tag ()));
1622 typename M::iterator2 it2_end (end (it1, iterator1_tag ()));
1624 increment (it2, it2_end);
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;
1638 BOOST_UBLAS_CHECK (m.size1 () == e ().size1 (), bad_size ());
1639 BOOST_UBLAS_CHECK (m.size2 () == e ().size2 (), bad_size ());
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 ());
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 ();
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 ());
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 ()));
1663 if (it1 != it1_end && it1e != it1e_end) {
1664 size_type it1_index = it1.index1 (), it1e_index = it1e.index1 ();
1666 difference_type compare2 = it1_index - it1e_index;
1667 if (compare2 == 0) {
1668 functor_type::apply (*it1, *it1e);
1670 if (it1 != it1_end && it1e != it1e_end) {
1671 it1_index = it1.index1 ();
1672 it1e_index = it1e.index1 ();
1675 } else if (compare2 < 0) {
1676 increment (it1, it1_end, - compare2);
1678 it1_index = it1.index1 ();
1681 } else if (compare2 > 0) {
1682 increment (it1e, it1e_end, compare2);
1683 if (it1e != it1e_end)
1684 it1e_index = it1e.index1 ();
1690 #if BOOST_UBLAS_TYPE_CHECK
1691 increment (it1e, it1e_end);
1692 increment (it1, it1_end);
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 ());
1702 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1703 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1705 increment (it1, it1_end);
1709 increment (it2, it2_end, - compare);
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 ());
1718 typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1719 typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
1721 increment (it1e, it1e_end);
1725 increment (it2e, it2e_end, compare);
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 ());
1735 typename E::iterator1 it1e (begin (it2e, iterator2_tag ()));
1736 typename E::iterator1 it1e_end (end (it2e, iterator2_tag ()));
1738 increment (it1e, it1e_end);
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 ());
1746 typename M::iterator1 it1 (begin (it2, iterator2_tag ()));
1747 typename M::iterator1 it1_end (end (it2, iterator2_tag ()));
1749 increment (it1, it1_end);
1756 template<template <class T1, class T2> class F, class M, class E>
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 ());
1769 template<template <class T1, class T2> class F, class R, class M, class E>
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 ());