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
operator ()() const29     const type &operator () () const {
30         return *static_cast<const type *> (this);
31     }
32     BOOST_UBLAS_INLINE
operator ()()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
vector_move_to_manip(const T & k)49     vector_move_to_manip(const T &k): i(k) { }
50 
51     template <typename V>
52     BOOST_UBLAS_INLINE
manip(V & k) const53     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>
move_to(T i)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
manip(V & k) const93     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>
move_to()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
vector_move_manip(const T & k)131     vector_move_manip(const T &k): i(k) { }
132 
133     template <typename V>
manip(V & k) const134     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>
move(T i)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::size_t I>
174 class static_vector_move_manip: public index_manipulator<static_vector_move_manip<I> > {
175 public:
176     template <typename V>
manip(V & k) const177     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::size_t I>
move()202 BOOST_UBLAS_INLINE 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
matrix_move_to_manip(T k,T l)220     matrix_move_to_manip(T k, T l): i(k), j(l) { }
221 
222     template <typename V1, typename V2>
223     BOOST_UBLAS_INLINE
manip(V1 & k,V2 & l) const224     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>
move_to(T i,T j)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
manip(V & k,K & l) const277     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>
move_to()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
matrix_move_manip(T k,T l)322     matrix_move_manip(T k, T l): i(k), j(l) { }
323 
324     template <typename V, typename K>
325     BOOST_UBLAS_INLINE
manip(V & k,K & l) const326     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>
move(T i,T j)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::size_t I, std::size_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
manip(V & k,K & l) const377     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::size_t I, std::size_t J>
move()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
manip(V & k,K &) const427     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 */
begin1()454 BOOST_UBLAS_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
manip(V &,K & l) const471     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 */
begin2()498 BOOST_UBLAS_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
manip(V & k,K & l) const515     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 */
next_row()543 BOOST_UBLAS_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
manip(V & k,K & l) const559     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 */
next_column()587 BOOST_UBLAS_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
apply(T & e,const S & i,const V & v)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
apply(T & e,const S & i,const S & j,const V & v)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
apply(T & e,const S & i,const V & v)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
apply(T & e,const S & i,const S & j,const V & v)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
apply(T & e,const S & i,const V & v)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
apply(T & e,const S & i,const S & j,const V & v)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
apply(T & e,const S & i,const V & v)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
apply(T & e,const S & i,const S & j,const V & v)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
apply(T & e,const S & i,const V & v)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
apply(T & e,const S & i,const S & j,const V & v)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
apply1boost::numeric::ublas::traverse_policy::no_wrap740         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
apply2boost::numeric::ublas::traverse_policy::no_wrap748         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
apply1boost::numeric::ublas::traverse_policy::wrap763         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
apply2boost::numeric::ublas::traverse_policy::wrap775         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
advance(S1 &,S2 & j)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
next(const E1 & e,const E2 & me,S1 & i,S2 & j,const S3 &,const S3 & j0,S4 & k,S5 & l)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 happens 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
apply_wrap(const E & e,S1 & i,S2 & j)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
advance(S1 & i,S2 &)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
next(const E1 & e,const E2 & me,S1 & i,S2 & j,const S3 & i0,const S3 &,S4 & k,S5 & l)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 happens 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
apply_wrap(const E & e,S1 & i,S2 & j)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 
by_row()888     by_row_policy<DEFAULT_WRAP_POLICY> by_row() {
889     return by_row_policy<DEFAULT_WRAP_POLICY>();
890     }
891 
by_row_wrap()892     by_row_policy<wrap> by_row_wrap() {
893         return by_row_policy<wrap>();
894     }
895 
by_row_no_wrap()896     by_row_policy<no_wrap> by_row_no_wrap() {
897         return by_row_policy<no_wrap>();
898     }
899 
by_column()900     by_column_policy<DEFAULT_WRAP_POLICY> by_column() {
901         return by_column_policy<DEFAULT_WRAP_POLICY>();
902     }
903 
by_column_wrap()904     by_column_policy<wrap> by_column_wrap() {
905         return by_column_policy<wrap>();
906     }
907 
by_column_no_wrap()908     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
vector_expression_assigner(E & e)929     vector_expression_assigner(E &e):ve(e), i(0) {
930     }
931 
932     BOOST_UBLAS_INLINE
vector_expression_assigner(size_type k,E & e)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
vector_expression_assigner(E & e,value_type val)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
vector_expression_assigner(E & e,const vector_expression<AE> & nve)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
vector_expression_assigner(E & e,const index_manipulator<T> & ta)951     vector_expression_assigner(E &e, const index_manipulator<T> &ta):ve(e), i(0) {
952         operator,(ta);
953     }
954 
955     BOOST_UBLAS_INLINE
operator ,(const value_type & val)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
operator ,(const vector_expression<AE> & nve)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
operator ,(const index_manipulator<T> & ta)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
operator ,(fill_policy_wrapper<T>) const978     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
apply(const typename E::expression_type::value_type & val)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
operator <<=(vector_expression<E> & v,const typename E::value_type & val)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
operator <<=(vector_expression<E1> & v,const vector_expression<E2> & ve)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
operator <<=(vector_expression<E> & v,const index_manipulator<T> & nv)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
operator <<=(vector_expression<E> & v,fill_policy_wrapper<T>)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
matrix_expression_assigner(E & e)1104     matrix_expression_assigner(E &e): me(e), i(0), j(0) {
1105     }
1106 
1107     BOOST_UBLAS_INLINE
matrix_expression_assigner(E & e,size_type k,size_type l)1108     matrix_expression_assigner(E &e, size_type k, size_type l): me(e), i(k), j(l) {
1109     }
1110 
1111     BOOST_UBLAS_INLINE
matrix_expression_assigner(E & e,typename E::expression_type::value_type val)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
matrix_expression_assigner(E & e,const vector_expression<AE> & nve)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
matrix_expression_assigner(E & e,const matrix_expression<AE> & nme)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
matrix_expression_assigner(E & e,const index_manipulator<T> & ta)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
operator ,(const typename E::expression_type::value_type & val)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
operator ,(const vector_expression<AE> & nve)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
operator ,(const matrix_expression<AE> & nme)1151     matrix_expression_assigner &operator, (const matrix_expression<AE> &nme) {
1152         return apply(nme);
1153     }
1154 
1155     template <typename T>
1156     BOOST_UBLAS_INLINE
operator ,(const index_manipulator<T> & ta)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
operator ,(fill_policy_wrapper<T>) const1164     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
operator ,(traverse_policy_wrapper<T>)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
apply(const typename E::expression_type::value_type & val)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
apply(const matrix_expression<AE> & nme)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
operator <<=(matrix_expression<E> & me,const typename E::value_type & val)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
operator <<=(matrix_expression<E> & me,fill_policy_wrapper<T>)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
operator <<=(matrix_expression<E> & me,const index_manipulator<T> & ta)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
operator <<=(matrix_expression<E> & me,traverse_policy_wrapper<T>)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
operator <<=(matrix_expression<E1> & me,const vector_expression<E2> & ve)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
operator <<=(matrix_expression<E1> & me1,const matrix_expression<E2> & me2)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
1282