1 //
2 // Copyright (c) 2010 Athanasios Iliopoulos
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8
9 #ifndef ASSIGNMENT_HPP
10 #define ASSIGNMENT_HPP
11
12 #include <boost/numeric/ublas/vector_expression.hpp>
13 #include <boost/numeric/ublas/matrix_expression.hpp>
14
15 /*! \file assignment.hpp
16 \brief uBlas assignment operator <<=.
17 */
18
19 namespace boost { namespace numeric { namespace ublas {
20
21 /** \brief A CRTP and Barton-Nackman trick index manipulator wrapper class.
22 *
23 * This class is not meant to be used directly.
24 */
25 template <class TV>
26 class index_manipulator {
27 public:
28 typedef TV type;
29 BOOST_UBLAS_INLINE
operator ()() const30 const type &operator () () const {
31 return *static_cast<const type *> (this);
32 }
33 BOOST_UBLAS_INLINE
operator ()()34 type &operator () () {
35 return *static_cast<type *> (this);
36 }
37 };
38
39 /** \brief A move_to vector index manipulator.
40 *
41 * When member function \c manip is called the referenced
42 * index will be set to the manipulators' index.
43 *
44 * \sa move_to(T i)
45 */
46 template <typename T>
47 class vector_move_to_manip: public index_manipulator<vector_move_to_manip<T> > {
48 public:
49 BOOST_UBLAS_INLINE
vector_move_to_manip(const T & k)50 vector_move_to_manip(const T &k): i(k) { }
51
52 template <typename V>
53 BOOST_UBLAS_INLINE
manip(V & k) const54 void manip(V &k) const { k=i; }
55 private:
56 T i;
57 };
58
59 /** \brief An object generator that returns a move_to vector index manipulator
60 *
61 * \param i The element number the manipulator will move to when \c manip member function is called
62 * \return A move_to vector manipulator
63 *
64 * Example usage:
65 * \code
66 * vector<double> a(6, 0);
67 * a <<= 1, 2, move_to(5), 3;
68 * \endcode
69 * will result in:
70 * \code
71 * 1 2 0 0 0 3
72 * \endcode
73 *
74 * \tparam T Size type
75 * \sa move_to()
76 */
77 template <typename T>
move_to(T i)78 BOOST_UBLAS_INLINE vector_move_to_manip<T> move_to(T i) {
79 return vector_move_to_manip<T>(i);
80 }
81
82 /** \brief A static move to vector manipulator.
83 *
84 * When member function \c manip is called the referenced
85 * index will be set to the manipulators' index
86 *
87 * \sa move_to(T i) and move_to()
88 */
89 template <std::size_t I>
90 class static_vector_move_to_manip: public index_manipulator<static_vector_move_to_manip<I> > {
91 public:
92 template <typename V>
93 BOOST_UBLAS_INLINE
manip(V & k) const94 void manip(V &k) const { k=I; }
95 };
96
97 /** \brief An object generator that returns a static move_to vector index manipulator.
98 *
99 * Typically faster than the dynamic version, but can be used only when the
100 * values are known at compile time.
101 *
102 * \return A static move_to vector manipulator
103 *
104 * Example usage:
105 * \code
106 * vector<double> a(6, 0);
107 * a <<= 1, 2, move_to<5>(), 3;
108 * \endcode
109 * will result in:
110 * \code
111 * 1 2 0 0 0 3
112 * \endcode
113 *
114 * \tparam I The number of elements the manipulator will traverse the index when \c manip function is called
115 */
116 template <std::size_t I>
move_to()117 BOOST_UBLAS_INLINE static_vector_move_to_manip<I> move_to() {
118 return static_vector_move_to_manip<I>();
119 }
120
121 /** \brief A move vector index manipulator.
122 *
123 * When member function traverse is called the manipulators'
124 * index will be added to the referenced index.
125 *
126 * \see move(T i)
127 */
128 template <typename T>
129 class vector_move_manip: public index_manipulator<vector_move_manip<T> > {
130 public:
131 BOOST_UBLAS_INLINE
vector_move_manip(const T & k)132 vector_move_manip(const T &k): i(k) { }
133
134 template <typename V>
manip(V & k) const135 BOOST_UBLAS_INLINE void manip(V &k) const { k+=i; }
136 private:
137 T i;
138 };
139
140 /**
141 * \brief An object generator that returns a move vector index manipulator
142 *
143 * \tparam T Size type
144 * \param i The number of elements the manipulator will traverse the index when \c manip
145 * member function is called. Negative values can be used.
146 * \return A move vector manipulator
147 *
148 * Example usage:
149 * \code
150 * vector<double> a(6, 0);
151 * a <<= 1, 2, move(3), 3;
152 * \endcode
153 * will result in:
154 * \code
155 * 1 2 0 0 0 3
156 * \endcode
157 *
158 */
159 template <typename T>
move(T i)160 BOOST_UBLAS_INLINE vector_move_manip<T> move(T i) {
161 return vector_move_manip<T>(i);
162 }
163
164 /**
165 * \brief A static move vector manipulator
166 *
167 * When member function \c manip is called the manipulators
168 * index will be added to the referenced index
169 *
170 * \sa move()
171 *
172 * \todo Doxygen has some problems with similar template functions. Correct that.
173 */
174 template <std::ptrdiff_t I>
175 class static_vector_move_manip: public index_manipulator<static_vector_move_manip<I> > {
176 public:
177 template <typename V>
manip(V & k) const178 BOOST_UBLAS_INLINE void manip(V &k) const {
179 // With the equivalent expression using '+=' operator, mscv reports waring C4245:
180 // '+=' : conversion from 'ptrdiff_t' to 'unsigned int', signed/unsigned mismatch
181 k = k + I;
182 }
183 };
184
185 /**
186 * \brief An object generator that returns a static move vector index manipulator.
187 *
188 * Typically faster than the dynamic version, but can be used only when the
189 * values are known at compile time.
190 * \tparam I The Number of elements the manipulator will traverse the index when \c manip
191 * function is called.Negative values can be used.
192 * \return A static move vector manipulator
193 *
194 * Example usage:
195 * \code
196 * vector<double> a(6, 0);
197 * a <<= 1, 2, move<3>(), 3;
198 * \endcode
199 * will result in:
200 * \code
201 * 1 2 0 0 0 3
202 * \endcode
203 *
204 * \todo Doxygen has some problems with similar template functions. Correct that.
205 */
206 template <std::ptrdiff_t I>
move()207 static_vector_move_manip<I> move() {
208 return static_vector_move_manip<I>();
209 }
210
211 /**
212 * \brief A move_to matrix manipulator
213 *
214 * When member function \c manip is called the referenced
215 * index will be set to the manipulators' index
216 *
217 * \sa move_to(T i, T j)
218 *
219 * \todo Doxygen has some problems with similar template functions. Correct that.
220 */
221 template <typename T>
222 class matrix_move_to_manip: public index_manipulator<matrix_move_to_manip<T> > {
223 public:
224 BOOST_UBLAS_INLINE
matrix_move_to_manip(T k,T l)225 matrix_move_to_manip(T k, T l): i(k), j(l) { }
226
227 template <typename V1, typename V2>
228 BOOST_UBLAS_INLINE
manip(V1 & k,V2 & l) const229 void manip(V1 &k, V2 &l) const {
230 k=i;
231 l=j;
232 }
233 private:
234 T i, j;
235 };
236
237 /**
238 * \brief An object generator that returns a "move_to" matrix index manipulator
239 *
240 * \tparam size type
241 * \param i The row number the manipulator will move to when \c manip
242 * member function is called
243 * \param j The column number the manipulator will move to when \c manip
244 * member function is called
245 * \return A move matrix manipulator
246 *
247 * Example usage:
248 * \code:
249 * matrix<double> A(3, 3, 0);
250 * A <<= 1, 2, move_to(A.size1()-1, A.size1()-1), 3;
251 * \endcode
252 * will result in:
253 * \code
254 * 1 2 0
255 * 0 0 0
256 * 0 0 3
257 * \endcode
258 * \sa move_to(T i, T j) and static_matrix_move_to_manip
259 *
260 * \todo Doxygen has some problems with similar template functions. Correct that.
261 */
262 template <typename T>
move_to(T i,T j)263 BOOST_UBLAS_INLINE matrix_move_to_manip<T> move_to(T i, T j) {
264 return matrix_move_to_manip<T>(i, j);
265 }
266
267
268 /**
269 * \brief A static move_to matrix manipulator
270 * When member function traverse is called the referenced
271 * index will be set to the manipulators' index
272 *
273 * \sa move_to()
274 *
275 * \todo Doxygen has some problems with similar template functions. Correct that.
276 */
277 template <std::size_t I,std::size_t J>
278 class static_matrix_move_to_manip: public index_manipulator<static_matrix_move_to_manip<I, J> > {
279 public:
280 template <typename V, typename K>
281 BOOST_UBLAS_INLINE
manip(V & k,K & l) const282 void manip(V &k, K &l) const {
283 k=I;
284 l=J;
285 }
286 };
287
288 /**
289 * \brief An object generator that returns a static move_to matrix index manipulator.
290 *
291 * Typically faster than the dynamic version, but can be used only when the
292 * values are known at compile time.
293 * \tparam I The row number the manipulator will set the matrix assigner index to.
294 * \tparam J The column number the manipulator will set the matrix assigner index to.
295 * \return A static move_to matrix manipulator
296 *
297 * Example usage:
298 * \code:
299 * matrix<double> A(3, 3, 0);
300 * A <<= 1, 2, move_to<2,2>, 3;
301 * \endcode
302 * will result in:
303 * \code
304 * 1 2 0
305 * 0 0 0
306 * 0 0 3
307 * \endcode
308 * \sa move_to(T i, T j) and static_matrix_move_to_manip
309 */
310 template <std::size_t I, std::size_t J>
move_to()311 BOOST_UBLAS_INLINE static_matrix_move_to_manip<I, J> move_to() {
312 return static_matrix_move_to_manip<I, J>();
313 }
314
315 /**
316 * \brief A move matrix index manipulator.
317 *
318 * When member function \c manip is called the manipulator's
319 * index will be added to the referenced' index.
320 *
321 * \sa move(T i, T j)
322 */
323 template <typename T>
324 class matrix_move_manip: public index_manipulator<matrix_move_manip<T> > {
325 public:
326 BOOST_UBLAS_INLINE
matrix_move_manip(T k,T l)327 matrix_move_manip(T k, T l): i(k), j(l) { }
328
329 template <typename V, typename K>
330 BOOST_UBLAS_INLINE
manip(V & k,K & l) const331 void manip(V &k, K &l) const {
332 k+=i;
333 l+=j;
334 }
335 private:
336 T i, j;
337 };
338
339 /**
340 * \brief An object generator that returns a move matrix index manipulator
341 *
342 * \tparam size type
343 * \param i The number of rows the manipulator will traverse the index when "manip"
344 * member function is called
345 * \param j The number of columns the manipulator will traverse the index when "manip"
346 * member function is called
347 * \return A move matrix manipulator
348 *
349 * Example:
350 * \code:
351 * matrix<double> A(3, 3, 0);
352 * A <<= 1, 2, move(1,0),
353 * 3,;
354 * \endcode
355 * will result in:
356 * \code
357 * 1 2 0
358 * 0 0 3
359 * 0 0 0
360 * \endcode
361 */
362 template <typename T>
move(T i,T j)363 BOOST_UBLAS_INLINE matrix_move_manip<T> move(T i, T j) {
364 return matrix_move_manip<T>(i, j);
365 }
366
367 /**
368 * \brief A static move matrix index manipulator.
369 *
370 * When member function traverse is called the manipulator's
371 * index will be added to the referenced' index.
372 *
373 * \sa move()
374 *
375 * \todo Doxygen has some problems with similar template functions. Correct that.
376 */
377 template <std::ptrdiff_t I, std::ptrdiff_t J>
378 class static_matrix_move_manip: public index_manipulator<static_matrix_move_manip<I, J> > {
379 public:
380 template <typename V, typename K>
381 BOOST_UBLAS_INLINE
manip(V & k,K & l) const382 void manip(V &k, K &l) const {
383 // With the equivalent expression using '+=' operator, mscv reports waring C4245:
384 // '+=' : conversion from 'ptrdiff_t' to 'unsigned int', signed/unsigned mismatch
385 k = k + I;
386 l = l + J;
387 }
388 };
389
390 /**
391 * \brief An object generator that returns a static "move" matrix index manipulator.
392 *
393 * Typically faster than the dynamic version, but can be used only when the
394 * values are known at compile time. Negative values can be used.
395 * \tparam I The number of rows the manipulator will trasverse the matrix assigner index.
396 * \tparam J The number of columns the manipulator will trasverse the matrix assigner index.
397 * \tparam size type
398 * \return A static move matrix manipulator
399 *
400 * Example:
401 * \code:
402 * matrix<double> A(3, 3, 0);
403 * A <<= 1, 2, move<1,0>(),
404 * 3,;
405 * \endcode
406 * will result in:
407 * \code
408 * 1 2 0
409 * 0 0 3
410 * 0 0 0
411 * \endcode
412 *
413 * \sa move_to()
414 *
415 * \todo Doxygen has some problems with similar template functions. Correct that.
416 */
417 template <std::ptrdiff_t I, std::ptrdiff_t J>
move()418 BOOST_UBLAS_INLINE static_matrix_move_manip<I, J> move() {
419 return static_matrix_move_manip<I, J>();
420 }
421
422 /**
423 * \brief A begining of row manipulator
424 *
425 * When member function \c manip is called the referenced
426 * index will be be set to the begining of the row (i.e. column = 0)
427 *
428 * \sa begin1()
429 */
430 class begin1_manip: public index_manipulator<begin1_manip > {
431 public:
432 template <typename V, typename K>
433 BOOST_UBLAS_INLINE
manip(V & k,K &) const434 void manip(V & k, K &/*l*/) const {
435 k=0;
436 }
437 };
438
439 /**
440 * \brief An object generator that returns a begin1 manipulator.
441 *
442 * The resulted manipulator will traverse the index to the begining
443 * of the current column when its' \c manip member function is called.
444 *
445 * \return A begin1 matrix index manipulator
446 *
447 * Example usage:
448 * \code:
449 * matrix<double> A(3, 3, 0);
450 * A <<= 1, 2, next_row(),
451 * 3, 4, begin1(), 1;
452 * \endcode
453 * will result in:
454 * \code
455 * 1 2 1
456 * 3 4 0
457 * 0 0 0
458 * \endcode
459 * \sa begin2()
460 */
begin1()461 inline begin1_manip begin1() {
462 return begin1_manip();
463 }
464
465 /**
466 * \brief A begining of column manipulator
467 *
468 * When member function \c manip is called the referenced
469 * index will be be set to the begining of the column (i.e. row = 0).
470 *
471 *
472 * \sa begin2()
473 */
474 class begin2_manip: public index_manipulator<begin2_manip > {
475 public:
476 template <typename V, typename K>
477 BOOST_UBLAS_INLINE
manip(V &,K & l) const478 void manip(V &/*k*/, K &l) const {
479 l=0;
480 }
481 };
482
483 /**
484 * \brief An object generator that returns a begin2 manipulator to be used to traverse a matrix.
485 *
486 * The resulted manipulator will traverse the index to the begining
487 * of the current row when its' \c manip member function is called.
488 *
489 * \return A begin2 matrix manipulator
490 *
491 * Example:
492 * \code:
493 * matrix<double> A(3, 3, 0);
494 * A <<= 1, 2, move<1,0>(),
495 * 3, begin2(), 1;
496 * \endcode
497 * will result in:
498 * \code
499 * 1 2 0
500 * 1 0 3
501 * 0 0 0
502 * \endcode
503 * \sa begin1() begin2_manip
504 */
begin2()505 inline begin2_manip begin2() {
506 return begin2_manip();
507 }
508
509
510 /**
511 * \brief A next row matrix manipulator.
512 *
513 * When member function traverse is called the referenced
514 * index will be traveresed to the begining of next row.
515 *
516 * \sa next_row()
517 */
518 class next_row_manip: public index_manipulator<next_row_manip> {
519 public:
520 template <typename V, typename K>
521 BOOST_UBLAS_INLINE
manip(V & k,K & l) const522 void manip(V &k, K &l) const {
523 k++;
524 l=0;
525 }
526 };
527
528 /**
529 * \brief An object generator that returns a next_row manipulator.
530 *
531 * The resulted manipulator will traverse the index to the begining
532 * of the next row when it's manip member function is called.
533 *
534 * \return A next_row matrix manipulator.
535 *
536 * Example:
537 * \code:
538 * matrix<double> A(3, 3, 0);
539 * A <<= 1, 2, next_row(),
540 * 3, 4;
541 * \endcode
542 * will result in:
543 * \code
544 * 1 2 0
545 * 3 4 0
546 * 0 0 0
547 * \endcode
548 * \sa next_column()
549 */
next_row()550 inline next_row_manip next_row() {
551 return next_row_manip();
552 }
553
554 /**
555 * \brief A next column matrix manipulator.
556 *
557 * When member function traverse is called the referenced
558 * index will be traveresed to the begining of next column.
559 *
560 * \sa next_column()
561 */
562 class next_column_manip: public index_manipulator<next_column_manip> {
563 public:
564 template <typename V, typename K>
565 BOOST_UBLAS_INLINE
manip(V & k,K & l) const566 void manip(V &k, K &l) const {
567 k=0;
568 l++;
569 }
570 };
571
572 /**
573 * \brief An object generator that returns a next_row manipulator.
574 *
575 * The resulted manipulator will traverse the index to the begining
576 * of the next column when it's manip member function is called.
577 *
578 * \return A next_column matrix manipulator.
579 *
580 * Example:
581 * \code:
582 * matrix<double> A(3, 3, 0);
583 * A <<= 1, 2, 0,
584 * 3, next_column(), 4;
585 * \endcode
586 * will result in:
587 * \code
588 * 1 2 4
589 * 3 0 0
590 * 0 0 0
591 * \endcode
592 *
593 */
next_column()594 inline next_column_manip next_column() {
595 return next_column_manip();
596 }
597
598 /**
599 * \brief A wrapper for fill policy classes
600 *
601 */
602 template <class T>
603 class fill_policy_wrapper {
604 public:
605 typedef T type;
606 };
607
608 // Collection of the fill policies
609 namespace fill_policy {
610
611 /**
612 * \brief An index assign policy
613 *
614 * This policy is used to for the simplified ublas assign through
615 * normal indexing.
616 *
617 *
618 */
619 class index_assign :public fill_policy_wrapper<index_assign> {
620 public:
621 template <class T, typename S, typename V>
622 BOOST_UBLAS_INLINE
apply(T & e,const S & i,const V & v)623 static void apply(T &e, const S &i, const V &v) {
624 e()(i) = v;
625 }
626 template <class T, typename S, typename V>
627 BOOST_UBLAS_INLINE
apply(T & e,const S & i,const S & j,const V & v)628 static void apply(T &e, const S &i, const S &j, const V &v) {
629 e()(i, j) = v;
630 }
631 };
632
633 /**
634 * \brief An index plus assign policy
635 *
636 * This policy is used when the assignment is desired to be followed
637 * by an addition.
638 *
639 *
640 */
641 class index_plus_assign :public fill_policy_wrapper<index_plus_assign> {
642 public:
643 template <class T, typename S, typename V>
644 BOOST_UBLAS_INLINE
apply(T & e,const S & i,const V & v)645 static void apply(T &e, const S &i, const V &v) {
646 e()(i) += v;
647 }
648 template <class T, typename S, typename V>
649 BOOST_UBLAS_INLINE
apply(T & e,const S & i,const S & j,const V & v)650 static void apply(T &e, const S &i, const S &j, const V &v) {
651 e()(i, j) += v;
652 }
653 };
654
655 /**
656 * \brief An index minus assign policy
657 *
658 * This policy is used when the assignment is desired to be followed
659 * by a substraction.
660 *
661 *
662 */
663 class index_minus_assign :public fill_policy_wrapper<index_minus_assign> {
664 public:
665 template <class T, typename S, typename V>
666 BOOST_UBLAS_INLINE
apply(T & e,const S & i,const V & v)667 static void apply(T &e, const S &i, const V &v) {
668 e()(i) -= v;
669 }
670 template <class T, typename S, typename V>
671 BOOST_UBLAS_INLINE
apply(T & e,const S & i,const S & j,const V & v)672 static void apply(T &e, const S &i, const S &j, const V &v) {
673 e()(i, j) -= v;
674 }
675 };
676
677 /**
678 * \brief The sparse push_back fill policy.
679 *
680 * This policy is adequate for sparse types, when fast filling is required, where indexing
681 * assign is pretty slow.
682
683 * It is important to note that push_back assign cannot be used to add elements before elements
684 * already existing in a sparse container. To achieve that please use the sparse_insert fill policy.
685 */
686 class sparse_push_back :public fill_policy_wrapper<sparse_push_back > {
687 public:
688 template <class T, class S, class V>
689 BOOST_UBLAS_INLINE
apply(T & e,const S & i,const V & v)690 static void apply(T &e, const S &i, const V &v) {
691 e().push_back(i, v);
692 }
693 template <class T, class S, class V>
694 BOOST_UBLAS_INLINE
apply(T & e,const S & i,const S & j,const V & v)695 static void apply(T &e, const S &i, const S &j, const V &v) {
696 e().push_back(i,j, v);
697 }
698 };
699
700 /**
701 * \brief The sparse insert fill policy.
702 *
703 * This policy is adequate for sparse types, when fast filling is required, where indexing
704 * assign is pretty slow. It is slower than sparse_push_back fill policy, but it can be used to
705 * insert elements anywhere inside the container.
706 */
707 class sparse_insert :public fill_policy_wrapper<sparse_insert> {
708 public:
709 template <class T, class S, class V>
710 BOOST_UBLAS_INLINE
apply(T & e,const S & i,const V & v)711 static void apply(T &e, const S &i, const V &v) {
712 e().insert_element(i, v);
713 }
714 template <class T, class S, class V>
715 BOOST_UBLAS_INLINE
apply(T & e,const S & i,const S & j,const V & v)716 static void apply(T &e, const S &i, const S &j, const V &v) {
717 e().insert_element(i,j, v);
718 }
719 };
720
721 }
722
723 /** \brief A wrapper for traverse policy classes
724 *
725 */
726 template <class T>
727 class traverse_policy_wrapper {
728 public:
729 typedef T type;
730 };
731
732 // Collection of the traverse policies
733 namespace traverse_policy {
734
735
736 /**
737 * \brief The no wrap policy.
738 *
739 * The no wrap policy does not allow wrapping when assigning to a matrix
740 */
741 struct no_wrap {
742 /**
743 * \brief Element wrap method
744 */
745 template <class S1, class S2, class S3>
746 BOOST_UBLAS_INLINE
apply1boost::numeric::ublas::traverse_policy::no_wrap747 static void apply1(const S1 &/*s*/, S2 &/*i*/, S3 &/*j*/) {
748 }
749
750 /**
751 * \brief Matrix block wrap method
752 */
753 template <class S1, class S2, class S3>
754 BOOST_UBLAS_INLINE
apply2boost::numeric::ublas::traverse_policy::no_wrap755 static void apply2(const S1 &/*s1*/, const S1 &/*s2*/, S2 &/*i1*/, S3 &/*i2*/) {
756 }
757 };
758
759 /**
760 * \brief The wrap policy.
761 *
762 * The wrap policy enables element wrapping when assigning to a matrix
763 */
764 struct wrap {
765 /**
766 * \brief Element wrap method
767 */
768 template <class S1, class S2, class S3>
769 BOOST_UBLAS_INLINE
apply1boost::numeric::ublas::traverse_policy::wrap770 static void apply1(const S1 &s, S2 &i1, S3 &i2) {
771 if (i2>=s) {
772 i1++;
773 i2=0;
774 }
775 }
776
777 /**
778 * \brief Matrix block wrap method
779 */
780 template <class S1, class S2, class S3>
781 BOOST_UBLAS_INLINE
apply2boost::numeric::ublas::traverse_policy::wrap782 static void apply2(const S1 &s1, const S1 &s2, S2 &i1, S3 &i2) {
783 if (i2>=s2) i2=0; // Wrap to the next block
784 else i1-=s1; // Move up (or right) one block
785 }
786 };
787
788 /**
789 * \brief The row_by_row traverse policy
790 *
791 * This policy is used when the assignment is desired to happen
792 * row_major wise for performance or other reasons.
793 *
794 * This is the default behaviour. To change it globally please define BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
795 * in the compilation options or in an adequate header file.
796 *
797 * Please see EXAMPLES_LINK for usage information.
798 *
799 * \todo Add examples link
800 */
801 template <class Wrap = wrap>
802 class by_row_policy :public traverse_policy_wrapper<by_row_policy<Wrap> > {
803 public:
804 template <typename S1, typename S2>
805 BOOST_UBLAS_INLINE
advance(S1 &,S2 & j)806 static void advance(S1 &/*i*/, S2 &j) { j++;}
807
808 template <class E1, class E2, typename S1, typename S2, typename S3, typename S4, typename S5>
809 BOOST_UBLAS_INLINE
next(const E1 & e,const E2 & me,S1 & i,S2 & j,const S3 &,const S3 & j0,S4 & k,S5 & l)810 static bool next(const E1 &e, const E2 &me, S1 &i, S2 &j, const S3 &/*i0*/, const S3 &j0, S4 &k, S5 &l) {
811 l++; j++;
812 if (l>=e().size2()) {
813 l=0; k++; j=j0; i++;
814 // It is assumed that the iteration starts from 0 and progresses only using this function from within
815 // an assigner object.
816 // Otherwise (i.e. if it is called outside the assigner object) apply2 should have been
817 // outside the if statement.
818 if (k>=e().size1()) {
819 j=j0+e().size2();
820 Wrap::apply2(e().size1(), me().size2(), i, j);
821 return false;
822 }
823 }
824 return true;
825 }
826
827 template <class E, typename S1, typename S2>
828 BOOST_UBLAS_INLINE
apply_wrap(const E & e,S1 & i,S2 & j)829 static void apply_wrap(const E& e, S1 &i, S2 &j) {
830 Wrap::apply1(e().size2(), i, j);
831 }
832 };
833
834 /**
835 * \brief The column_by_column traverse policy
836 *
837 * This policy is used when the assignment is desired to happen
838 * column_major wise, for performance or other reasons.
839 *
840 * This is the NOT the default behaviour. To set this as the default define BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
841 * in the compilation options or in an adequate header file.
842 *
843 * Please see EXAMPLES_LINK for usage information.
844 *
845 * \todo Add examples link
846 */
847 template <class Wrap = wrap>
848 class by_column_policy :public traverse_policy_wrapper<by_column_policy<Wrap> > {
849 public:
850 template <typename S1, typename S2>
851 BOOST_UBLAS_INLINE
advance(S1 & i,S2 &)852 static void advance(S1 &i, S2 &/*j*/) { i++;}
853
854 template <class E1, class E2, typename S1, typename S2, typename S3, typename S4, typename S5>
855 BOOST_UBLAS_INLINE
next(const E1 & e,const E2 & me,S1 & i,S2 & j,const S3 & i0,const S3 &,S4 & k,S5 & l)856 static bool next(const E1 &e, const E2 &me, S1 &i, S2 &j, const S3 &i0, const S3 &/*j0*/, S4 &k, S5 &l) {
857 k++; i++;
858 if (k>=e().size1()) {
859 k=0; l++; i=i0; j++;
860 // It is assumed that the iteration starts from 0 and progresses only using this function from within
861 // an assigner object.
862 // Otherwise (i.e. if it is called outside the assigner object) apply2 should have been
863 // outside the if statement.
864 if (l>=e().size2()) {
865 i=i0+e().size1();
866 Wrap::apply2(e().size2(), me().size1(), j, i);
867 return false;
868 }
869 }
870 return true;
871 }
872
873 template <class E, typename S1, typename S2>
874 BOOST_UBLAS_INLINE
apply_wrap(const E & e,S1 & i,S2 & j)875 static void apply_wrap(const E& e, S1 &i, S2 &j) {
876 Wrap::apply1(e().size1(), j, i);
877 }
878 };
879 }
880 #ifndef BOOST_UBLAS_DEFAULT_NO_WRAP_POLICY
881 typedef traverse_policy::wrap DEFAULT_WRAP_POLICY;
882 #else
883 typedef traverse_policy::no_wrap DEFAULT_WRAP_POLICY;
884 #endif
885
886 #ifndef BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
887 typedef traverse_policy::by_row_policy<DEFAULT_WRAP_POLICY> DEFAULT_TRAVERSE_POLICY;
888 #else
889 typedef traverse_policy::by_column<DEFAULT_WRAP_POLICY> DEFAULT_TRAVERSE_POLICY;
890 #endif
891
892 // Traverse policy namespace
893 namespace traverse_policy {
894
by_row()895 inline by_row_policy<DEFAULT_WRAP_POLICY> by_row() {
896 return by_row_policy<DEFAULT_WRAP_POLICY>();
897 }
898
by_row_wrap()899 inline by_row_policy<wrap> by_row_wrap() {
900 return by_row_policy<wrap>();
901 }
902
by_row_no_wrap()903 inline by_row_policy<no_wrap> by_row_no_wrap() {
904 return by_row_policy<no_wrap>();
905 }
906
by_column()907 inline by_column_policy<DEFAULT_WRAP_POLICY> by_column() {
908 return by_column_policy<DEFAULT_WRAP_POLICY>();
909 }
910
by_column_wrap()911 inline by_column_policy<wrap> by_column_wrap() {
912 return by_column_policy<wrap>();
913 }
914
by_column_no_wrap()915 inline by_column_policy<no_wrap> by_column_no_wrap() {
916 return by_column_policy<no_wrap>();
917 }
918
919 }
920
921 /**
922 * \brief An assigner object used to fill a vector using operator <<= and operator, (comma)
923 *
924 * This object is meant to be created by appropriate object generators.
925 * Please see EXAMPLES_LINK for usage information.
926 *
927 * \todo Add examples link
928 */
929 template <class E, class Fill_Policy = fill_policy::index_assign>
930 class vector_expression_assigner {
931 public:
932 typedef typename E::expression_type::value_type value_type;
933 typedef typename E::expression_type::size_type size_type;
934
935 BOOST_UBLAS_INLINE
vector_expression_assigner(E & e)936 vector_expression_assigner(E &e):ve(&e), i(0) {
937 }
938
939 BOOST_UBLAS_INLINE
vector_expression_assigner(size_type k,E & e)940 vector_expression_assigner(size_type k, E &e):ve(&e), i(k) {
941 // Overloaded like that so it can be differentiated from (E, val).
942 // Otherwise there would be an ambiquity when value_type == size_type.
943 }
944
945 BOOST_UBLAS_INLINE
vector_expression_assigner(E & e,value_type val)946 vector_expression_assigner(E &e, value_type val):ve(&e), i(0) {
947 operator,(val);
948 }
949
950 template <class AE>
951 BOOST_UBLAS_INLINE
vector_expression_assigner(E & e,const vector_expression<AE> & nve)952 vector_expression_assigner(E &e, const vector_expression<AE> &nve):ve(&e), i(0) {
953 operator,(nve);
954 }
955
956 template <typename T>
957 BOOST_UBLAS_INLINE
vector_expression_assigner(E & e,const index_manipulator<T> & ta)958 vector_expression_assigner(E &e, const index_manipulator<T> &ta):ve(&e), i(0) {
959 operator,(ta);
960 }
961
962 BOOST_UBLAS_INLINE
operator ,(const value_type & val)963 vector_expression_assigner &operator, (const value_type& val) {
964 apply(val);
965 return *this;
966 }
967
968 template <class AE>
969 BOOST_UBLAS_INLINE
operator ,(const vector_expression<AE> & nve)970 vector_expression_assigner &operator, (const vector_expression<AE> &nve) {
971 for (typename AE::size_type k = 0; k!= nve().size(); k++)
972 operator,(nve()(k));
973 return *this;
974 }
975
976 template <typename T>
977 BOOST_UBLAS_INLINE
operator ,(const index_manipulator<T> & ta)978 vector_expression_assigner &operator, (const index_manipulator<T> &ta) {
979 ta().manip(i);
980 return *this;
981 }
982
983 template <class T>
984 BOOST_UBLAS_INLINE
operator ,(fill_policy_wrapper<T>) const985 vector_expression_assigner<E, T> operator, (fill_policy_wrapper<T>) const {
986 return vector_expression_assigner<E, T>(i, *ve);
987 }
988
989 private:
990 BOOST_UBLAS_INLINE
apply(const typename E::expression_type::value_type & val)991 vector_expression_assigner &apply(const typename E::expression_type::value_type& val) {
992 Fill_Policy::apply(*ve, i++, val);
993 return *this;
994 }
995
996 private:
997 E *ve;
998 size_type i;
999 };
1000
1001 /*
1002 // The following static assigner is about 30% slower than the dynamic one, probably due to the recursive creation of assigner objects.
1003 // It remains commented here for future reference.
1004
1005 template <class E, std::size_t I=0>
1006 class static_vector_expression_assigner {
1007 public:
1008 typedef typename E::expression_type::value_type value_type;
1009 typedef typename E::expression_type::size_type size_type;
1010
1011 BOOST_UBLAS_INLINE
1012 static_vector_expression_assigner(E &e):ve(e) {
1013 }
1014
1015 BOOST_UBLAS_INLINE
1016 static_vector_expression_assigner(E &e, value_type val):ve(e) {
1017 operator,(val);
1018 }
1019
1020 BOOST_UBLAS_INLINE
1021 static_vector_expression_assigner<E, I+1> operator, (const value_type& val) {
1022 return apply(val);
1023 }
1024
1025 private:
1026 BOOST_UBLAS_INLINE
1027 static_vector_expression_assigner<E, I+1> apply(const typename E::expression_type::value_type& val) {
1028 ve()(I)=val;
1029 return static_vector_expression_assigner<E, I+1>(ve);
1030 }
1031
1032 private:
1033 E &ve;
1034 };
1035
1036 template <class E>
1037 BOOST_UBLAS_INLINE
1038 static_vector_expression_assigner<vector_expression<E>, 1 > test_static(vector_expression<E> &v, const typename E::value_type &val) {
1039 v()(0)=val;
1040 return static_vector_expression_assigner<vector_expression<E>, 1 >(v);
1041 }
1042 */
1043
1044
1045 /**
1046 * \brief A vector_expression_assigner generator used with operator<<= for simple types
1047 *
1048 * Please see EXAMPLES_LINK for usage information.
1049 *
1050 * \todo Add examples link
1051 */
1052 template <class E>
1053 BOOST_UBLAS_INLINE
operator <<=(vector_expression<E> & v,const typename E::value_type & val)1054 vector_expression_assigner<vector_expression<E> > operator<<=(vector_expression<E> &v, const typename E::value_type &val) {
1055 return vector_expression_assigner<vector_expression<E> >(v,val);
1056 }
1057
1058 /**
1059 * \brief ! A vector_expression_assigner generator used with operator<<= for vector expressions
1060 *
1061 * Please see EXAMPLES_LINK for usage information.
1062 *
1063 * \todo Add examples link
1064 */
1065 template <class E1, class E2>
1066 BOOST_UBLAS_INLINE
operator <<=(vector_expression<E1> & v,const vector_expression<E2> & ve)1067 vector_expression_assigner<vector_expression<E1> > operator<<=(vector_expression<E1> &v, const vector_expression<E2> &ve) {
1068 return vector_expression_assigner<vector_expression<E1> >(v,ve);
1069 }
1070
1071 /**
1072 * \brief A vector_expression_assigner generator used with operator<<= for traverse manipulators
1073 *
1074 * Please see EXAMPLES_LINK for usage information.
1075 *
1076 * \todo Add examples link
1077 */
1078 template <class E, typename T>
1079 BOOST_UBLAS_INLINE
operator <<=(vector_expression<E> & v,const index_manipulator<T> & nv)1080 vector_expression_assigner<vector_expression<E> > operator<<=(vector_expression<E> &v, const index_manipulator<T> &nv) {
1081 return vector_expression_assigner<vector_expression<E> >(v,nv);
1082 }
1083
1084 /**
1085 * \brief A vector_expression_assigner generator used with operator<<= for choice of fill policy
1086 *
1087 * Please see EXAMPLES_LINK for usage information.
1088 *
1089 * \todo Add examples link
1090 */
1091 template <class E, typename T>
1092 BOOST_UBLAS_INLINE
operator <<=(vector_expression<E> & v,fill_policy_wrapper<T>)1093 vector_expression_assigner<vector_expression<E>, T> operator<<=(vector_expression<E> &v, fill_policy_wrapper<T>) {
1094 return vector_expression_assigner<vector_expression<E>, T>(v);
1095 }
1096
1097 /**
1098 * \brief An assigner object used to fill a vector using operator <<= and operator, (comma)
1099 *
1100 * This object is meant to be created by appropriate object generators.
1101 * Please see EXAMPLES_LINK for usage information.
1102 *
1103 * \todo Add examples link
1104 */
1105 template <class E, class Fill_Policy = fill_policy::index_assign, class Traverse_Policy = DEFAULT_TRAVERSE_POLICY >
1106 class matrix_expression_assigner {
1107 public:
1108 typedef typename E::expression_type::size_type size_type;
1109
1110 BOOST_UBLAS_INLINE
matrix_expression_assigner(E & e)1111 matrix_expression_assigner(E &e): me(&e), i(0), j(0) {
1112 }
1113
1114 BOOST_UBLAS_INLINE
matrix_expression_assigner(E & e,size_type k,size_type l)1115 matrix_expression_assigner(E &e, size_type k, size_type l): me(&e), i(k), j(l) {
1116 }
1117
1118 BOOST_UBLAS_INLINE
matrix_expression_assigner(E & e,typename E::expression_type::value_type val)1119 matrix_expression_assigner(E &e, typename E::expression_type::value_type val): me(&e), i(0), j(0) {
1120 operator,(val);
1121 }
1122
1123 template <class AE>
1124 BOOST_UBLAS_INLINE
matrix_expression_assigner(E & e,const vector_expression<AE> & nve)1125 matrix_expression_assigner(E &e, const vector_expression<AE> &nve):me(&e), i(0), j(0) {
1126 operator,(nve);
1127 }
1128
1129 template <class AE>
1130 BOOST_UBLAS_INLINE
matrix_expression_assigner(E & e,const matrix_expression<AE> & nme)1131 matrix_expression_assigner(E &e, const matrix_expression<AE> &nme):me(&e), i(0), j(0) {
1132 operator,(nme);
1133 }
1134
1135 template <typename T>
1136 BOOST_UBLAS_INLINE
matrix_expression_assigner(E & e,const index_manipulator<T> & ta)1137 matrix_expression_assigner(E &e, const index_manipulator<T> &ta):me(&e), i(0), j(0) {
1138 operator,(ta);
1139 }
1140
1141 BOOST_UBLAS_INLINE
operator ,(const typename E::expression_type::value_type & val)1142 matrix_expression_assigner &operator, (const typename E::expression_type::value_type& val) {
1143 Traverse_Policy::apply_wrap(*me, i ,j);
1144 return apply(val);
1145 }
1146
1147 template <class AE>
1148 BOOST_UBLAS_INLINE
operator ,(const vector_expression<AE> & nve)1149 matrix_expression_assigner &operator, (const vector_expression<AE> &nve) {
1150 for (typename AE::size_type k = 0; k!= nve().size(); k++) {
1151 operator,(nve()(k));
1152 }
1153 return *this;
1154 }
1155
1156 template <class AE>
1157 BOOST_UBLAS_INLINE
operator ,(const matrix_expression<AE> & nme)1158 matrix_expression_assigner &operator, (const matrix_expression<AE> &nme) {
1159 return apply(nme);
1160 }
1161
1162 template <typename T>
1163 BOOST_UBLAS_INLINE
operator ,(const index_manipulator<T> & ta)1164 matrix_expression_assigner &operator, (const index_manipulator<T> &ta) {
1165 ta().manip(i, j);
1166 return *this;
1167 }
1168
1169 template <class T>
1170 BOOST_UBLAS_INLINE
operator ,(fill_policy_wrapper<T>) const1171 matrix_expression_assigner<E, T, Traverse_Policy> operator, (fill_policy_wrapper<T>) const {
1172 return matrix_expression_assigner<E, T, Traverse_Policy>(*me, i, j);
1173 }
1174
1175
1176 template <class T>
1177 BOOST_UBLAS_INLINE
operator ,(traverse_policy_wrapper<T>)1178 matrix_expression_assigner<E, Fill_Policy, T> operator, (traverse_policy_wrapper<T>) {
1179 Traverse_Policy::apply_wrap(*me, i ,j);
1180 return matrix_expression_assigner<E, Fill_Policy, T>(*me, i, j);
1181 }
1182
1183 private:
1184 BOOST_UBLAS_INLINE
apply(const typename E::expression_type::value_type & val)1185 matrix_expression_assigner &apply(const typename E::expression_type::value_type& val) {
1186 Fill_Policy::apply(*me, i, j, val);
1187 Traverse_Policy::advance(i,j);
1188 return *this;
1189 }
1190
1191 template <class AE>
1192 BOOST_UBLAS_INLINE
apply(const matrix_expression<AE> & nme)1193 matrix_expression_assigner &apply(const matrix_expression<AE> &nme) {
1194 size_type bi = i;
1195 size_type bj = j;
1196 typename AE::size_type k=0, l=0;
1197 Fill_Policy::apply(*me, i, j, nme()(k, l));
1198 while (Traverse_Policy::next(nme, *me, i, j, bi, bj, k, l))
1199 Fill_Policy::apply(*me, i, j, nme()(k, l));
1200 return *this;
1201 }
1202
1203 private:
1204 E *me;
1205 size_type i, j;
1206 };
1207
1208 /**
1209 * \brief A matrix_expression_assigner generator used with operator<<= for simple types
1210 *
1211 * Please see EXAMPLES_LINK for usage information.
1212 *
1213 * \todo Add examples link
1214 */
1215 template <class E>
1216 BOOST_UBLAS_INLINE
operator <<=(matrix_expression<E> & me,const typename E::value_type & val)1217 matrix_expression_assigner<matrix_expression<E> > operator<<=(matrix_expression<E> &me, const typename E::value_type &val) {
1218 return matrix_expression_assigner<matrix_expression<E> >(me,val);
1219 }
1220
1221 /**
1222 * \brief A matrix_expression_assigner generator used with operator<<= for choice of fill policy
1223 *
1224 * Please see EXAMPLES_LINK for usage information.
1225 *
1226 * \todo Add examples link
1227 */
1228 template <class E, typename T>
1229 BOOST_UBLAS_INLINE
operator <<=(matrix_expression<E> & me,fill_policy_wrapper<T>)1230 matrix_expression_assigner<matrix_expression<E>, T> operator<<=(matrix_expression<E> &me, fill_policy_wrapper<T>) {
1231 return matrix_expression_assigner<matrix_expression<E>, T>(me);
1232 }
1233
1234 /**
1235 * \brief A matrix_expression_assigner generator used with operator<<= for traverse manipulators
1236 *
1237 * Please see EXAMPLES_LINK for usage information.
1238 *
1239 * \todo Add examples link
1240 */
1241 template <class E, typename T>
1242 BOOST_UBLAS_INLINE
operator <<=(matrix_expression<E> & me,const index_manipulator<T> & ta)1243 matrix_expression_assigner<matrix_expression<E> > operator<<=(matrix_expression<E> &me, const index_manipulator<T> &ta) {
1244 return matrix_expression_assigner<matrix_expression<E> >(me,ta);
1245 }
1246
1247 /**
1248 * \brief A matrix_expression_assigner generator used with operator<<= for traverse manipulators
1249 *
1250 * Please see EXAMPLES_LINK for usage information.
1251 *
1252 * \todo Add examples link
1253 */
1254 template <class E, typename T>
1255 BOOST_UBLAS_INLINE
operator <<=(matrix_expression<E> & me,traverse_policy_wrapper<T>)1256 matrix_expression_assigner<matrix_expression<E>, fill_policy::index_assign, T> operator<<=(matrix_expression<E> &me, traverse_policy_wrapper<T>) {
1257 return matrix_expression_assigner<matrix_expression<E>, fill_policy::index_assign, T>(me);
1258 }
1259
1260 /**
1261 * \brief A matrix_expression_assigner generator used with operator<<= for vector expressions
1262 *
1263 * Please see EXAMPLES_LINK for usage information.
1264 *
1265 * \todo Add examples link
1266 */
1267 template <class E1, class E2>
1268 BOOST_UBLAS_INLINE
operator <<=(matrix_expression<E1> & me,const vector_expression<E2> & ve)1269 matrix_expression_assigner<matrix_expression<E1> > operator<<=(matrix_expression<E1> &me, const vector_expression<E2> &ve) {
1270 return matrix_expression_assigner<matrix_expression<E1> >(me,ve);
1271 }
1272
1273 /**
1274 * \brief A matrix_expression_assigner generator used with operator<<= for matrix expressions
1275 *
1276 * Please see EXAMPLES_LINK for usage information.
1277 *
1278 * \todo Add examples link
1279 */
1280 template <class E1, class E2>
1281 BOOST_UBLAS_INLINE
operator <<=(matrix_expression<E1> & me1,const matrix_expression<E2> & me2)1282 matrix_expression_assigner<matrix_expression<E1> > operator<<=(matrix_expression<E1> &me1, const matrix_expression<E2> &me2) {
1283 return matrix_expression_assigner<matrix_expression<E1> >(me1,me2);
1284 }
1285
1286 } } }
1287
1288 #endif // ASSIGNMENT_HPP
1289