Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:03

0001 //
0002 //  Copyright (c) 2010 Athanasios Iliopoulos
0003 //
0004 //  Distributed under the Boost Software License, Version 1.0. (See
0005 //  accompanying file LICENSE_1_0.txt or copy at
0006 //  http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 
0009 #ifndef ASSIGNMENT_HPP
0010 #define ASSIGNMENT_HPP
0011 
0012 #include <boost/numeric/ublas/vector_expression.hpp>
0013 #include <boost/numeric/ublas/matrix_expression.hpp>
0014 
0015 /*! \file assignment.hpp
0016     \brief uBlas assignment operator <<=.
0017 */
0018 
0019 namespace boost { namespace numeric { namespace ublas {
0020 
0021 /** \brief A CRTP and Barton-Nackman trick index manipulator wrapper class.
0022  *
0023  * This class is not meant to be used directly.
0024  */
0025 template <class TV>
0026 class index_manipulator {
0027 public:
0028     typedef TV type;
0029     BOOST_UBLAS_INLINE
0030     const type &operator () () const {
0031         return *static_cast<const type *> (this);
0032     }
0033     BOOST_UBLAS_INLINE
0034     type &operator () () {
0035         return *static_cast<type *> (this);
0036     }
0037 };
0038 
0039 /** \brief A move_to vector index manipulator.
0040  *
0041  * When member function \c manip is called the referenced
0042  * index will be set to the manipulators' index.
0043  *
0044  * \sa move_to(T i)
0045  */
0046 template <typename T>
0047 class vector_move_to_manip: public index_manipulator<vector_move_to_manip<T> > {
0048 public:
0049     BOOST_UBLAS_INLINE
0050     vector_move_to_manip(const T &k): i(k) { }
0051 
0052     template <typename V>
0053     BOOST_UBLAS_INLINE
0054     void manip(V &k) const { k=i; }
0055 private:
0056     T i;
0057 };
0058 
0059 /** \brief An object generator that returns a move_to vector index manipulator
0060  *
0061  * \param i The element number the manipulator will move to when \c manip member function is called
0062  * \return A move_to vector manipulator
0063  *
0064  * Example usage:
0065  * \code
0066  * vector<double> a(6, 0);
0067  * a <<= 1, 2, move_to(5), 3;
0068  * \endcode
0069  * will result in:
0070  * \code
0071  * 1 2 0 0 0 3
0072  * \endcode
0073  *
0074  * \tparam T Size type
0075  * \sa move_to()
0076  */
0077 template <typename T>
0078 BOOST_UBLAS_INLINE vector_move_to_manip<T>  move_to(T i) {
0079     return vector_move_to_manip<T>(i);
0080 }
0081 
0082 /** \brief A static move to vector manipulator.
0083  *
0084  * When member function \c manip is called the referenced
0085  * index will be set to the manipulators' index
0086  *
0087  * \sa move_to(T i) and move_to()
0088 */
0089 template <std::size_t I>
0090 class static_vector_move_to_manip: public index_manipulator<static_vector_move_to_manip<I> > {
0091 public:
0092     template <typename V>
0093     BOOST_UBLAS_INLINE
0094     void manip(V &k) const { k=I; }
0095 };
0096 
0097 /** \brief An object generator that returns a static move_to vector index  manipulator.
0098  *
0099  * Typically faster than the dynamic version, but can be used only when the
0100  * values are known at compile time.
0101  *
0102  * \return A static move_to vector manipulator
0103  *
0104  * Example usage:
0105  * \code
0106  * vector<double> a(6, 0);
0107  * a <<= 1, 2, move_to<5>(), 3;
0108  * \endcode
0109  * will result in:
0110  * \code
0111  * 1 2 0 0 0 3
0112  * \endcode
0113  *
0114  * \tparam I The number of elements the manipulator will traverse the index when \c manip function is called
0115  */
0116 template <std::size_t I>
0117 BOOST_UBLAS_INLINE static_vector_move_to_manip<I>  move_to() {
0118     return static_vector_move_to_manip<I>();
0119 }
0120 
0121 /** \brief A move vector index manipulator.
0122  *
0123  * When member function traverse is called the manipulators'
0124  * index will be added to the referenced index.
0125  *
0126  * \see move(T i)
0127  */
0128 template <typename T>
0129 class vector_move_manip: public index_manipulator<vector_move_manip<T> > {
0130 public:
0131     BOOST_UBLAS_INLINE
0132     vector_move_manip(const T &k): i(k) { }
0133 
0134     template <typename V>
0135     BOOST_UBLAS_INLINE void manip(V &k) const { k+=i; }
0136 private:
0137     T i;
0138 };
0139 
0140 /**
0141 * \brief  An object generator that returns a move vector index manipulator
0142 *
0143 * \tparam T Size type
0144 * \param i The number of elements the manipulator will traverse the index when \c manip
0145 * member function is called. Negative values can be used.
0146 * \return A move vector manipulator
0147 *
0148 * Example usage:
0149 * \code
0150 * vector<double> a(6, 0);
0151 * a <<= 1, 2, move(3), 3;
0152 * \endcode
0153 * will result in:
0154 * \code
0155 * 1 2 0 0 0 3
0156 * \endcode
0157 *
0158 */
0159 template <typename T>
0160 BOOST_UBLAS_INLINE vector_move_manip<T>  move(T i) {
0161     return vector_move_manip<T>(i);
0162 }
0163 
0164 /**
0165 * \brief A static move vector manipulator
0166 *
0167 * When member function \c manip is called the manipulators
0168 * index will be added to the referenced index
0169 *
0170 * \sa move()
0171 *
0172 * \todo Doxygen has some problems with similar template functions. Correct that.
0173 */
0174 template <std::ptrdiff_t I>
0175 class static_vector_move_manip: public index_manipulator<static_vector_move_manip<I> > {
0176 public:
0177     template <typename V>
0178     BOOST_UBLAS_INLINE void manip(V &k) const {
0179         // With the equivalent expression using '+=' operator, mscv reports waring C4245:
0180         // '+=' : conversion from 'ptrdiff_t' to 'unsigned int', signed/unsigned mismatch
0181         k = k + I;
0182     }
0183 };
0184 
0185 /**
0186 * \brief An object generator that returns a static move vector index manipulator.
0187 *
0188 * Typically faster than the dynamic version, but can be used only when the
0189 * values are known at compile time.
0190 * \tparam I The Number of elements the manipulator will traverse the index when \c manip
0191 * function is called.Negative values can be used.
0192 * \return A static move vector manipulator
0193 *
0194 * Example usage:
0195 * \code
0196 * vector<double> a(6, 0);
0197 * a <<= 1, 2, move<3>(), 3;
0198 * \endcode
0199 * will result in:
0200 * \code
0201 * 1 2 0 0 0 3
0202 * \endcode
0203 *
0204 * \todo Doxygen has some problems with similar template functions. Correct that.
0205 */
0206 template <std::ptrdiff_t I>
0207 static_vector_move_manip<I>  move() {
0208     return static_vector_move_manip<I>();
0209 }
0210 
0211 /**
0212 * \brief A move_to matrix manipulator
0213 *
0214 * When member function \c manip is called the referenced
0215 * index will be set to the manipulators' index
0216 *
0217 * \sa move_to(T i, T j)
0218 *
0219 * \todo Doxygen has some problems with similar template functions. Correct that.
0220 */
0221 template <typename T>
0222 class matrix_move_to_manip: public index_manipulator<matrix_move_to_manip<T> > {
0223 public:
0224     BOOST_UBLAS_INLINE
0225     matrix_move_to_manip(T k, T l): i(k), j(l) { }
0226 
0227     template <typename V1, typename V2>
0228     BOOST_UBLAS_INLINE
0229     void manip(V1 &k, V2 &l) const {
0230         k=i;
0231         l=j;
0232     }
0233 private:
0234     T i, j;
0235 };
0236 
0237 /**
0238 * \brief  An object generator that returns a "move_to" matrix index manipulator
0239 *
0240 * \tparam size type
0241 * \param i The row number the manipulator will move to when \c manip
0242 * member function is called
0243 * \param j The column number the manipulator will move to when \c manip
0244 * member function is called
0245 * \return A move matrix manipulator
0246 *
0247 * Example usage:
0248 * \code:
0249 * matrix<double> A(3, 3, 0);
0250 * A <<= 1, 2, move_to(A.size1()-1, A.size1()-1), 3;
0251 * \endcode
0252 * will result in:
0253 * \code
0254 * 1 2 0
0255 * 0 0 0
0256 * 0 0 3
0257 * \endcode
0258 * \sa move_to(T i, T j) and static_matrix_move_to_manip
0259 *
0260 * \todo Doxygen has some problems with similar template functions. Correct that.
0261 */
0262 template <typename T>
0263 BOOST_UBLAS_INLINE matrix_move_to_manip<T>  move_to(T i, T j) {
0264     return matrix_move_to_manip<T>(i, j);
0265 }
0266 
0267 
0268 /**
0269 * \brief A static move_to matrix manipulator
0270 * When member function traverse is called the referenced
0271 * index will be set to the manipulators' index
0272 *
0273 * \sa move_to()
0274 *
0275 * \todo Doxygen has some problems with similar template functions. Correct that.
0276 */
0277 template <std::size_t I,std::size_t J>
0278 class static_matrix_move_to_manip: public index_manipulator<static_matrix_move_to_manip<I, J> > {
0279 public:
0280     template <typename V, typename K>
0281     BOOST_UBLAS_INLINE
0282     void manip(V &k, K &l) const {
0283         k=I;
0284         l=J;
0285     }
0286 };
0287 
0288 /**
0289 * \brief  An object generator that returns a static move_to matrix index manipulator.
0290 *
0291 * Typically faster than the dynamic version, but can be used only when the
0292 * values are known at compile time.
0293 * \tparam I The row number the manipulator will set the matrix assigner index to.
0294 * \tparam J The column number the manipulator will set the matrix assigner index to.
0295 * \return A static move_to matrix manipulator
0296 *
0297 * Example usage:
0298 * \code:
0299 * matrix<double> A(3, 3, 0);
0300 * A <<= 1, 2, move_to<2,2>, 3;
0301 * \endcode
0302 * will result in:
0303 * \code
0304 * 1 2 0
0305 * 0 0 0
0306 * 0 0 3
0307 * \endcode
0308 * \sa move_to(T i, T j) and static_matrix_move_to_manip
0309 */
0310 template <std::size_t I, std::size_t J>
0311 BOOST_UBLAS_INLINE static_matrix_move_to_manip<I, J>  move_to() {
0312     return static_matrix_move_to_manip<I, J>();
0313 }
0314 
0315 /**
0316 * \brief A move matrix index manipulator.
0317 *
0318 * When member function \c manip is called the manipulator's
0319 * index will be added to the referenced' index.
0320 *
0321 * \sa move(T i, T j)
0322 */
0323 template <typename T>
0324 class matrix_move_manip: public index_manipulator<matrix_move_manip<T> > {
0325 public:
0326     BOOST_UBLAS_INLINE
0327     matrix_move_manip(T k, T l): i(k), j(l) { }
0328 
0329     template <typename V, typename K>
0330     BOOST_UBLAS_INLINE
0331     void manip(V &k, K &l) const {
0332         k+=i;
0333         l+=j;
0334     }
0335 private:
0336     T i, j;
0337 };
0338 
0339 /**
0340 * \brief  An object generator that returns a move matrix index manipulator
0341 *
0342 * \tparam size type
0343 * \param i The number of rows the manipulator will traverse the index when "manip"
0344 * member function is called
0345 * \param j The number of columns the manipulator will traverse the index when "manip"
0346 * member function is called
0347 * \return A move matrix manipulator
0348 *
0349 * Example:
0350 * \code:
0351 * matrix<double> A(3, 3, 0);
0352 * A <<= 1, 2, move(1,0),
0353 *            3,;
0354 * \endcode
0355 * will result in:
0356 * \code
0357 * 1 2 0
0358 * 0 0 3
0359 * 0 0 0
0360 * \endcode
0361 */
0362 template <typename T>
0363 BOOST_UBLAS_INLINE matrix_move_manip<T>  move(T i, T j) {
0364     return matrix_move_manip<T>(i, j);
0365 }
0366 
0367 /**
0368 * \brief A static move matrix index manipulator.
0369 *
0370 * When member function traverse is called the manipulator's
0371 * index will be added to the referenced' index.
0372 *
0373 * \sa move()
0374 *
0375 * \todo Doxygen has some problems with similar template functions. Correct that.
0376 */
0377 template <std::ptrdiff_t I, std::ptrdiff_t J>
0378 class static_matrix_move_manip: public index_manipulator<static_matrix_move_manip<I, J> > {
0379 public:
0380     template <typename V, typename K>
0381     BOOST_UBLAS_INLINE
0382     void manip(V &k, K &l) const {
0383         // With the equivalent expression using '+=' operator, mscv reports waring C4245:
0384         // '+=' : conversion from 'ptrdiff_t' to 'unsigned int', signed/unsigned mismatch
0385         k = k + I;
0386         l = l + J;
0387     }
0388 };
0389 
0390 /**
0391 * \brief  An object generator that returns a static "move" matrix index manipulator.
0392 *
0393 * Typically faster than the dynamic version, but can be used only when the
0394 * values are known at compile time. Negative values can be used.
0395 * \tparam I The number of rows the manipulator will trasverse the matrix assigner index.
0396 * \tparam J The number of columns the manipulator will trasverse the matrix assigner index.
0397 * \tparam size type
0398 * \return A static move matrix manipulator
0399 *
0400 * Example:
0401 * \code:
0402 * matrix<double> A(3, 3, 0);
0403 * A <<= 1, 2, move<1,0>(),
0404 *            3,;
0405 * \endcode
0406 * will result in:
0407 * \code
0408 * 1 2 0
0409 * 0 0 3
0410 * 0 0 0
0411 * \endcode
0412 *
0413 * \sa move_to()
0414 *
0415 * \todo Doxygen has some problems with similar template functions. Correct that.
0416 */
0417 template <std::ptrdiff_t I, std::ptrdiff_t J>
0418 BOOST_UBLAS_INLINE static_matrix_move_manip<I, J>  move() {
0419     return static_matrix_move_manip<I, J>();
0420 }
0421 
0422 /**
0423 * \brief A begining of row manipulator
0424 *
0425 * When member function \c manip is called the referenced
0426 * index will be be set to the begining of the row (i.e. column = 0)
0427 *
0428 * \sa begin1()
0429 */
0430 class begin1_manip: public index_manipulator<begin1_manip > {
0431 public:
0432     template <typename V, typename K>
0433     BOOST_UBLAS_INLINE
0434     void manip(V & k, K &/*l*/) const {
0435         k=0;
0436     }
0437 };
0438 
0439 /**
0440 * \brief  An object generator that returns a begin1 manipulator.
0441 *
0442 * The resulted manipulator will traverse the index to the begining
0443 * of the current column when its' \c manip member function is called.
0444 *
0445 * \return A begin1 matrix index manipulator
0446 *
0447 * Example usage:
0448 * \code:
0449 * matrix<double> A(3, 3, 0);
0450 * A <<= 1, 2, next_row(),
0451 *      3, 4, begin1(), 1;
0452 * \endcode
0453 * will result in:
0454 * \code
0455 * 1 2 1
0456 * 3 4 0
0457 * 0 0 0
0458 * \endcode
0459 * \sa begin2()
0460 */
0461 inline begin1_manip  begin1() {
0462     return begin1_manip();
0463 }
0464 
0465 /**
0466 * \brief A begining of column manipulator
0467 *
0468 * When member function \c manip is called the referenced
0469 * index will be be set to the begining of the column (i.e. row = 0).
0470 *
0471 *
0472 * \sa begin2()
0473 */
0474 class begin2_manip: public index_manipulator<begin2_manip > {
0475 public:
0476     template <typename V, typename K>
0477     BOOST_UBLAS_INLINE
0478     void manip(V &/*k*/, K &l) const {
0479         l=0;
0480     }
0481 };
0482 
0483 /**
0484 * \brief  An object generator that returns a begin2 manipulator to be used to traverse a matrix.
0485 *
0486 * The resulted manipulator will traverse the index to the begining
0487 * of the current row when its' \c manip member function is called.
0488 *
0489 * \return A begin2 matrix manipulator
0490 *
0491 * Example:
0492 * \code:
0493 * matrix<double> A(3, 3, 0);
0494 * A <<= 1, 2, move<1,0>(),
0495 *      3, begin2(), 1;
0496 * \endcode
0497 * will result in:
0498 * \code
0499 * 1 2 0
0500 * 1 0 3
0501 * 0 0 0
0502 * \endcode
0503 * \sa begin1() begin2_manip
0504 */
0505 inline begin2_manip  begin2() {
0506     return begin2_manip();
0507 }
0508 
0509 
0510 /**
0511 * \brief A next row matrix manipulator.
0512 *
0513 * When member function traverse is called the referenced
0514 * index will be traveresed to the begining of next row.
0515 *
0516 * \sa next_row()
0517 */
0518 class next_row_manip: public index_manipulator<next_row_manip> {
0519 public:
0520     template <typename V, typename K>
0521     BOOST_UBLAS_INLINE
0522     void manip(V &k, K &l) const {
0523         k++;
0524         l=0;
0525     }
0526 };
0527 
0528 /**
0529 * \brief  An object generator that returns a next_row manipulator.
0530 *
0531 * The resulted manipulator will traverse the index to the begining
0532 * of the next row when it's manip member function is called.
0533 *
0534 * \return A next_row matrix manipulator.
0535 *
0536 * Example:
0537 * \code:
0538 * matrix<double> A(3, 3, 0);
0539 * A <<= 1, 2, next_row(),
0540 *      3, 4;
0541 * \endcode
0542 * will result in:
0543 * \code
0544 * 1 2 0
0545 * 3 4 0
0546 * 0 0 0
0547 * \endcode
0548 * \sa next_column()
0549 */
0550 inline next_row_manip  next_row() {
0551     return next_row_manip();
0552 }
0553 
0554 /**
0555 * \brief A next column matrix manipulator.
0556 *
0557 * When member function traverse is called the referenced
0558 * index will be traveresed to the begining of next column.
0559 *
0560 * \sa next_column()
0561 */
0562 class next_column_manip: public index_manipulator<next_column_manip> {
0563 public:
0564     template <typename V, typename K>
0565     BOOST_UBLAS_INLINE
0566     void manip(V &k, K &l) const {
0567         k=0;
0568         l++;
0569     }
0570 };
0571 
0572 /**
0573 * \brief  An object generator that returns a next_row manipulator.
0574 *
0575 * The resulted manipulator will traverse the index to the begining
0576 * of the next column when it's manip member function is called.
0577 *
0578 * \return A next_column matrix manipulator.
0579 *
0580 * Example:
0581 * \code:
0582 * matrix<double> A(3, 3, 0);
0583 * A <<= 1, 2, 0,
0584 *      3, next_column(), 4;
0585 * \endcode
0586 * will result in:
0587 * \code
0588 * 1 2 4
0589 * 3 0 0
0590 * 0 0 0
0591 * \endcode
0592 *
0593 */
0594 inline next_column_manip next_column() {
0595     return next_column_manip();
0596 }
0597 
0598 /**
0599 * \brief  A wrapper for fill policy classes
0600 *
0601 */
0602 template <class T>
0603 class fill_policy_wrapper {
0604 public:
0605     typedef T type;
0606 };
0607 
0608 // Collection of the fill policies
0609 namespace fill_policy {
0610 
0611     /**
0612     * \brief  An index assign policy
0613     *
0614     * This policy is used to for the simplified ublas assign through
0615     * normal indexing.
0616     *
0617     *
0618     */
0619     class index_assign :public fill_policy_wrapper<index_assign> {
0620     public:
0621         template <class T, typename S, typename V>
0622         BOOST_UBLAS_INLINE
0623         static void apply(T &e, const S &i, const V &v) {
0624             e()(i) = v;
0625         }
0626         template <class T, typename S, typename V>
0627         BOOST_UBLAS_INLINE
0628         static void apply(T &e, const S &i, const S &j, const V &v) {
0629             e()(i, j) = v;
0630         }
0631     };
0632 
0633     /**
0634     * \brief  An index plus assign policy
0635     *
0636     * This policy is used when the assignment is desired to be followed
0637     * by an addition.
0638     *
0639     *
0640     */
0641     class index_plus_assign :public fill_policy_wrapper<index_plus_assign> {
0642     public:
0643         template <class T, typename S, typename V>
0644         BOOST_UBLAS_INLINE
0645         static void apply(T &e, const S &i, const V &v) {
0646             e()(i) += v;
0647         }
0648         template <class T, typename S, typename V>
0649         BOOST_UBLAS_INLINE
0650         static void apply(T &e, const S &i, const S &j, const V &v) {
0651             e()(i, j) += v;
0652         }
0653     };
0654 
0655     /**
0656     * \brief  An index minus assign policy
0657     *
0658     * This policy is used when the assignment is desired to be followed
0659     * by a substraction.
0660     *
0661     *
0662     */
0663     class index_minus_assign :public fill_policy_wrapper<index_minus_assign> {
0664     public:
0665         template <class T, typename S, typename V>
0666         BOOST_UBLAS_INLINE
0667         static void apply(T &e, const S &i, const V &v) {
0668             e()(i) -= v;
0669         }
0670         template <class T, typename S, typename V>
0671         BOOST_UBLAS_INLINE
0672         static void apply(T &e, const S &i, const S &j, const V &v) {
0673             e()(i, j) -= v;
0674         }
0675     };
0676 
0677     /**
0678     * \brief  The sparse push_back fill policy.
0679     *
0680     * This policy is adequate for sparse types, when fast filling is required, where indexing
0681     * assign is pretty slow.
0682 
0683     * It is important to note that push_back assign cannot be used to add elements before elements
0684     * already existing in a sparse container. To achieve that please use the sparse_insert fill policy.
0685     */
0686     class sparse_push_back :public fill_policy_wrapper<sparse_push_back > {
0687     public:
0688         template <class T, class S, class V>
0689         BOOST_UBLAS_INLINE
0690         static void apply(T &e, const S &i, const V &v) {
0691             e().push_back(i, v);
0692         }
0693         template <class T, class S, class V>
0694         BOOST_UBLAS_INLINE
0695         static void apply(T &e, const S &i, const S &j, const V &v) {
0696             e().push_back(i,j, v);
0697         }
0698     };
0699 
0700     /**
0701     * \brief  The sparse insert fill policy.
0702     *
0703     * This policy is adequate for sparse types, when fast filling is required, where indexing
0704     * assign is pretty slow. It is slower than sparse_push_back fill policy, but it can be used to
0705     * insert elements anywhere inside the container.
0706     */
0707     class sparse_insert :public fill_policy_wrapper<sparse_insert> {
0708     public:
0709         template <class T, class S, class V>
0710         BOOST_UBLAS_INLINE
0711         static void apply(T &e, const S &i, const V &v) {
0712             e().insert_element(i, v);
0713         }
0714         template <class T, class S, class V>
0715         BOOST_UBLAS_INLINE
0716         static void apply(T &e, const S &i, const S &j, const V &v) {
0717             e().insert_element(i,j, v);
0718         }
0719     };
0720 
0721 }
0722 
0723 /** \brief A wrapper for traverse policy classes
0724 *
0725 */
0726 template <class T>
0727 class traverse_policy_wrapper {
0728 public:
0729     typedef T type;
0730 };
0731 
0732 // Collection of the traverse policies
0733 namespace traverse_policy {
0734 
0735 
0736     /**
0737     * \brief  The no wrap policy.
0738     *
0739     * The no wrap policy does not allow wrapping when assigning to a matrix
0740     */
0741     struct no_wrap {
0742         /**
0743         * \brief  Element wrap method
0744         */
0745         template <class S1, class S2, class S3>
0746         BOOST_UBLAS_INLINE
0747         static void apply1(const S1 &/*s*/, S2 &/*i*/, S3 &/*j*/) {
0748         }
0749 
0750         /**
0751         * \brief  Matrix block wrap method
0752         */
0753         template <class S1, class S2, class S3>
0754         BOOST_UBLAS_INLINE
0755         static void apply2(const S1 &/*s1*/, const S1 &/*s2*/, S2 &/*i1*/, S3 &/*i2*/) {
0756         }
0757     };
0758 
0759     /**
0760     * \brief  The wrap policy.
0761     *
0762     * The wrap policy enables element wrapping when assigning to a matrix
0763     */
0764     struct wrap {
0765         /**
0766         * \brief  Element wrap method
0767         */
0768         template <class S1, class S2, class S3>
0769         BOOST_UBLAS_INLINE
0770         static void apply1(const S1 &s, S2 &i1, S3 &i2) {
0771             if (i2>=s) {
0772                 i1++;
0773                 i2=0;
0774             }
0775         }
0776 
0777         /**
0778         * \brief  Matrix block wrap method
0779         */
0780         template <class S1, class S2, class S3>
0781         BOOST_UBLAS_INLINE
0782         static void apply2(const S1 &s1, const S1 &s2, S2 &i1, S3 &i2) {
0783             if (i2>=s2) i2=0;   // Wrap to the next block
0784             else i1-=s1;        // Move up (or right) one block
0785         }
0786     };
0787 
0788     /**
0789     * \brief  The row_by_row traverse policy
0790     *
0791     * This policy is used when the assignment is desired to happen
0792     * row_major wise for performance or other reasons.
0793     *
0794     * This is the default behaviour. To change it globally please define BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
0795     * in the compilation options or in an adequate header file.
0796     *
0797     * Please see EXAMPLES_LINK for usage information.
0798     *
0799     * \todo Add examples link
0800     */
0801     template <class Wrap = wrap>
0802     class by_row_policy :public traverse_policy_wrapper<by_row_policy<Wrap> > {
0803     public:
0804         template <typename S1, typename S2>
0805         BOOST_UBLAS_INLINE
0806         static void advance(S1 &/*i*/, S2 &j) { j++;}
0807 
0808         template <class E1, class E2, typename S1, typename S2, typename S3, typename S4, typename S5>
0809         BOOST_UBLAS_INLINE
0810         static bool next(const E1 &e, const E2 &me, S1 &i, S2 &j, const S3 &/*i0*/, const S3 &j0, S4 &k, S5 &l) {
0811             l++; j++;
0812             if (l>=e().size2()) {
0813                 l=0; k++; j=j0; i++;
0814                 // It is assumed that the iteration starts from 0 and progresses only using this function from within
0815                 // an assigner object.
0816                 // Otherwise (i.e. if it is called outside the assigner object) apply2 should have been
0817                 // outside the if statement.
0818                 if (k>=e().size1()) {
0819                     j=j0+e().size2();
0820                     Wrap::apply2(e().size1(), me().size2(), i, j);
0821                     return false;
0822                 }
0823             }
0824             return true;
0825         }
0826 
0827         template <class E, typename S1, typename S2>
0828         BOOST_UBLAS_INLINE
0829         static void apply_wrap(const E& e, S1 &i, S2 &j) {
0830             Wrap::apply1(e().size2(), i, j);
0831         }
0832     };
0833 
0834     /**
0835     * \brief  The column_by_column traverse policy
0836     *
0837     * This policy is used when the assignment is desired to happen
0838     * column_major wise, for performance or other reasons.
0839     *
0840     * This is the NOT the default behaviour. To set this as the default define BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
0841     * in the compilation options or in an adequate header file.
0842     *
0843     * Please see EXAMPLES_LINK for usage information.
0844     *
0845     * \todo Add examples link
0846     */
0847     template <class Wrap = wrap>
0848     class by_column_policy :public traverse_policy_wrapper<by_column_policy<Wrap> > {
0849     public:
0850         template <typename S1, typename S2>
0851         BOOST_UBLAS_INLINE
0852         static void advance(S1 &i, S2 &/*j*/) { i++;}
0853 
0854         template <class E1, class E2, typename S1, typename S2, typename S3, typename S4, typename S5>
0855         BOOST_UBLAS_INLINE
0856         static bool next(const E1 &e, const E2 &me, S1 &i, S2 &j, const S3 &i0, const S3 &/*j0*/, S4 &k, S5 &l) {
0857             k++; i++;
0858             if (k>=e().size1()) {
0859                 k=0; l++; i=i0; j++;
0860                 // It is assumed that the iteration starts from 0 and progresses only using this function from within
0861                 // an assigner object.
0862                 // Otherwise (i.e. if it is called outside the assigner object) apply2 should have been
0863                 // outside the if statement.
0864                 if (l>=e().size2()) {
0865                     i=i0+e().size1();
0866                     Wrap::apply2(e().size2(), me().size1(), j, i);
0867                     return false;
0868                 }
0869             }
0870             return true;
0871         }
0872 
0873         template <class E, typename S1, typename S2>
0874         BOOST_UBLAS_INLINE
0875         static void apply_wrap(const E& e, S1 &i, S2 &j) {
0876             Wrap::apply1(e().size1(), j, i);
0877         }
0878     };
0879 }
0880 #ifndef BOOST_UBLAS_DEFAULT_NO_WRAP_POLICY
0881     typedef traverse_policy::wrap DEFAULT_WRAP_POLICY;
0882 #else
0883     typedef traverse_policy::no_wrap DEFAULT_WRAP_POLICY;
0884 #endif
0885 
0886 #ifndef BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
0887     typedef traverse_policy::by_row_policy<DEFAULT_WRAP_POLICY> DEFAULT_TRAVERSE_POLICY;
0888 #else
0889     typedef traverse_policy::by_column<DEFAULT_WRAP_POLICY> DEFAULT_TRAVERSE_POLICY;
0890 #endif
0891 
0892  // Traverse policy namespace
0893 namespace traverse_policy {
0894 
0895     inline by_row_policy<DEFAULT_WRAP_POLICY> by_row() {
0896     return by_row_policy<DEFAULT_WRAP_POLICY>();
0897     }
0898 
0899     inline by_row_policy<wrap> by_row_wrap() {
0900         return by_row_policy<wrap>();
0901     }
0902 
0903     inline by_row_policy<no_wrap> by_row_no_wrap() {
0904         return by_row_policy<no_wrap>();
0905     }
0906 
0907     inline by_column_policy<DEFAULT_WRAP_POLICY> by_column() {
0908         return by_column_policy<DEFAULT_WRAP_POLICY>();
0909     }
0910 
0911     inline by_column_policy<wrap> by_column_wrap() {
0912         return by_column_policy<wrap>();
0913     }
0914 
0915     inline by_column_policy<no_wrap> by_column_no_wrap() {
0916         return by_column_policy<no_wrap>();
0917     }
0918 
0919 }
0920 
0921 /**
0922 * \brief  An assigner object used to fill a vector using operator <<= and operator, (comma)
0923 *
0924 * This object is meant to be created by appropriate object generators.
0925 * Please see EXAMPLES_LINK for usage information.
0926 *
0927 * \todo Add examples link
0928 */
0929 template <class E, class Fill_Policy = fill_policy::index_assign>
0930 class vector_expression_assigner {
0931 public:
0932     typedef typename E::expression_type::value_type value_type;
0933     typedef typename E::expression_type::size_type size_type;
0934 
0935     BOOST_UBLAS_INLINE
0936     vector_expression_assigner(E &e):ve(&e), i(0) {
0937     }
0938 
0939     BOOST_UBLAS_INLINE
0940     vector_expression_assigner(size_type k, E &e):ve(&e), i(k) {
0941         // Overloaded like that so it can be differentiated from (E, val).
0942         // Otherwise there would be an ambiquity when value_type == size_type.
0943     }
0944 
0945     BOOST_UBLAS_INLINE
0946     vector_expression_assigner(E &e, value_type val):ve(&e), i(0) {
0947         operator,(val);
0948     }
0949 
0950     template <class AE>
0951     BOOST_UBLAS_INLINE
0952     vector_expression_assigner(E &e, const vector_expression<AE> &nve):ve(&e), i(0) {
0953         operator,(nve);
0954     }
0955 
0956     template <typename T>
0957     BOOST_UBLAS_INLINE
0958     vector_expression_assigner(E &e, const index_manipulator<T> &ta):ve(&e), i(0) {
0959         operator,(ta);
0960     }
0961 
0962     BOOST_UBLAS_INLINE
0963     vector_expression_assigner &operator, (const value_type& val) {
0964         apply(val);
0965         return *this;
0966     }
0967 
0968     template <class AE>
0969     BOOST_UBLAS_INLINE
0970     vector_expression_assigner &operator, (const vector_expression<AE> &nve) {
0971         for (typename AE::size_type k = 0; k!= nve().size(); k++)
0972             operator,(nve()(k));
0973         return *this;
0974     }
0975 
0976     template <typename T>
0977     BOOST_UBLAS_INLINE
0978     vector_expression_assigner &operator, (const index_manipulator<T> &ta) {
0979         ta().manip(i);
0980         return *this;
0981     }
0982 
0983     template <class T>
0984     BOOST_UBLAS_INLINE
0985     vector_expression_assigner<E, T> operator, (fill_policy_wrapper<T>) const {
0986         return vector_expression_assigner<E, T>(i, *ve);
0987     }
0988 
0989 private:
0990     BOOST_UBLAS_INLINE
0991     vector_expression_assigner &apply(const typename E::expression_type::value_type& val) {
0992         Fill_Policy::apply(*ve, i++, val);
0993         return *this;
0994     }
0995 
0996 private:
0997     E *ve;
0998     size_type i;
0999 };
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
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
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
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
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
1111     matrix_expression_assigner(E &e): me(&e), i(0), j(0) {
1112     }
1113 
1114     BOOST_UBLAS_INLINE
1115     matrix_expression_assigner(E &e, size_type k, size_type l): me(&e), i(k), j(l) {
1116     }
1117 
1118     BOOST_UBLAS_INLINE
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
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
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
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
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
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
1158     matrix_expression_assigner &operator, (const matrix_expression<AE> &nme) {
1159         return apply(nme);
1160     }
1161 
1162     template <typename T>
1163     BOOST_UBLAS_INLINE
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
1171     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
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
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
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
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
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
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
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
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
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