New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
assignment.hpp in vendors/XIOS/current/extern/boost/include/boost/numeric/ublas – NEMO

source: vendors/XIOS/current/extern/boost/include/boost/numeric/ublas/assignment.hpp @ 3408

Last change on this file since 3408 was 3408, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

  • Property svn:keywords set to Id
File size: 34.5 KB
Line 
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::size_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::size_t I>
202BOOST_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*/
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::size_t I, std::size_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::size_t I, std::size_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*/
454BOOST_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*/
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*/
498BOOST_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*/
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*/
543BOOST_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*/
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*/
587BOOST_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*/
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 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
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 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
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    by_row_policy<DEFAULT_WRAP_POLICY> by_row() {
889    return by_row_policy<DEFAULT_WRAP_POLICY>();
890    }
891
892    by_row_policy<wrap> by_row_wrap() {
893        return by_row_policy<wrap>();
894    }
895
896    by_row_policy<no_wrap> by_row_no_wrap() {
897        return by_row_policy<no_wrap>();
898    }
899
900    by_column_policy<DEFAULT_WRAP_POLICY> by_column() {
901        return by_column_policy<DEFAULT_WRAP_POLICY>();
902    }
903
904    by_column_policy<wrap> by_column_wrap() {
905        return by_column_policy<wrap>();
906    }
907
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*/
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
Note: See TracBrowser for help on using the repository browser.