assignment.hpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  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. #ifndef ASSIGNMENT_HPP
  9. #define ASSIGNMENT_HPP
  10. #include <boost/numeric/ublas/vector_expression.hpp>
  11. #include <boost/numeric/ublas/matrix_expression.hpp>
  12. /*! \file assignment.hpp
  13. \brief uBlas assignment operator <<=.
  14. */
  15. namespace boost { namespace numeric { namespace ublas {
  16. /** \brief A CRTP and Barton-Nackman trick index manipulator wrapper class.
  17. *
  18. * This class is not meant to be used directly.
  19. */
  20. template <class TV>
  21. class index_manipulator {
  22. public:
  23. typedef TV type;
  24. BOOST_UBLAS_INLINE
  25. const type &operator () () const {
  26. return *static_cast<const type *> (this);
  27. }
  28. BOOST_UBLAS_INLINE
  29. type &operator () () {
  30. return *static_cast<type *> (this);
  31. }
  32. };
  33. /** \brief A move_to vector index manipulator.
  34. *
  35. * When member function \c manip is called the referenced
  36. * index will be set to the manipulators' index.
  37. *
  38. * \sa move_to(T i)
  39. */
  40. template <typename T>
  41. class vector_move_to_manip: public index_manipulator<vector_move_to_manip<T> > {
  42. public:
  43. BOOST_UBLAS_INLINE
  44. vector_move_to_manip(const T &k): i(k) { }
  45. template <typename V>
  46. BOOST_UBLAS_INLINE
  47. void manip(V &k) const { k=i; }
  48. private:
  49. T i;
  50. };
  51. /** \brief An object generator that returns a move_to vector index manipulator
  52. *
  53. * \param i The element number the manipulator will move to when \c manip member function is called
  54. * \return A move_to vector manipulator
  55. *
  56. * Example usage:
  57. * \code
  58. * vector<double> a(6, 0);
  59. * a <<= 1, 2, move_to(5), 3;
  60. * \endcode
  61. * will result in:
  62. * \code
  63. * 1 2 0 0 0 3
  64. * \endcode
  65. *
  66. * \tparam T Size type
  67. * \sa move_to()
  68. */
  69. template <typename T>
  70. BOOST_UBLAS_INLINE vector_move_to_manip<T> move_to(T i) {
  71. return vector_move_to_manip<T>(i);
  72. }
  73. /** \brief A static move to vector manipulator.
  74. *
  75. * When member function \c manip is called the referenced
  76. * index will be set to the manipulators' index
  77. *
  78. * \sa move_to(T i) and move_to()
  79. */
  80. template <std::size_t I>
  81. class static_vector_move_to_manip: public index_manipulator<static_vector_move_to_manip<I> > {
  82. public:
  83. template <typename V>
  84. BOOST_UBLAS_INLINE
  85. void manip(V &k) const { k=I; }
  86. };
  87. /** \brief An object generator that returns a static move_to vector index manipulator.
  88. *
  89. * Typically faster than the dynamic version, but can be used only when the
  90. * values are known at compile time.
  91. *
  92. * \return A static move_to vector manipulator
  93. *
  94. * Example usage:
  95. * \code
  96. * vector<double> a(6, 0);
  97. * a <<= 1, 2, move_to<5>(), 3;
  98. * \endcode
  99. * will result in:
  100. * \code
  101. * 1 2 0 0 0 3
  102. * \endcode
  103. *
  104. * \tparam I The number of elements the manipulator will traverse the index when \c manip function is called
  105. */
  106. template <std::size_t I>
  107. BOOST_UBLAS_INLINE static_vector_move_to_manip<I> move_to() {
  108. return static_vector_move_to_manip<I>();
  109. }
  110. /** \brief A move vector index manipulator.
  111. *
  112. * When member function traverse is called the manipulators'
  113. * index will be added to the referenced index.
  114. *
  115. * \see move(T i)
  116. */
  117. template <typename T>
  118. class vector_move_manip: public index_manipulator<vector_move_manip<T> > {
  119. public:
  120. BOOST_UBLAS_INLINE
  121. vector_move_manip(const T &k): i(k) { }
  122. template <typename V>
  123. BOOST_UBLAS_INLINE void manip(V &k) const { k+=i; }
  124. private:
  125. T i;
  126. };
  127. /**
  128. * \brief An object generator that returns a move vector index manipulator
  129. *
  130. * \tparam T Size type
  131. * \param i The number of elements the manipulator will traverse the index when \c manip
  132. * member function is called. Negative values can be used.
  133. * \return A move vector manipulator
  134. *
  135. * Example usage:
  136. * \code
  137. * vector<double> a(6, 0);
  138. * a <<= 1, 2, move(3), 3;
  139. * \endcode
  140. * will result in:
  141. * \code
  142. * 1 2 0 0 0 3
  143. * \endcode
  144. *
  145. */
  146. template <typename T>
  147. BOOST_UBLAS_INLINE vector_move_manip<T> move(T i) {
  148. return vector_move_manip<T>(i);
  149. }
  150. /**
  151. * \brief A static move vector manipulator
  152. *
  153. * When member function \c manip is called the manipulators
  154. * index will be added to the referenced index
  155. *
  156. * \sa move()
  157. *
  158. * \todo Doxygen has some problems with similar template functions. Correct that.
  159. */
  160. template <std::ptrdiff_t I>
  161. class static_vector_move_manip: public index_manipulator<static_vector_move_manip<I> > {
  162. public:
  163. template <typename V>
  164. BOOST_UBLAS_INLINE void manip(V &k) const { k+=I; }
  165. };
  166. /**
  167. * \brief An object generator that returns a static move vector index manipulator.
  168. *
  169. * Typically faster than the dynamic version, but can be used only when the
  170. * values are known at compile time.
  171. * \tparam I The Number of elements the manipulator will traverse the index when \c manip
  172. * function is called.Negative values can be used.
  173. * \return A static move vector manipulator
  174. *
  175. * Example usage:
  176. * \code
  177. * vector<double> a(6, 0);
  178. * a <<= 1, 2, move<3>(), 3;
  179. * \endcode
  180. * will result in:
  181. * \code
  182. * 1 2 0 0 0 3
  183. * \endcode
  184. *
  185. * \todo Doxygen has some problems with similar template functions. Correct that.
  186. */
  187. template <std::ptrdiff_t I>
  188. static_vector_move_manip<I> move() {
  189. return static_vector_move_manip<I>();
  190. }
  191. /**
  192. * \brief A move_to matrix manipulator
  193. *
  194. * When member function \c manip is called the referenced
  195. * index will be set to the manipulators' index
  196. *
  197. * \sa move_to(T i, T j)
  198. *
  199. * \todo Doxygen has some problems with similar template functions. Correct that.
  200. */
  201. template <typename T>
  202. class matrix_move_to_manip: public index_manipulator<matrix_move_to_manip<T> > {
  203. public:
  204. BOOST_UBLAS_INLINE
  205. matrix_move_to_manip(T k, T l): i(k), j(l) { }
  206. template <typename V1, typename V2>
  207. BOOST_UBLAS_INLINE
  208. void manip(V1 &k, V2 &l) const {
  209. k=i;
  210. l=j;
  211. }
  212. private:
  213. T i, j;
  214. };
  215. /**
  216. * \brief An object generator that returns a "move_to" matrix index manipulator
  217. *
  218. * \tparam size type
  219. * \param i The row number the manipulator will move to when \c manip
  220. * member function is called
  221. * \param j The column number the manipulator will move to when \c manip
  222. * member function is called
  223. * \return A move matrix manipulator
  224. *
  225. * Example usage:
  226. * \code:
  227. * matrix<double> A(3, 3, 0);
  228. * A <<= 1, 2, move_to(A.size1()-1, A.size1()-1), 3;
  229. * \endcode
  230. * will result in:
  231. * \code
  232. * 1 2 0
  233. * 0 0 0
  234. * 0 0 3
  235. * \endcode
  236. * \sa move_to(T i, T j) and static_matrix_move_to_manip
  237. *
  238. * \todo Doxygen has some problems with similar template functions. Correct that.
  239. */
  240. template <typename T>
  241. BOOST_UBLAS_INLINE matrix_move_to_manip<T> move_to(T i, T j) {
  242. return matrix_move_to_manip<T>(i, j);
  243. }
  244. /**
  245. * \brief A static move_to matrix manipulator
  246. * When member function traverse is called the referenced
  247. * index will be set to the manipulators' index
  248. *
  249. * \sa move_to()
  250. *
  251. * \todo Doxygen has some problems with similar template functions. Correct that.
  252. */
  253. template <std::size_t I,std::size_t J>
  254. class static_matrix_move_to_manip: public index_manipulator<static_matrix_move_to_manip<I, J> > {
  255. public:
  256. template <typename V, typename K>
  257. BOOST_UBLAS_INLINE
  258. void manip(V &k, K &l) const {
  259. k=I;
  260. l=J;
  261. }
  262. };
  263. /**
  264. * \brief An object generator that returns a static move_to matrix index manipulator.
  265. *
  266. * Typically faster than the dynamic version, but can be used only when the
  267. * values are known at compile time.
  268. * \tparam I The row number the manipulator will set the matrix assigner index to.
  269. * \tparam J The column number the manipulator will set the matrix assigner index to.
  270. * \return A static move_to matrix manipulator
  271. *
  272. * Example usage:
  273. * \code:
  274. * matrix<double> A(3, 3, 0);
  275. * A <<= 1, 2, move_to<2,2>, 3;
  276. * \endcode
  277. * will result in:
  278. * \code
  279. * 1 2 0
  280. * 0 0 0
  281. * 0 0 3
  282. * \endcode
  283. * \sa move_to(T i, T j) and static_matrix_move_to_manip
  284. */
  285. template <std::size_t I, std::size_t J>
  286. BOOST_UBLAS_INLINE static_matrix_move_to_manip<I, J> move_to() {
  287. return static_matrix_move_to_manip<I, J>();
  288. }
  289. /**
  290. * \brief A move matrix index manipulator.
  291. *
  292. * When member function \c manip is called the manipulator's
  293. * index will be added to the referenced' index.
  294. *
  295. * \sa move(T i, T j)
  296. */
  297. template <typename T>
  298. class matrix_move_manip: public index_manipulator<matrix_move_manip<T> > {
  299. public:
  300. BOOST_UBLAS_INLINE
  301. matrix_move_manip(T k, T l): i(k), j(l) { }
  302. template <typename V, typename K>
  303. BOOST_UBLAS_INLINE
  304. void manip(V &k, K &l) const {
  305. k+=i;
  306. l+=j;
  307. }
  308. private:
  309. T i, j;
  310. };
  311. /**
  312. * \brief An object generator that returns a move matrix index manipulator
  313. *
  314. * \tparam size type
  315. * \param i The number of rows the manipulator will traverse the index when "manip"
  316. * member function is called
  317. * \param j The number of columns the manipulator will traverse the index when "manip"
  318. * member function is called
  319. * \return A move matrix manipulator
  320. *
  321. * Example:
  322. * \code:
  323. * matrix<double> A(3, 3, 0);
  324. * A <<= 1, 2, move(1,0),
  325. * 3,;
  326. * \endcode
  327. * will result in:
  328. * \code
  329. * 1 2 0
  330. * 0 0 3
  331. * 0 0 0
  332. * \endcode
  333. */
  334. template <typename T>
  335. BOOST_UBLAS_INLINE matrix_move_manip<T> move(T i, T j) {
  336. return matrix_move_manip<T>(i, j);
  337. }
  338. /**
  339. * \brief A static move matrix index manipulator.
  340. *
  341. * When member function traverse is called the manipulator's
  342. * index will be added to the referenced' index.
  343. *
  344. * \sa move()
  345. *
  346. * \todo Doxygen has some problems with similar template functions. Correct that.
  347. */
  348. template <std::ptrdiff_t I, std::ptrdiff_t J>
  349. class static_matrix_move_manip: public index_manipulator<static_matrix_move_manip<I, J> > {
  350. public:
  351. template <typename V, typename K>
  352. BOOST_UBLAS_INLINE
  353. void manip(V &k, K &l) const {
  354. k+=I;
  355. l+=J;
  356. }
  357. };
  358. /**
  359. * \brief An object generator that returns a static "move" matrix index manipulator.
  360. *
  361. * Typically faster than the dynamic version, but can be used only when the
  362. * values are known at compile time. Negative values can be used.
  363. * \tparam I The number of rows the manipulator will trasverse the matrix assigner index.
  364. * \tparam J The number of columns the manipulator will trasverse the matrix assigner index.
  365. * \tparam size type
  366. * \return A static move matrix manipulator
  367. *
  368. * Example:
  369. * \code:
  370. * matrix<double> A(3, 3, 0);
  371. * A <<= 1, 2, move<1,0>(),
  372. * 3,;
  373. * \endcode
  374. * will result in:
  375. * \code
  376. * 1 2 0
  377. * 0 0 3
  378. * 0 0 0
  379. * \endcode
  380. *
  381. * \sa move_to()
  382. *
  383. * \todo Doxygen has some problems with similar template functions. Correct that.
  384. */
  385. template <std::ptrdiff_t I, std::ptrdiff_t J>
  386. BOOST_UBLAS_INLINE static_matrix_move_manip<I, J> move() {
  387. return static_matrix_move_manip<I, J>();
  388. }
  389. /**
  390. * \brief A begining of row manipulator
  391. *
  392. * When member function \c manip is called the referenced
  393. * index will be be set to the begining of the row (i.e. column = 0)
  394. *
  395. * \sa begin1()
  396. */
  397. class begin1_manip: public index_manipulator<begin1_manip > {
  398. public:
  399. template <typename V, typename K>
  400. BOOST_UBLAS_INLINE
  401. void manip(V & k, K &/*l*/) const {
  402. k=0;
  403. }
  404. };
  405. /**
  406. * \brief An object generator that returns a begin1 manipulator.
  407. *
  408. * The resulted manipulator will traverse the index to the begining
  409. * of the current column when its' \c manip member function is called.
  410. *
  411. * \return A begin1 matrix index manipulator
  412. *
  413. * Example usage:
  414. * \code:
  415. * matrix<double> A(3, 3, 0);
  416. * A <<= 1, 2, next_row(),
  417. * 3, 4, begin1(), 1;
  418. * \endcode
  419. * will result in:
  420. * \code
  421. * 1 2 1
  422. * 3 4 0
  423. * 0 0 0
  424. * \endcode
  425. * \sa begin2()
  426. */
  427. inline begin1_manip begin1() {
  428. return begin1_manip();
  429. }
  430. /**
  431. * \brief A begining of column manipulator
  432. *
  433. * When member function \c manip is called the referenced
  434. * index will be be set to the begining of the column (i.e. row = 0).
  435. *
  436. *
  437. * \sa begin2()
  438. */
  439. class begin2_manip: public index_manipulator<begin2_manip > {
  440. public:
  441. template <typename V, typename K>
  442. BOOST_UBLAS_INLINE
  443. void manip(V &/*k*/, K &l) const {
  444. l=0;
  445. }
  446. };
  447. /**
  448. * \brief An object generator that returns a begin2 manipulator to be used to traverse a matrix.
  449. *
  450. * The resulted manipulator will traverse the index to the begining
  451. * of the current row when its' \c manip member function is called.
  452. *
  453. * \return A begin2 matrix manipulator
  454. *
  455. * Example:
  456. * \code:
  457. * matrix<double> A(3, 3, 0);
  458. * A <<= 1, 2, move<1,0>(),
  459. * 3, begin2(), 1;
  460. * \endcode
  461. * will result in:
  462. * \code
  463. * 1 2 0
  464. * 1 0 3
  465. * 0 0 0
  466. * \endcode
  467. * \sa begin1() begin2_manip
  468. */
  469. inline begin2_manip begin2() {
  470. return begin2_manip();
  471. }
  472. /**
  473. * \brief A next row matrix manipulator.
  474. *
  475. * When member function traverse is called the referenced
  476. * index will be traveresed to the begining of next row.
  477. *
  478. * \sa next_row()
  479. */
  480. class next_row_manip: public index_manipulator<next_row_manip> {
  481. public:
  482. template <typename V, typename K>
  483. BOOST_UBLAS_INLINE
  484. void manip(V &k, K &l) const {
  485. k++;
  486. l=0;
  487. }
  488. };
  489. /**
  490. * \brief An object generator that returns a next_row manipulator.
  491. *
  492. * The resulted manipulator will traverse the index to the begining
  493. * of the next row when it's manip member function is called.
  494. *
  495. * \return A next_row matrix manipulator.
  496. *
  497. * Example:
  498. * \code:
  499. * matrix<double> A(3, 3, 0);
  500. * A <<= 1, 2, next_row(),
  501. * 3, 4;
  502. * \endcode
  503. * will result in:
  504. * \code
  505. * 1 2 0
  506. * 3 4 0
  507. * 0 0 0
  508. * \endcode
  509. * \sa next_column()
  510. */
  511. inline next_row_manip next_row() {
  512. return next_row_manip();
  513. }
  514. /**
  515. * \brief A next column matrix manipulator.
  516. *
  517. * When member function traverse is called the referenced
  518. * index will be traveresed to the begining of next column.
  519. *
  520. * \sa next_column()
  521. */
  522. class next_column_manip: public index_manipulator<next_column_manip> {
  523. public:
  524. template <typename V, typename K>
  525. BOOST_UBLAS_INLINE
  526. void manip(V &k, K &l) const {
  527. k=0;
  528. l++;
  529. }
  530. };
  531. /**
  532. * \brief An object generator that returns a next_row manipulator.
  533. *
  534. * The resulted manipulator will traverse the index to the begining
  535. * of the next column when it's manip member function is called.
  536. *
  537. * \return A next_column matrix manipulator.
  538. *
  539. * Example:
  540. * \code:
  541. * matrix<double> A(3, 3, 0);
  542. * A <<= 1, 2, 0,
  543. * 3, next_column(), 4;
  544. * \endcode
  545. * will result in:
  546. * \code
  547. * 1 2 4
  548. * 3 0 0
  549. * 0 0 0
  550. * \endcode
  551. *
  552. */
  553. inline next_column_manip next_column() {
  554. return next_column_manip();
  555. }
  556. /**
  557. * \brief A wrapper for fill policy classes
  558. *
  559. */
  560. template <class T>
  561. class fill_policy_wrapper {
  562. public:
  563. typedef T type;
  564. };
  565. // Collection of the fill policies
  566. namespace fill_policy {
  567. /**
  568. * \brief An index assign policy
  569. *
  570. * This policy is used to for the simplified ublas assign through
  571. * normal indexing.
  572. *
  573. *
  574. */
  575. class index_assign :public fill_policy_wrapper<index_assign> {
  576. public:
  577. template <class T, typename S, typename V>
  578. BOOST_UBLAS_INLINE
  579. static void apply(T &e, const S &i, const V &v) {
  580. e()(i) = v;
  581. }
  582. template <class T, typename S, typename V>
  583. BOOST_UBLAS_INLINE
  584. static void apply(T &e, const S &i, const S &j, const V &v) {
  585. e()(i, j) = v;
  586. }
  587. };
  588. /**
  589. * \brief An index plus assign policy
  590. *
  591. * This policy is used when the assignment is desired to be followed
  592. * by an addition.
  593. *
  594. *
  595. */
  596. class index_plus_assign :public fill_policy_wrapper<index_plus_assign> {
  597. public:
  598. template <class T, typename S, typename V>
  599. BOOST_UBLAS_INLINE
  600. static void apply(T &e, const S &i, const V &v) {
  601. e()(i) += v;
  602. }
  603. template <class T, typename S, typename V>
  604. BOOST_UBLAS_INLINE
  605. static void apply(T &e, const S &i, const S &j, const V &v) {
  606. e()(i, j) += v;
  607. }
  608. };
  609. /**
  610. * \brief An index minus assign policy
  611. *
  612. * This policy is used when the assignment is desired to be followed
  613. * by a substraction.
  614. *
  615. *
  616. */
  617. class index_minus_assign :public fill_policy_wrapper<index_minus_assign> {
  618. public:
  619. template <class T, typename S, typename V>
  620. BOOST_UBLAS_INLINE
  621. static void apply(T &e, const S &i, const V &v) {
  622. e()(i) -= v;
  623. }
  624. template <class T, typename S, typename V>
  625. BOOST_UBLAS_INLINE
  626. static void apply(T &e, const S &i, const S &j, const V &v) {
  627. e()(i, j) -= v;
  628. }
  629. };
  630. /**
  631. * \brief The sparse push_back fill policy.
  632. *
  633. * This policy is adequate for sparse types, when fast filling is required, where indexing
  634. * assign is pretty slow.
  635. * It is important to note that push_back assign cannot be used to add elements before elements
  636. * already existing in a sparse container. To achieve that please use the sparse_insert fill policy.
  637. */
  638. class sparse_push_back :public fill_policy_wrapper<sparse_push_back > {
  639. public:
  640. template <class T, class S, class V>
  641. BOOST_UBLAS_INLINE
  642. static void apply(T &e, const S &i, const V &v) {
  643. e().push_back(i, v);
  644. }
  645. template <class T, class S, class V>
  646. BOOST_UBLAS_INLINE
  647. static void apply(T &e, const S &i, const S &j, const V &v) {
  648. e().push_back(i,j, v);
  649. }
  650. };
  651. /**
  652. * \brief The sparse insert fill policy.
  653. *
  654. * This policy is adequate for sparse types, when fast filling is required, where indexing
  655. * assign is pretty slow. It is slower than sparse_push_back fill policy, but it can be used to
  656. * insert elements anywhere inside the container.
  657. */
  658. class sparse_insert :public fill_policy_wrapper<sparse_insert> {
  659. public:
  660. template <class T, class S, class V>
  661. BOOST_UBLAS_INLINE
  662. static void apply(T &e, const S &i, const V &v) {
  663. e().insert_element(i, v);
  664. }
  665. template <class T, class S, class V>
  666. BOOST_UBLAS_INLINE
  667. static void apply(T &e, const S &i, const S &j, const V &v) {
  668. e().insert_element(i,j, v);
  669. }
  670. };
  671. }
  672. /** \brief A wrapper for traverse policy classes
  673. *
  674. */
  675. template <class T>
  676. class traverse_policy_wrapper {
  677. public:
  678. typedef T type;
  679. };
  680. // Collection of the traverse policies
  681. namespace traverse_policy {
  682. /**
  683. * \brief The no wrap policy.
  684. *
  685. * The no wrap policy does not allow wrapping when assigning to a matrix
  686. */
  687. struct no_wrap {
  688. /**
  689. * \brief Element wrap method
  690. */
  691. template <class S1, class S2, class S3>
  692. BOOST_UBLAS_INLINE
  693. static void apply1(const S1 &/*s*/, S2 &/*i*/, S3 &/*j*/) {
  694. }
  695. /**
  696. * \brief Matrix block wrap method
  697. */
  698. template <class S1, class S2, class S3>
  699. BOOST_UBLAS_INLINE
  700. static void apply2(const S1 &/*s1*/, const S1 &/*s2*/, S2 &/*i1*/, S3 &/*i2*/) {
  701. }
  702. };
  703. /**
  704. * \brief The wrap policy.
  705. *
  706. * The wrap policy enables element wrapping when assigning to a matrix
  707. */
  708. struct wrap {
  709. /**
  710. * \brief Element wrap method
  711. */
  712. template <class S1, class S2, class S3>
  713. BOOST_UBLAS_INLINE
  714. static void apply1(const S1 &s, S2 &i1, S3 &i2) {
  715. if (i2>=s) {
  716. i1++;
  717. i2=0;
  718. }
  719. }
  720. /**
  721. * \brief Matrix block wrap method
  722. */
  723. template <class S1, class S2, class S3>
  724. BOOST_UBLAS_INLINE
  725. static void apply2(const S1 &s1, const S1 &s2, S2 &i1, S3 &i2) {
  726. if (i2>=s2) i2=0; // Wrap to the next block
  727. else i1-=s1; // Move up (or right) one block
  728. }
  729. };
  730. /**
  731. * \brief The row_by_row traverse policy
  732. *
  733. * This policy is used when the assignment is desired to happen
  734. * row_major wise for performance or other reasons.
  735. *
  736. * This is the default behaviour. To change it globally please define BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
  737. * in the compilation options or in an adequate header file.
  738. *
  739. * Please see EXAMPLES_LINK for usage information.
  740. *
  741. * \todo Add examples link
  742. */
  743. template <class Wrap = wrap>
  744. class by_row_policy :public traverse_policy_wrapper<by_row_policy<Wrap> > {
  745. public:
  746. template <typename S1, typename S2>
  747. BOOST_UBLAS_INLINE
  748. static void advance(S1 &/*i*/, S2 &j) { j++;}
  749. template <class E1, class E2, typename S1, typename S2, typename S3, typename S4, typename S5>
  750. BOOST_UBLAS_INLINE
  751. static bool next(const E1 &e, const E2 &me, S1 &i, S2 &j, const S3 &/*i0*/, const S3 &j0, S4 &k, S5 &l) {
  752. l++; j++;
  753. if (l>=e().size2()) {
  754. l=0; k++; j=j0; i++;
  755. // It is assumed that the iteration starts from 0 and progresses only using this function from within
  756. // an assigner object.
  757. // Otherwise (i.e. if it is called outside the assigner object) apply2 should have been
  758. // outside the if statement.
  759. if (k>=e().size1()) {
  760. j=j0+e().size2();
  761. Wrap::apply2(e().size1(), me().size2(), i, j);
  762. return false;
  763. }
  764. }
  765. return true;
  766. }
  767. template <class E, typename S1, typename S2>
  768. BOOST_UBLAS_INLINE
  769. static void apply_wrap(const E& e, S1 &i, S2 &j) {
  770. Wrap::apply1(e().size2(), i, j);
  771. }
  772. };
  773. /**
  774. * \brief The column_by_column traverse policy
  775. *
  776. * This policy is used when the assignment is desired to happen
  777. * column_major wise, for performance or other reasons.
  778. *
  779. * This is the NOT the default behaviour. To set this as the default define BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
  780. * in the compilation options or in an adequate header file.
  781. *
  782. * Please see EXAMPLES_LINK for usage information.
  783. *
  784. * \todo Add examples link
  785. */
  786. template <class Wrap = wrap>
  787. class by_column_policy :public traverse_policy_wrapper<by_column_policy<Wrap> > {
  788. public:
  789. template <typename S1, typename S2>
  790. BOOST_UBLAS_INLINE
  791. static void advance(S1 &i, S2 &/*j*/) { i++;}
  792. template <class E1, class E2, typename S1, typename S2, typename S3, typename S4, typename S5>
  793. BOOST_UBLAS_INLINE
  794. static bool next(const E1 &e, const E2 &me, S1 &i, S2 &j, const S3 &i0, const S3 &/*j0*/, S4 &k, S5 &l) {
  795. k++; i++;
  796. if (k>=e().size1()) {
  797. k=0; l++; i=i0; j++;
  798. // It is assumed that the iteration starts from 0 and progresses only using this function from within
  799. // an assigner object.
  800. // Otherwise (i.e. if it is called outside the assigner object) apply2 should have been
  801. // outside the if statement.
  802. if (l>=e().size2()) {
  803. i=i0+e().size1();
  804. Wrap::apply2(e().size2(), me().size1(), j, i);
  805. return false;
  806. }
  807. }
  808. return true;
  809. }
  810. template <class E, typename S1, typename S2>
  811. BOOST_UBLAS_INLINE
  812. static void apply_wrap(const E& e, S1 &i, S2 &j) {
  813. Wrap::apply1(e().size1(), j, i);
  814. }
  815. };
  816. }
  817. #ifndef BOOST_UBLAS_DEFAULT_NO_WRAP_POLICY
  818. typedef traverse_policy::wrap DEFAULT_WRAP_POLICY;
  819. #else
  820. typedef traverse_policy::no_wrap DEFAULT_WRAP_POLICY;
  821. #endif
  822. #ifndef BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN
  823. typedef traverse_policy::by_row_policy<DEFAULT_WRAP_POLICY> DEFAULT_TRAVERSE_POLICY;
  824. #else
  825. typedef traverse_policy::by_column<DEFAULT_WRAP_POLICY> DEFAULT_TRAVERSE_POLICY;
  826. #endif
  827. // Traverse policy namespace
  828. namespace traverse_policy {
  829. inline by_row_policy<DEFAULT_WRAP_POLICY> by_row() {
  830. return by_row_policy<DEFAULT_WRAP_POLICY>();
  831. }
  832. inline by_row_policy<wrap> by_row_wrap() {
  833. return by_row_policy<wrap>();
  834. }
  835. inline by_row_policy<no_wrap> by_row_no_wrap() {
  836. return by_row_policy<no_wrap>();
  837. }
  838. inline by_column_policy<DEFAULT_WRAP_POLICY> by_column() {
  839. return by_column_policy<DEFAULT_WRAP_POLICY>();
  840. }
  841. inline by_column_policy<wrap> by_column_wrap() {
  842. return by_column_policy<wrap>();
  843. }
  844. inline by_column_policy<no_wrap> by_column_no_wrap() {
  845. return by_column_policy<no_wrap>();
  846. }
  847. }
  848. /**
  849. * \brief An assigner object used to fill a vector using operator <<= and operator, (comma)
  850. *
  851. * This object is meant to be created by appropriate object generators.
  852. * Please see EXAMPLES_LINK for usage information.
  853. *
  854. * \todo Add examples link
  855. */
  856. template <class E, class Fill_Policy = fill_policy::index_assign>
  857. class vector_expression_assigner {
  858. public:
  859. typedef typename E::expression_type::value_type value_type;
  860. typedef typename E::expression_type::size_type size_type;
  861. BOOST_UBLAS_INLINE
  862. vector_expression_assigner(E &e):ve(e), i(0) {
  863. }
  864. BOOST_UBLAS_INLINE
  865. vector_expression_assigner(size_type k, E &e):ve(e), i(k) {
  866. // Overloaded like that so it can be differentiated from (E, val).
  867. // Otherwise there would be an ambiquity when value_type == size_type.
  868. }
  869. BOOST_UBLAS_INLINE
  870. vector_expression_assigner(E &e, value_type val):ve(e), i(0) {
  871. operator,(val);
  872. }
  873. template <class AE>
  874. BOOST_UBLAS_INLINE
  875. vector_expression_assigner(E &e, const vector_expression<AE> &nve):ve(e), i(0) {
  876. operator,(nve);
  877. }
  878. template <typename T>
  879. BOOST_UBLAS_INLINE
  880. vector_expression_assigner(E &e, const index_manipulator<T> &ta):ve(e), i(0) {
  881. operator,(ta);
  882. }
  883. BOOST_UBLAS_INLINE
  884. vector_expression_assigner &operator, (const value_type& val) {
  885. apply(val);
  886. return *this;
  887. }
  888. template <class AE>
  889. BOOST_UBLAS_INLINE
  890. vector_expression_assigner &operator, (const vector_expression<AE> &nve) {
  891. for (typename AE::size_type k = 0; k!= nve().size(); k++)
  892. operator,(nve()(k));
  893. return *this;
  894. }
  895. template <typename T>
  896. BOOST_UBLAS_INLINE
  897. vector_expression_assigner &operator, (const index_manipulator<T> &ta) {
  898. ta().manip(i);
  899. return *this;
  900. }
  901. template <class T>
  902. BOOST_UBLAS_INLINE
  903. vector_expression_assigner<E, T> operator, (fill_policy_wrapper<T>) const {
  904. return vector_expression_assigner<E, T>(i, ve);
  905. }
  906. private:
  907. BOOST_UBLAS_INLINE
  908. vector_expression_assigner &apply(const typename E::expression_type::value_type& val) {
  909. Fill_Policy::apply(ve, i++, val);
  910. return *this;
  911. }
  912. private:
  913. E &ve;
  914. size_type i;
  915. };
  916. /*
  917. // The following static assigner is about 30% slower than the dynamic one, probably due to the recursive creation of assigner objects.
  918. // It remains commented here for future reference.
  919. template <class E, std::size_t I=0>
  920. class static_vector_expression_assigner {
  921. public:
  922. typedef typename E::expression_type::value_type value_type;
  923. typedef typename E::expression_type::size_type size_type;
  924. BOOST_UBLAS_INLINE
  925. static_vector_expression_assigner(E &e):ve(e) {
  926. }
  927. BOOST_UBLAS_INLINE
  928. static_vector_expression_assigner(E &e, value_type val):ve(e) {
  929. operator,(val);
  930. }
  931. BOOST_UBLAS_INLINE
  932. static_vector_expression_assigner<E, I+1> operator, (const value_type& val) {
  933. return apply(val);
  934. }
  935. private:
  936. BOOST_UBLAS_INLINE
  937. static_vector_expression_assigner<E, I+1> apply(const typename E::expression_type::value_type& val) {
  938. ve()(I)=val;
  939. return static_vector_expression_assigner<E, I+1>(ve);
  940. }
  941. private:
  942. E &ve;
  943. };
  944. template <class E>
  945. BOOST_UBLAS_INLINE
  946. static_vector_expression_assigner<vector_expression<E>, 1 > test_static(vector_expression<E> &v, const typename E::value_type &val) {
  947. v()(0)=val;
  948. return static_vector_expression_assigner<vector_expression<E>, 1 >(v);
  949. }
  950. */
  951. /**
  952. * \brief A vector_expression_assigner generator used with operator<<= for simple types
  953. *
  954. * Please see EXAMPLES_LINK for usage information.
  955. *
  956. * \todo Add examples link
  957. */
  958. template <class E>
  959. BOOST_UBLAS_INLINE
  960. vector_expression_assigner<vector_expression<E> > operator<<=(vector_expression<E> &v, const typename E::value_type &val) {
  961. return vector_expression_assigner<vector_expression<E> >(v,val);
  962. }
  963. /**
  964. * \brief ! A vector_expression_assigner generator used with operator<<= for vector expressions
  965. *
  966. * Please see EXAMPLES_LINK for usage information.
  967. *
  968. * \todo Add examples link
  969. */
  970. template <class E1, class E2>
  971. BOOST_UBLAS_INLINE
  972. vector_expression_assigner<vector_expression<E1> > operator<<=(vector_expression<E1> &v, const vector_expression<E2> &ve) {
  973. return vector_expression_assigner<vector_expression<E1> >(v,ve);
  974. }
  975. /**
  976. * \brief A vector_expression_assigner generator used with operator<<= for traverse manipulators
  977. *
  978. * Please see EXAMPLES_LINK for usage information.
  979. *
  980. * \todo Add examples link
  981. */
  982. template <class E, typename T>
  983. BOOST_UBLAS_INLINE
  984. vector_expression_assigner<vector_expression<E> > operator<<=(vector_expression<E> &v, const index_manipulator<T> &nv) {
  985. return vector_expression_assigner<vector_expression<E> >(v,nv);
  986. }
  987. /**
  988. * \brief A vector_expression_assigner generator used with operator<<= for choice of fill policy
  989. *
  990. * Please see EXAMPLES_LINK for usage information.
  991. *
  992. * \todo Add examples link
  993. */
  994. template <class E, typename T>
  995. BOOST_UBLAS_INLINE
  996. vector_expression_assigner<vector_expression<E>, T> operator<<=(vector_expression<E> &v, fill_policy_wrapper<T>) {
  997. return vector_expression_assigner<vector_expression<E>, T>(v);
  998. }
  999. /**
  1000. * \brief An assigner object used to fill a vector using operator <<= and operator, (comma)
  1001. *
  1002. * This object is meant to be created by appropriate object generators.
  1003. * Please see EXAMPLES_LINK for usage information.
  1004. *
  1005. * \todo Add examples link
  1006. */
  1007. template <class E, class Fill_Policy = fill_policy::index_assign, class Traverse_Policy = DEFAULT_TRAVERSE_POLICY >
  1008. class matrix_expression_assigner {
  1009. public:
  1010. typedef typename E::expression_type::size_type size_type;
  1011. BOOST_UBLAS_INLINE
  1012. matrix_expression_assigner(E &e): me(e), i(0), j(0) {
  1013. }
  1014. BOOST_UBLAS_INLINE
  1015. matrix_expression_assigner(E &e, size_type k, size_type l): me(e), i(k), j(l) {
  1016. }
  1017. BOOST_UBLAS_INLINE
  1018. matrix_expression_assigner(E &e, typename E::expression_type::value_type val): me(e), i(0), j(0) {
  1019. operator,(val);
  1020. }
  1021. template <class AE>
  1022. BOOST_UBLAS_INLINE
  1023. matrix_expression_assigner(E &e, const vector_expression<AE> &nve):me(e), i(0), j(0) {
  1024. operator,(nve);
  1025. }
  1026. template <class AE>
  1027. BOOST_UBLAS_INLINE
  1028. matrix_expression_assigner(E &e, const matrix_expression<AE> &nme):me(e), i(0), j(0) {
  1029. operator,(nme);
  1030. }
  1031. template <typename T>
  1032. BOOST_UBLAS_INLINE
  1033. matrix_expression_assigner(E &e, const index_manipulator<T> &ta):me(e), i(0), j(0) {
  1034. operator,(ta);
  1035. }
  1036. BOOST_UBLAS_INLINE
  1037. matrix_expression_assigner &operator, (const typename E::expression_type::value_type& val) {
  1038. Traverse_Policy::apply_wrap(me, i ,j);
  1039. return apply(val);
  1040. }
  1041. template <class AE>
  1042. BOOST_UBLAS_INLINE
  1043. matrix_expression_assigner &operator, (const vector_expression<AE> &nve) {
  1044. for (typename AE::size_type k = 0; k!= nve().size(); k++) {
  1045. operator,(nve()(k));
  1046. }
  1047. return *this;
  1048. }
  1049. template <class AE>
  1050. BOOST_UBLAS_INLINE
  1051. matrix_expression_assigner &operator, (const matrix_expression<AE> &nme) {
  1052. return apply(nme);
  1053. }
  1054. template <typename T>
  1055. BOOST_UBLAS_INLINE
  1056. matrix_expression_assigner &operator, (const index_manipulator<T> &ta) {
  1057. ta().manip(i, j);
  1058. return *this;
  1059. }
  1060. template <class T>
  1061. BOOST_UBLAS_INLINE
  1062. matrix_expression_assigner<E, T, Traverse_Policy> operator, (fill_policy_wrapper<T>) const {
  1063. return matrix_expression_assigner<E, T, Traverse_Policy>(me, i, j);
  1064. }
  1065. template <class T>
  1066. BOOST_UBLAS_INLINE
  1067. matrix_expression_assigner<E, Fill_Policy, T> operator, (traverse_policy_wrapper<T>) {
  1068. Traverse_Policy::apply_wrap(me, i ,j);
  1069. return matrix_expression_assigner<E, Fill_Policy, T>(me, i, j);
  1070. }
  1071. private:
  1072. BOOST_UBLAS_INLINE
  1073. matrix_expression_assigner &apply(const typename E::expression_type::value_type& val) {
  1074. Fill_Policy::apply(me, i, j, val);
  1075. Traverse_Policy::advance(i,j);
  1076. return *this;
  1077. }
  1078. template <class AE>
  1079. BOOST_UBLAS_INLINE
  1080. matrix_expression_assigner &apply(const matrix_expression<AE> &nme) {
  1081. size_type bi = i;
  1082. size_type bj = j;
  1083. typename AE::size_type k=0, l=0;
  1084. Fill_Policy::apply(me, i, j, nme()(k, l));
  1085. while (Traverse_Policy::next(nme, me, i, j, bi, bj, k, l))
  1086. Fill_Policy::apply(me, i, j, nme()(k, l));
  1087. return *this;
  1088. }
  1089. private:
  1090. E &me;
  1091. size_type i, j;
  1092. };
  1093. /**
  1094. * \brief A matrix_expression_assigner generator used with operator<<= for simple types
  1095. *
  1096. * Please see EXAMPLES_LINK for usage information.
  1097. *
  1098. * \todo Add examples link
  1099. */
  1100. template <class E>
  1101. BOOST_UBLAS_INLINE
  1102. matrix_expression_assigner<matrix_expression<E> > operator<<=(matrix_expression<E> &me, const typename E::value_type &val) {
  1103. return matrix_expression_assigner<matrix_expression<E> >(me,val);
  1104. }
  1105. /**
  1106. * \brief A matrix_expression_assigner generator used with operator<<= for choice of fill policy
  1107. *
  1108. * Please see EXAMPLES_LINK for usage information.
  1109. *
  1110. * \todo Add examples link
  1111. */
  1112. template <class E, typename T>
  1113. BOOST_UBLAS_INLINE
  1114. matrix_expression_assigner<matrix_expression<E>, T> operator<<=(matrix_expression<E> &me, fill_policy_wrapper<T>) {
  1115. return matrix_expression_assigner<matrix_expression<E>, T>(me);
  1116. }
  1117. /**
  1118. * \brief A matrix_expression_assigner generator used with operator<<= for traverse manipulators
  1119. *
  1120. * Please see EXAMPLES_LINK for usage information.
  1121. *
  1122. * \todo Add examples link
  1123. */
  1124. template <class E, typename T>
  1125. BOOST_UBLAS_INLINE
  1126. matrix_expression_assigner<matrix_expression<E> > operator<<=(matrix_expression<E> &me, const index_manipulator<T> &ta) {
  1127. return matrix_expression_assigner<matrix_expression<E> >(me,ta);
  1128. }
  1129. /**
  1130. * \brief A matrix_expression_assigner generator used with operator<<= for traverse manipulators
  1131. *
  1132. * Please see EXAMPLES_LINK for usage information.
  1133. *
  1134. * \todo Add examples link
  1135. */
  1136. template <class E, typename T>
  1137. BOOST_UBLAS_INLINE
  1138. matrix_expression_assigner<matrix_expression<E>, fill_policy::index_assign, T> operator<<=(matrix_expression<E> &me, traverse_policy_wrapper<T>) {
  1139. return matrix_expression_assigner<matrix_expression<E>, fill_policy::index_assign, T>(me);
  1140. }
  1141. /**
  1142. * \brief A matrix_expression_assigner generator used with operator<<= for vector expressions
  1143. *
  1144. * Please see EXAMPLES_LINK for usage information.
  1145. *
  1146. * \todo Add examples link
  1147. */
  1148. template <class E1, class E2>
  1149. BOOST_UBLAS_INLINE
  1150. matrix_expression_assigner<matrix_expression<E1> > operator<<=(matrix_expression<E1> &me, const vector_expression<E2> &ve) {
  1151. return matrix_expression_assigner<matrix_expression<E1> >(me,ve);
  1152. }
  1153. /**
  1154. * \brief A matrix_expression_assigner generator used with operator<<= for matrix expressions
  1155. *
  1156. * Please see EXAMPLES_LINK for usage information.
  1157. *
  1158. * \todo Add examples link
  1159. */
  1160. template <class E1, class E2>
  1161. BOOST_UBLAS_INLINE
  1162. matrix_expression_assigner<matrix_expression<E1> > operator<<=(matrix_expression<E1> &me1, const matrix_expression<E2> &me2) {
  1163. return matrix_expression_assigner<matrix_expression<E1> >(me1,me2);
  1164. }
  1165. } } }
  1166. #endif // ASSIGNMENT_HPP