assignment.hpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282
  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