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