assignment.hpp 35 KB

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