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