]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/numeric/ublas/include/boost/numeric/ublas/assignment.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / numeric / ublas / include / boost / numeric / ublas / assignment.hpp
CommitLineData
7c673cae
FG
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
18namespace 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 */
24template <class TV>
25class index_manipulator {
26public:
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 */
45template <typename T>
46class vector_move_to_manip: public index_manipulator<vector_move_to_manip<T> > {
47public:
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; }
54private:
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 */
76template <typename T>
77BOOST_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*/
88template <std::size_t I>
89class static_vector_move_to_manip: public index_manipulator<static_vector_move_to_manip<I> > {
90public:
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 */
115template <std::size_t I>
116BOOST_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 */
127template <typename T>
128class vector_move_manip: public index_manipulator<vector_move_manip<T> > {
129public:
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; }
135private:
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*/
158template <typename T>
159BOOST_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*/
173template <std::ptrdiff_t I>
174class static_vector_move_manip: public index_manipulator<static_vector_move_manip<I> > {
175public:
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*/
201template <std::ptrdiff_t I>
202static_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*/
216template <typename T>
217class matrix_move_to_manip: public index_manipulator<matrix_move_to_manip<T> > {
218public:
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 }
228private:
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*/
257template <typename T>
258BOOST_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*/
272template <std::size_t I,std::size_t J>
273class static_matrix_move_to_manip: public index_manipulator<static_matrix_move_to_manip<I, J> > {
274public:
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*/
305template <std::size_t I, std::size_t J>
306BOOST_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*/
318template <typename T>
319class matrix_move_manip: public index_manipulator<matrix_move_manip<T> > {
320public:
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 }
330private:
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*/
357template <typename T>
358BOOST_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*/
372template <std::ptrdiff_t I, std::ptrdiff_t J>
373class static_matrix_move_manip: public index_manipulator<static_matrix_move_manip<I, J> > {
374public:
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*/
410template <std::ptrdiff_t I, std::ptrdiff_t J>
411BOOST_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*/
423class begin1_manip: public index_manipulator<begin1_manip > {
424public:
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*/
454inline 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*/
467class begin2_manip: public index_manipulator<begin2_manip > {
468public:
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*/
498inline 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*/
511class next_row_manip: public index_manipulator<next_row_manip> {
512public:
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*/
543inline 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*/
555class next_column_manip: public index_manipulator<next_column_manip> {
556public:
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*/
587inline next_column_manip next_column() {
588 return next_column_manip();
589}
590
591/**
592* \brief A wrapper for fill policy classes
593*
594*/
595template <class T>
596class fill_policy_wrapper {
597public:
598 typedef T type;
599};
600
601// Collection of the fill policies
602namespace 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*/
719template <class T>
720class traverse_policy_wrapper {
721public:
722 typedef T type;
723};
724
725// Collection of the traverse policies
726namespace 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
886namespace 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*/
922template <class E, class Fill_Policy = fill_policy::index_assign>
923class vector_expression_assigner {
924public:
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
982private:
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
989private:
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
998template <class E, std::size_t I=0>
999class static_vector_expression_assigner {
1000public:
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
1018private:
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
1025private:
1026 E &ve;
1027};
1028
1029template <class E>
1030BOOST_UBLAS_INLINE
1031static_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*/
1045template <class E>
1046BOOST_UBLAS_INLINE
1047vector_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*/
1058template <class E1, class E2>
1059BOOST_UBLAS_INLINE
1060vector_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*/
1071template <class E, typename T>
1072BOOST_UBLAS_INLINE
1073vector_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*/
1084template <class E, typename T>
1085BOOST_UBLAS_INLINE
1086vector_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*/
1098template <class E, class Fill_Policy = fill_policy::index_assign, class Traverse_Policy = DEFAULT_TRAVERSE_POLICY >
1099class matrix_expression_assigner {
1100public:
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
1176private:
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
1196private:
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*/
1208template <class E>
1209BOOST_UBLAS_INLINE
1210matrix_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*/
1221template <class E, typename T>
1222BOOST_UBLAS_INLINE
1223matrix_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*/
1234template <class E, typename T>
1235BOOST_UBLAS_INLINE
1236matrix_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*/
1247template <class E, typename T>
1248BOOST_UBLAS_INLINE
1249matrix_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*/
1260template <class E1, class E2>
1261BOOST_UBLAS_INLINE
1262matrix_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*/
1273template <class E1, class E2>
1274BOOST_UBLAS_INLINE
1275matrix_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