triangular.hpp 98 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604
  1. //
  2. // Copyright (c) 2000-2002
  3. // Joerg Walter, Mathias Koch
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // The authors gratefully acknowledge the support of
  10. // GeNeSys mbH & Co. KG in producing this work.
  11. //
  12. #ifndef _BOOST_UBLAS_TRIANGULAR_
  13. #define _BOOST_UBLAS_TRIANGULAR_
  14. #include <boost/numeric/ublas/matrix.hpp>
  15. #include <boost/numeric/ublas/detail/temporary.hpp>
  16. #include <boost/type_traits/remove_const.hpp>
  17. // Iterators based on ideas of Jeremy Siek
  18. namespace boost { namespace numeric { namespace ublas {
  19. namespace detail {
  20. using namespace boost::numeric::ublas;
  21. // Matrix resizing algorithm
  22. template <class L, class T, class M>
  23. BOOST_UBLAS_INLINE
  24. void matrix_resize_preserve (M& m, M& temporary) {
  25. typedef L layout_type;
  26. typedef T triangular_type;
  27. typedef typename M::size_type size_type;
  28. const size_type msize1 (m.size1 ()); // original size
  29. const size_type msize2 (m.size2 ());
  30. const size_type size1 (temporary.size1 ()); // new size is specified by temporary
  31. const size_type size2 (temporary.size2 ());
  32. // Common elements to preserve
  33. const size_type size1_min = (std::min) (size1, msize1);
  34. const size_type size2_min = (std::min) (size2, msize2);
  35. // Order for major and minor sizes
  36. const size_type major_size = layout_type::size_M (size1_min, size2_min);
  37. const size_type minor_size = layout_type::size_m (size1_min, size2_min);
  38. // Indexing copy over major
  39. for (size_type major = 0; major != major_size; ++major) {
  40. for (size_type minor = 0; minor != minor_size; ++minor) {
  41. // find indexes - use invertability of element_ functions
  42. const size_type i1 = layout_type::index_M(major, minor);
  43. const size_type i2 = layout_type::index_m(major, minor);
  44. if ( triangular_type::other(i1,i2) ) {
  45. temporary.data () [triangular_type::element (layout_type (), i1, size1, i2, size2)] =
  46. m.data() [triangular_type::element (layout_type (), i1, msize1, i2, msize2)];
  47. }
  48. }
  49. }
  50. m.assign_temporary (temporary);
  51. }
  52. }
  53. /** \brief A triangular matrix of values of type \c T.
  54. *
  55. * For a \f$(n \times n )\f$-dimensional lower triangular matrix and if \f$0 \leq i < n\f$, \f$0 \leq j < n\f$ and \f$i>j\f$ holds,
  56. * \f$m_{i,j}=0\f$. Furthermore if \f$m_{i,i}=1\f$, the matrix is called unit lower triangular.
  57. *
  58. * For a \f$(n \times n )\f$-dimensional upper triangular matrix and if \f$0 \leq i < n\f$, \f$0 \leq j < n\f$ and \f$i<j\f$ holds,
  59. * \f$m_{i,j}=0\f$. Furthermore if \f$m_{i,i}=1\f$, the matrix is called unit upper triangular.
  60. *
  61. * The default storage for triangular matrices is packed. Orientation and storage can also be specified.
  62. * Default is \c row_major and and unbounded_array. It is \b not required by the storage to initialize
  63. * elements of the matrix.
  64. *
  65. * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
  66. * \tparam TRI the type of the triangular matrix. It can either be \c lower or \c upper. Default is \c lower
  67. * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
  68. * \tparam A the type of Storage array. Default is \c unbounded_array
  69. */
  70. template<class T, class TRI, class L, class A>
  71. class triangular_matrix:
  72. public matrix_container<triangular_matrix<T, TRI, L, A> > {
  73. typedef T *pointer;
  74. typedef TRI triangular_type;
  75. typedef L layout_type;
  76. typedef triangular_matrix<T, TRI, L, A> self_type;
  77. public:
  78. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  79. using matrix_container<self_type>::operator ();
  80. #endif
  81. typedef typename A::size_type size_type;
  82. typedef typename A::difference_type difference_type;
  83. typedef T value_type;
  84. typedef const T &const_reference;
  85. typedef T &reference;
  86. typedef A array_type;
  87. typedef const matrix_reference<const self_type> const_closure_type;
  88. typedef matrix_reference<self_type> closure_type;
  89. typedef vector<T, A> vector_temporary_type;
  90. typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix
  91. typedef packed_tag storage_category;
  92. typedef typename L::orientation_category orientation_category;
  93. // Construction and destruction
  94. BOOST_UBLAS_INLINE
  95. triangular_matrix ():
  96. matrix_container<self_type> (),
  97. size1_ (0), size2_ (0), data_ (0) {}
  98. BOOST_UBLAS_INLINE
  99. triangular_matrix (size_type size1, size_type size2):
  100. matrix_container<self_type> (),
  101. size1_ (size1), size2_ (size2), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
  102. }
  103. BOOST_UBLAS_INLINE
  104. triangular_matrix (size_type size1, size_type size2, const array_type &data):
  105. matrix_container<self_type> (),
  106. size1_ (size1), size2_ (size2), data_ (data) {}
  107. BOOST_UBLAS_INLINE
  108. triangular_matrix (const triangular_matrix &m):
  109. matrix_container<self_type> (),
  110. size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
  111. template<class AE>
  112. BOOST_UBLAS_INLINE
  113. triangular_matrix (const matrix_expression<AE> &ae):
  114. matrix_container<self_type> (),
  115. size1_ (ae ().size1 ()), size2_ (ae ().size2 ()),
  116. data_ (triangular_type::packed_size (layout_type (), size1_, size2_)) {
  117. matrix_assign<scalar_assign> (*this, ae);
  118. }
  119. // Accessors
  120. BOOST_UBLAS_INLINE
  121. size_type size1 () const {
  122. return size1_;
  123. }
  124. BOOST_UBLAS_INLINE
  125. size_type size2 () const {
  126. return size2_;
  127. }
  128. // Storage accessors
  129. BOOST_UBLAS_INLINE
  130. const array_type &data () const {
  131. return data_;
  132. }
  133. BOOST_UBLAS_INLINE
  134. array_type &data () {
  135. return data_;
  136. }
  137. // Resizing
  138. BOOST_UBLAS_INLINE
  139. void resize (size_type size1, size_type size2, bool preserve = true) {
  140. if (preserve) {
  141. self_type temporary (size1, size2);
  142. detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary);
  143. }
  144. else {
  145. data ().resize (triangular_type::packed_size (layout_type (), size1, size2));
  146. size1_ = size1;
  147. size2_ = size2;
  148. }
  149. }
  150. BOOST_UBLAS_INLINE
  151. void resize_packed_preserve (size_type size1, size_type size2) {
  152. size1_ = size1;
  153. size2_ = size2;
  154. data ().resize (triangular_type::packed_size (layout_type (), size1_, size2_), value_type ());
  155. }
  156. // Element access
  157. BOOST_UBLAS_INLINE
  158. const_reference operator () (size_type i, size_type j) const {
  159. BOOST_UBLAS_CHECK (i < size1_, bad_index ());
  160. BOOST_UBLAS_CHECK (j < size2_, bad_index ());
  161. if (triangular_type::other (i, j))
  162. return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
  163. else if (triangular_type::one (i, j))
  164. return one_;
  165. else
  166. return zero_;
  167. }
  168. BOOST_UBLAS_INLINE
  169. reference at_element (size_type i, size_type j) {
  170. BOOST_UBLAS_CHECK (i < size1_, bad_index ());
  171. BOOST_UBLAS_CHECK (j < size2_, bad_index ());
  172. return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
  173. }
  174. BOOST_UBLAS_INLINE
  175. reference operator () (size_type i, size_type j) {
  176. BOOST_UBLAS_CHECK (i < size1_, bad_index ());
  177. BOOST_UBLAS_CHECK (j < size2_, bad_index ());
  178. if (!triangular_type::other (i, j)) {
  179. bad_index ().raise ();
  180. // NEVER reached
  181. }
  182. return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
  183. }
  184. // Element assignment
  185. BOOST_UBLAS_INLINE
  186. reference insert_element (size_type i, size_type j, const_reference t) {
  187. return (operator () (i, j) = t);
  188. }
  189. BOOST_UBLAS_INLINE
  190. void erase_element (size_type i, size_type j) {
  191. operator () (i, j) = value_type/*zero*/();
  192. }
  193. // Zeroing
  194. BOOST_UBLAS_INLINE
  195. void clear () {
  196. // data ().clear ();
  197. std::fill (data ().begin (), data ().end (), value_type/*zero*/());
  198. }
  199. // Assignment
  200. BOOST_UBLAS_INLINE
  201. triangular_matrix &operator = (const triangular_matrix &m) {
  202. size1_ = m.size1_;
  203. size2_ = m.size2_;
  204. data () = m.data ();
  205. return *this;
  206. }
  207. BOOST_UBLAS_INLINE
  208. triangular_matrix &assign_temporary (triangular_matrix &m) {
  209. swap (m);
  210. return *this;
  211. }
  212. template<class AE>
  213. BOOST_UBLAS_INLINE
  214. triangular_matrix &operator = (const matrix_expression<AE> &ae) {
  215. self_type temporary (ae);
  216. return assign_temporary (temporary);
  217. }
  218. template<class AE>
  219. BOOST_UBLAS_INLINE
  220. triangular_matrix &assign (const matrix_expression<AE> &ae) {
  221. matrix_assign<scalar_assign> (*this, ae);
  222. return *this;
  223. }
  224. template<class AE>
  225. BOOST_UBLAS_INLINE
  226. triangular_matrix& operator += (const matrix_expression<AE> &ae) {
  227. self_type temporary (*this + ae);
  228. return assign_temporary (temporary);
  229. }
  230. template<class AE>
  231. BOOST_UBLAS_INLINE
  232. triangular_matrix &plus_assign (const matrix_expression<AE> &ae) {
  233. matrix_assign<scalar_plus_assign> (*this, ae);
  234. return *this;
  235. }
  236. template<class AE>
  237. BOOST_UBLAS_INLINE
  238. triangular_matrix& operator -= (const matrix_expression<AE> &ae) {
  239. self_type temporary (*this - ae);
  240. return assign_temporary (temporary);
  241. }
  242. template<class AE>
  243. BOOST_UBLAS_INLINE
  244. triangular_matrix &minus_assign (const matrix_expression<AE> &ae) {
  245. matrix_assign<scalar_minus_assign> (*this, ae);
  246. return *this;
  247. }
  248. template<class AT>
  249. BOOST_UBLAS_INLINE
  250. triangular_matrix& operator *= (const AT &at) {
  251. matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  252. return *this;
  253. }
  254. template<class AT>
  255. BOOST_UBLAS_INLINE
  256. triangular_matrix& operator /= (const AT &at) {
  257. matrix_assign_scalar<scalar_divides_assign> (*this, at);
  258. return *this;
  259. }
  260. // Swapping
  261. BOOST_UBLAS_INLINE
  262. void swap (triangular_matrix &m) {
  263. if (this != &m) {
  264. // BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ());
  265. std::swap (size1_, m.size1_);
  266. std::swap (size2_, m.size2_);
  267. data ().swap (m.data ());
  268. }
  269. }
  270. BOOST_UBLAS_INLINE
  271. friend void swap (triangular_matrix &m1, triangular_matrix &m2) {
  272. m1.swap (m2);
  273. }
  274. // Iterator types
  275. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  276. typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
  277. typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
  278. typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
  279. typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
  280. #else
  281. class const_iterator1;
  282. class iterator1;
  283. class const_iterator2;
  284. class iterator2;
  285. #endif
  286. typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  287. typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  288. typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  289. typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  290. // Element lookup
  291. BOOST_UBLAS_INLINE
  292. const_iterator1 find1 (int rank, size_type i, size_type j) const {
  293. if (rank == 1)
  294. i = triangular_type::restrict1 (i, j, size1_, size2_);
  295. if (rank == 0)
  296. i = triangular_type::global_restrict1 (i, size1_, j, size2_);
  297. return const_iterator1 (*this, i, j);
  298. }
  299. BOOST_UBLAS_INLINE
  300. iterator1 find1 (int rank, size_type i, size_type j) {
  301. if (rank == 1)
  302. i = triangular_type::mutable_restrict1 (i, j, size1_, size2_);
  303. if (rank == 0)
  304. i = triangular_type::global_mutable_restrict1 (i, size1_, j, size2_);
  305. return iterator1 (*this, i, j);
  306. }
  307. BOOST_UBLAS_INLINE
  308. const_iterator2 find2 (int rank, size_type i, size_type j) const {
  309. if (rank == 1)
  310. j = triangular_type::restrict2 (i, j, size1_, size2_);
  311. if (rank == 0)
  312. j = triangular_type::global_restrict2 (i, size1_, j, size2_);
  313. return const_iterator2 (*this, i, j);
  314. }
  315. BOOST_UBLAS_INLINE
  316. iterator2 find2 (int rank, size_type i, size_type j) {
  317. if (rank == 1)
  318. j = triangular_type::mutable_restrict2 (i, j, size1_, size2_);
  319. if (rank == 0)
  320. j = triangular_type::global_mutable_restrict2 (i, size1_, j, size2_);
  321. return iterator2 (*this, i, j);
  322. }
  323. // Iterators simply are indices.
  324. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  325. class const_iterator1:
  326. public container_const_reference<triangular_matrix>,
  327. public random_access_iterator_base<packed_random_access_iterator_tag,
  328. const_iterator1, value_type> {
  329. public:
  330. typedef typename triangular_matrix::value_type value_type;
  331. typedef typename triangular_matrix::difference_type difference_type;
  332. typedef typename triangular_matrix::const_reference reference;
  333. typedef const typename triangular_matrix::pointer pointer;
  334. typedef const_iterator2 dual_iterator_type;
  335. typedef const_reverse_iterator2 dual_reverse_iterator_type;
  336. // Construction and destruction
  337. BOOST_UBLAS_INLINE
  338. const_iterator1 ():
  339. container_const_reference<self_type> (), it1_ (), it2_ () {}
  340. BOOST_UBLAS_INLINE
  341. const_iterator1 (const self_type &m, size_type it1, size_type it2):
  342. container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  343. BOOST_UBLAS_INLINE
  344. const_iterator1 (const iterator1 &it):
  345. container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
  346. // Arithmetic
  347. BOOST_UBLAS_INLINE
  348. const_iterator1 &operator ++ () {
  349. ++ it1_;
  350. return *this;
  351. }
  352. BOOST_UBLAS_INLINE
  353. const_iterator1 &operator -- () {
  354. -- it1_;
  355. return *this;
  356. }
  357. BOOST_UBLAS_INLINE
  358. const_iterator1 &operator += (difference_type n) {
  359. it1_ += n;
  360. return *this;
  361. }
  362. BOOST_UBLAS_INLINE
  363. const_iterator1 &operator -= (difference_type n) {
  364. it1_ -= n;
  365. return *this;
  366. }
  367. BOOST_UBLAS_INLINE
  368. difference_type operator - (const const_iterator1 &it) const {
  369. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  370. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  371. return it1_ - it.it1_;
  372. }
  373. // Dereference
  374. BOOST_UBLAS_INLINE
  375. const_reference operator * () const {
  376. return (*this) () (it1_, it2_);
  377. }
  378. BOOST_UBLAS_INLINE
  379. const_reference operator [] (difference_type n) const {
  380. return *(*this + n);
  381. }
  382. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  383. BOOST_UBLAS_INLINE
  384. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  385. typename self_type::
  386. #endif
  387. const_iterator2 begin () const {
  388. return (*this) ().find2 (1, it1_, 0);
  389. }
  390. BOOST_UBLAS_INLINE
  391. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  392. typename self_type::
  393. #endif
  394. const_iterator2 end () const {
  395. return (*this) ().find2 (1, it1_, (*this) ().size2 ());
  396. }
  397. BOOST_UBLAS_INLINE
  398. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  399. typename self_type::
  400. #endif
  401. const_reverse_iterator2 rbegin () const {
  402. return const_reverse_iterator2 (end ());
  403. }
  404. BOOST_UBLAS_INLINE
  405. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  406. typename self_type::
  407. #endif
  408. const_reverse_iterator2 rend () const {
  409. return const_reverse_iterator2 (begin ());
  410. }
  411. #endif
  412. // Indices
  413. BOOST_UBLAS_INLINE
  414. size_type index1 () const {
  415. return it1_;
  416. }
  417. BOOST_UBLAS_INLINE
  418. size_type index2 () const {
  419. return it2_;
  420. }
  421. // Assignment
  422. BOOST_UBLAS_INLINE
  423. const_iterator1 &operator = (const const_iterator1 &it) {
  424. container_const_reference<self_type>::assign (&it ());
  425. it1_ = it.it1_;
  426. it2_ = it.it2_;
  427. return *this;
  428. }
  429. // Comparison
  430. BOOST_UBLAS_INLINE
  431. bool operator == (const const_iterator1 &it) const {
  432. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  433. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  434. return it1_ == it.it1_;
  435. }
  436. BOOST_UBLAS_INLINE
  437. bool operator < (const const_iterator1 &it) const {
  438. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  439. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  440. return it1_ < it.it1_;
  441. }
  442. private:
  443. size_type it1_;
  444. size_type it2_;
  445. };
  446. #endif
  447. BOOST_UBLAS_INLINE
  448. const_iterator1 begin1 () const {
  449. return find1 (0, 0, 0);
  450. }
  451. BOOST_UBLAS_INLINE
  452. const_iterator1 end1 () const {
  453. return find1 (0, size1_, 0);
  454. }
  455. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  456. class iterator1:
  457. public container_reference<triangular_matrix>,
  458. public random_access_iterator_base<packed_random_access_iterator_tag,
  459. iterator1, value_type> {
  460. public:
  461. typedef typename triangular_matrix::value_type value_type;
  462. typedef typename triangular_matrix::difference_type difference_type;
  463. typedef typename triangular_matrix::reference reference;
  464. typedef typename triangular_matrix::pointer pointer;
  465. typedef iterator2 dual_iterator_type;
  466. typedef reverse_iterator2 dual_reverse_iterator_type;
  467. // Construction and destruction
  468. BOOST_UBLAS_INLINE
  469. iterator1 ():
  470. container_reference<self_type> (), it1_ (), it2_ () {}
  471. BOOST_UBLAS_INLINE
  472. iterator1 (self_type &m, size_type it1, size_type it2):
  473. container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  474. // Arithmetic
  475. BOOST_UBLAS_INLINE
  476. iterator1 &operator ++ () {
  477. ++ it1_;
  478. return *this;
  479. }
  480. BOOST_UBLAS_INLINE
  481. iterator1 &operator -- () {
  482. -- it1_;
  483. return *this;
  484. }
  485. BOOST_UBLAS_INLINE
  486. iterator1 &operator += (difference_type n) {
  487. it1_ += n;
  488. return *this;
  489. }
  490. BOOST_UBLAS_INLINE
  491. iterator1 &operator -= (difference_type n) {
  492. it1_ -= n;
  493. return *this;
  494. }
  495. BOOST_UBLAS_INLINE
  496. difference_type operator - (const iterator1 &it) const {
  497. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  498. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  499. return it1_ - it.it1_;
  500. }
  501. // Dereference
  502. BOOST_UBLAS_INLINE
  503. reference operator * () const {
  504. return (*this) () (it1_, it2_);
  505. }
  506. BOOST_UBLAS_INLINE
  507. reference operator [] (difference_type n) const {
  508. return *(*this + n);
  509. }
  510. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  511. BOOST_UBLAS_INLINE
  512. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  513. typename self_type::
  514. #endif
  515. iterator2 begin () const {
  516. return (*this) ().find2 (1, it1_, 0);
  517. }
  518. BOOST_UBLAS_INLINE
  519. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  520. typename self_type::
  521. #endif
  522. iterator2 end () const {
  523. return (*this) ().find2 (1, it1_, (*this) ().size2 ());
  524. }
  525. BOOST_UBLAS_INLINE
  526. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  527. typename self_type::
  528. #endif
  529. reverse_iterator2 rbegin () const {
  530. return reverse_iterator2 (end ());
  531. }
  532. BOOST_UBLAS_INLINE
  533. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  534. typename self_type::
  535. #endif
  536. reverse_iterator2 rend () const {
  537. return reverse_iterator2 (begin ());
  538. }
  539. #endif
  540. // Indices
  541. BOOST_UBLAS_INLINE
  542. size_type index1 () const {
  543. return it1_;
  544. }
  545. BOOST_UBLAS_INLINE
  546. size_type index2 () const {
  547. return it2_;
  548. }
  549. // Assignment
  550. BOOST_UBLAS_INLINE
  551. iterator1 &operator = (const iterator1 &it) {
  552. container_reference<self_type>::assign (&it ());
  553. it1_ = it.it1_;
  554. it2_ = it.it2_;
  555. return *this;
  556. }
  557. // Comparison
  558. BOOST_UBLAS_INLINE
  559. bool operator == (const iterator1 &it) const {
  560. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  561. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  562. return it1_ == it.it1_;
  563. }
  564. BOOST_UBLAS_INLINE
  565. bool operator < (const iterator1 &it) const {
  566. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  567. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  568. return it1_ < it.it1_;
  569. }
  570. private:
  571. size_type it1_;
  572. size_type it2_;
  573. friend class const_iterator1;
  574. };
  575. #endif
  576. BOOST_UBLAS_INLINE
  577. iterator1 begin1 () {
  578. return find1 (0, 0, 0);
  579. }
  580. BOOST_UBLAS_INLINE
  581. iterator1 end1 () {
  582. return find1 (0, size1_, 0);
  583. }
  584. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  585. class const_iterator2:
  586. public container_const_reference<triangular_matrix>,
  587. public random_access_iterator_base<packed_random_access_iterator_tag,
  588. const_iterator2, value_type> {
  589. public:
  590. typedef typename triangular_matrix::value_type value_type;
  591. typedef typename triangular_matrix::difference_type difference_type;
  592. typedef typename triangular_matrix::const_reference reference;
  593. typedef const typename triangular_matrix::pointer pointer;
  594. typedef const_iterator1 dual_iterator_type;
  595. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  596. // Construction and destruction
  597. BOOST_UBLAS_INLINE
  598. const_iterator2 ():
  599. container_const_reference<self_type> (), it1_ (), it2_ () {}
  600. BOOST_UBLAS_INLINE
  601. const_iterator2 (const self_type &m, size_type it1, size_type it2):
  602. container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  603. BOOST_UBLAS_INLINE
  604. const_iterator2 (const iterator2 &it):
  605. container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
  606. // Arithmetic
  607. BOOST_UBLAS_INLINE
  608. const_iterator2 &operator ++ () {
  609. ++ it2_;
  610. return *this;
  611. }
  612. BOOST_UBLAS_INLINE
  613. const_iterator2 &operator -- () {
  614. -- it2_;
  615. return *this;
  616. }
  617. BOOST_UBLAS_INLINE
  618. const_iterator2 &operator += (difference_type n) {
  619. it2_ += n;
  620. return *this;
  621. }
  622. BOOST_UBLAS_INLINE
  623. const_iterator2 &operator -= (difference_type n) {
  624. it2_ -= n;
  625. return *this;
  626. }
  627. BOOST_UBLAS_INLINE
  628. difference_type operator - (const const_iterator2 &it) const {
  629. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  630. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  631. return it2_ - it.it2_;
  632. }
  633. // Dereference
  634. BOOST_UBLAS_INLINE
  635. const_reference operator * () const {
  636. return (*this) () (it1_, it2_);
  637. }
  638. BOOST_UBLAS_INLINE
  639. const_reference operator [] (difference_type n) const {
  640. return *(*this + n);
  641. }
  642. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  643. BOOST_UBLAS_INLINE
  644. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  645. typename self_type::
  646. #endif
  647. const_iterator1 begin () const {
  648. return (*this) ().find1 (1, 0, it2_);
  649. }
  650. BOOST_UBLAS_INLINE
  651. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  652. typename self_type::
  653. #endif
  654. const_iterator1 end () const {
  655. return (*this) ().find1 (1, (*this) ().size1 (), it2_);
  656. }
  657. BOOST_UBLAS_INLINE
  658. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  659. typename self_type::
  660. #endif
  661. const_reverse_iterator1 rbegin () const {
  662. return const_reverse_iterator1 (end ());
  663. }
  664. BOOST_UBLAS_INLINE
  665. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  666. typename self_type::
  667. #endif
  668. const_reverse_iterator1 rend () const {
  669. return const_reverse_iterator1 (begin ());
  670. }
  671. #endif
  672. // Indices
  673. BOOST_UBLAS_INLINE
  674. size_type index1 () const {
  675. return it1_;
  676. }
  677. BOOST_UBLAS_INLINE
  678. size_type index2 () const {
  679. return it2_;
  680. }
  681. // Assignment
  682. BOOST_UBLAS_INLINE
  683. const_iterator2 &operator = (const const_iterator2 &it) {
  684. container_const_reference<self_type>::assign (&it ());
  685. it1_ = it.it1_;
  686. it2_ = it.it2_;
  687. return *this;
  688. }
  689. // Comparison
  690. BOOST_UBLAS_INLINE
  691. bool operator == (const const_iterator2 &it) const {
  692. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  693. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  694. return it2_ == it.it2_;
  695. }
  696. BOOST_UBLAS_INLINE
  697. bool operator < (const const_iterator2 &it) const {
  698. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  699. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  700. return it2_ < it.it2_;
  701. }
  702. private:
  703. size_type it1_;
  704. size_type it2_;
  705. };
  706. #endif
  707. BOOST_UBLAS_INLINE
  708. const_iterator2 begin2 () const {
  709. return find2 (0, 0, 0);
  710. }
  711. BOOST_UBLAS_INLINE
  712. const_iterator2 end2 () const {
  713. return find2 (0, 0, size2_);
  714. }
  715. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  716. class iterator2:
  717. public container_reference<triangular_matrix>,
  718. public random_access_iterator_base<packed_random_access_iterator_tag,
  719. iterator2, value_type> {
  720. public:
  721. typedef typename triangular_matrix::value_type value_type;
  722. typedef typename triangular_matrix::difference_type difference_type;
  723. typedef typename triangular_matrix::reference reference;
  724. typedef typename triangular_matrix::pointer pointer;
  725. typedef iterator1 dual_iterator_type;
  726. typedef reverse_iterator1 dual_reverse_iterator_type;
  727. // Construction and destruction
  728. BOOST_UBLAS_INLINE
  729. iterator2 ():
  730. container_reference<self_type> (), it1_ (), it2_ () {}
  731. BOOST_UBLAS_INLINE
  732. iterator2 (self_type &m, size_type it1, size_type it2):
  733. container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  734. // Arithmetic
  735. BOOST_UBLAS_INLINE
  736. iterator2 &operator ++ () {
  737. ++ it2_;
  738. return *this;
  739. }
  740. BOOST_UBLAS_INLINE
  741. iterator2 &operator -- () {
  742. -- it2_;
  743. return *this;
  744. }
  745. BOOST_UBLAS_INLINE
  746. iterator2 &operator += (difference_type n) {
  747. it2_ += n;
  748. return *this;
  749. }
  750. BOOST_UBLAS_INLINE
  751. iterator2 &operator -= (difference_type n) {
  752. it2_ -= n;
  753. return *this;
  754. }
  755. BOOST_UBLAS_INLINE
  756. difference_type operator - (const iterator2 &it) const {
  757. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  758. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  759. return it2_ - it.it2_;
  760. }
  761. // Dereference
  762. BOOST_UBLAS_INLINE
  763. reference operator * () const {
  764. return (*this) () (it1_, it2_);
  765. }
  766. BOOST_UBLAS_INLINE
  767. reference operator [] (difference_type n) const {
  768. return *(*this + n);
  769. }
  770. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  771. BOOST_UBLAS_INLINE
  772. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  773. typename self_type::
  774. #endif
  775. iterator1 begin () const {
  776. return (*this) ().find1 (1, 0, it2_);
  777. }
  778. BOOST_UBLAS_INLINE
  779. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  780. typename self_type::
  781. #endif
  782. iterator1 end () const {
  783. return (*this) ().find1 (1, (*this) ().size1 (), it2_);
  784. }
  785. BOOST_UBLAS_INLINE
  786. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  787. typename self_type::
  788. #endif
  789. reverse_iterator1 rbegin () const {
  790. return reverse_iterator1 (end ());
  791. }
  792. BOOST_UBLAS_INLINE
  793. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  794. typename self_type::
  795. #endif
  796. reverse_iterator1 rend () const {
  797. return reverse_iterator1 (begin ());
  798. }
  799. #endif
  800. // Indices
  801. BOOST_UBLAS_INLINE
  802. size_type index1 () const {
  803. return it1_;
  804. }
  805. BOOST_UBLAS_INLINE
  806. size_type index2 () const {
  807. return it2_;
  808. }
  809. // Assignment
  810. BOOST_UBLAS_INLINE
  811. iterator2 &operator = (const iterator2 &it) {
  812. container_reference<self_type>::assign (&it ());
  813. it1_ = it.it1_;
  814. it2_ = it.it2_;
  815. return *this;
  816. }
  817. // Comparison
  818. BOOST_UBLAS_INLINE
  819. bool operator == (const iterator2 &it) const {
  820. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  821. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  822. return it2_ == it.it2_;
  823. }
  824. BOOST_UBLAS_INLINE
  825. bool operator < (const iterator2 &it) const {
  826. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  827. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  828. return it2_ < it.it2_;
  829. }
  830. private:
  831. size_type it1_;
  832. size_type it2_;
  833. friend class const_iterator2;
  834. };
  835. #endif
  836. BOOST_UBLAS_INLINE
  837. iterator2 begin2 () {
  838. return find2 (0, 0, 0);
  839. }
  840. BOOST_UBLAS_INLINE
  841. iterator2 end2 () {
  842. return find2 (0, 0, size2_);
  843. }
  844. // Reverse iterators
  845. BOOST_UBLAS_INLINE
  846. const_reverse_iterator1 rbegin1 () const {
  847. return const_reverse_iterator1 (end1 ());
  848. }
  849. BOOST_UBLAS_INLINE
  850. const_reverse_iterator1 rend1 () const {
  851. return const_reverse_iterator1 (begin1 ());
  852. }
  853. BOOST_UBLAS_INLINE
  854. reverse_iterator1 rbegin1 () {
  855. return reverse_iterator1 (end1 ());
  856. }
  857. BOOST_UBLAS_INLINE
  858. reverse_iterator1 rend1 () {
  859. return reverse_iterator1 (begin1 ());
  860. }
  861. BOOST_UBLAS_INLINE
  862. const_reverse_iterator2 rbegin2 () const {
  863. return const_reverse_iterator2 (end2 ());
  864. }
  865. BOOST_UBLAS_INLINE
  866. const_reverse_iterator2 rend2 () const {
  867. return const_reverse_iterator2 (begin2 ());
  868. }
  869. BOOST_UBLAS_INLINE
  870. reverse_iterator2 rbegin2 () {
  871. return reverse_iterator2 (end2 ());
  872. }
  873. BOOST_UBLAS_INLINE
  874. reverse_iterator2 rend2 () {
  875. return reverse_iterator2 (begin2 ());
  876. }
  877. private:
  878. size_type size1_;
  879. size_type size2_;
  880. array_type data_;
  881. static const value_type zero_;
  882. static const value_type one_;
  883. };
  884. template<class T, class TRI, class L, class A>
  885. const typename triangular_matrix<T, TRI, L, A>::value_type triangular_matrix<T, TRI, L, A>::zero_ = value_type/*zero*/();
  886. template<class T, class TRI, class L, class A>
  887. const typename triangular_matrix<T, TRI, L, A>::value_type triangular_matrix<T, TRI, L, A>::one_ (1);
  888. // Triangular matrix adaptor class
  889. template<class M, class TRI>
  890. class triangular_adaptor:
  891. public matrix_expression<triangular_adaptor<M, TRI> > {
  892. typedef triangular_adaptor<M, TRI> self_type;
  893. public:
  894. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  895. using matrix_expression<self_type>::operator ();
  896. #endif
  897. typedef const M const_matrix_type;
  898. typedef M matrix_type;
  899. typedef TRI triangular_type;
  900. typedef typename M::size_type size_type;
  901. typedef typename M::difference_type difference_type;
  902. typedef typename M::value_type value_type;
  903. typedef typename M::const_reference const_reference;
  904. typedef typename boost::mpl::if_<boost::is_const<M>,
  905. typename M::const_reference,
  906. typename M::reference>::type reference;
  907. typedef typename boost::mpl::if_<boost::is_const<M>,
  908. typename M::const_closure_type,
  909. typename M::closure_type>::type matrix_closure_type;
  910. typedef const self_type const_closure_type;
  911. typedef self_type closure_type;
  912. // Replaced by _temporary_traits to avoid type requirements on M
  913. //typedef typename M::vector_temporary_type vector_temporary_type;
  914. //typedef typename M::matrix_temporary_type matrix_temporary_type;
  915. typedef typename storage_restrict_traits<typename M::storage_category,
  916. packed_proxy_tag>::storage_category storage_category;
  917. typedef typename M::orientation_category orientation_category;
  918. // Construction and destruction
  919. BOOST_UBLAS_INLINE
  920. triangular_adaptor (matrix_type &data):
  921. matrix_expression<self_type> (),
  922. data_ (data) {}
  923. BOOST_UBLAS_INLINE
  924. triangular_adaptor (const triangular_adaptor &m):
  925. matrix_expression<self_type> (),
  926. data_ (m.data_) {}
  927. // Accessors
  928. BOOST_UBLAS_INLINE
  929. size_type size1 () const {
  930. return data_.size1 ();
  931. }
  932. BOOST_UBLAS_INLINE
  933. size_type size2 () const {
  934. return data_.size2 ();
  935. }
  936. // Storage accessors
  937. BOOST_UBLAS_INLINE
  938. const matrix_closure_type &data () const {
  939. return data_;
  940. }
  941. BOOST_UBLAS_INLINE
  942. matrix_closure_type &data () {
  943. return data_;
  944. }
  945. // Element access
  946. #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
  947. BOOST_UBLAS_INLINE
  948. const_reference operator () (size_type i, size_type j) const {
  949. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  950. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  951. if (triangular_type::other (i, j))
  952. return data () (i, j);
  953. else if (triangular_type::one (i, j))
  954. return one_;
  955. else
  956. return zero_;
  957. }
  958. BOOST_UBLAS_INLINE
  959. reference operator () (size_type i, size_type j) {
  960. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  961. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  962. if (!triangular_type::other (i, j)) {
  963. bad_index ().raise ();
  964. // NEVER reached
  965. }
  966. return data () (i, j);
  967. }
  968. #else
  969. BOOST_UBLAS_INLINE
  970. reference operator () (size_type i, size_type j) const {
  971. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  972. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  973. if (!triangular_type::other (i, j)) {
  974. bad_index ().raise ();
  975. // NEVER reached
  976. }
  977. return data () (i, j);
  978. }
  979. #endif
  980. // Assignment
  981. BOOST_UBLAS_INLINE
  982. triangular_adaptor &operator = (const triangular_adaptor &m) {
  983. matrix_assign<scalar_assign> (*this, m);
  984. return *this;
  985. }
  986. BOOST_UBLAS_INLINE
  987. triangular_adaptor &assign_temporary (triangular_adaptor &m) {
  988. *this = m;
  989. return *this;
  990. }
  991. template<class AE>
  992. BOOST_UBLAS_INLINE
  993. triangular_adaptor &operator = (const matrix_expression<AE> &ae) {
  994. matrix_assign<scalar_assign> (*this, matrix<value_type> (ae));
  995. return *this;
  996. }
  997. template<class AE>
  998. BOOST_UBLAS_INLINE
  999. triangular_adaptor &assign (const matrix_expression<AE> &ae) {
  1000. matrix_assign<scalar_assign> (*this, ae);
  1001. return *this;
  1002. }
  1003. template<class AE>
  1004. BOOST_UBLAS_INLINE
  1005. triangular_adaptor& operator += (const matrix_expression<AE> &ae) {
  1006. matrix_assign<scalar_assign> (*this, matrix<value_type> (*this + ae));
  1007. return *this;
  1008. }
  1009. template<class AE>
  1010. BOOST_UBLAS_INLINE
  1011. triangular_adaptor &plus_assign (const matrix_expression<AE> &ae) {
  1012. matrix_assign<scalar_plus_assign> (*this, ae);
  1013. return *this;
  1014. }
  1015. template<class AE>
  1016. BOOST_UBLAS_INLINE
  1017. triangular_adaptor& operator -= (const matrix_expression<AE> &ae) {
  1018. matrix_assign<scalar_assign> (*this, matrix<value_type> (*this - ae));
  1019. return *this;
  1020. }
  1021. template<class AE>
  1022. BOOST_UBLAS_INLINE
  1023. triangular_adaptor &minus_assign (const matrix_expression<AE> &ae) {
  1024. matrix_assign<scalar_minus_assign> (*this, ae);
  1025. return *this;
  1026. }
  1027. template<class AT>
  1028. BOOST_UBLAS_INLINE
  1029. triangular_adaptor& operator *= (const AT &at) {
  1030. matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  1031. return *this;
  1032. }
  1033. template<class AT>
  1034. BOOST_UBLAS_INLINE
  1035. triangular_adaptor& operator /= (const AT &at) {
  1036. matrix_assign_scalar<scalar_divides_assign> (*this, at);
  1037. return *this;
  1038. }
  1039. // Closure comparison
  1040. BOOST_UBLAS_INLINE
  1041. bool same_closure (const triangular_adaptor &ta) const {
  1042. return (*this).data ().same_closure (ta.data ());
  1043. }
  1044. // Swapping
  1045. BOOST_UBLAS_INLINE
  1046. void swap (triangular_adaptor &m) {
  1047. if (this != &m)
  1048. matrix_swap<scalar_swap> (*this, m);
  1049. }
  1050. BOOST_UBLAS_INLINE
  1051. friend void swap (triangular_adaptor &m1, triangular_adaptor &m2) {
  1052. m1.swap (m2);
  1053. }
  1054. // Iterator types
  1055. private:
  1056. typedef typename M::const_iterator1 const_subiterator1_type;
  1057. typedef typename boost::mpl::if_<boost::is_const<M>,
  1058. typename M::const_iterator1,
  1059. typename M::iterator1>::type subiterator1_type;
  1060. typedef typename M::const_iterator2 const_subiterator2_type;
  1061. typedef typename boost::mpl::if_<boost::is_const<M>,
  1062. typename M::const_iterator2,
  1063. typename M::iterator2>::type subiterator2_type;
  1064. public:
  1065. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1066. typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
  1067. typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
  1068. typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
  1069. typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
  1070. #else
  1071. class const_iterator1;
  1072. class iterator1;
  1073. class const_iterator2;
  1074. class iterator2;
  1075. #endif
  1076. typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  1077. typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  1078. typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  1079. typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  1080. // Element lookup
  1081. BOOST_UBLAS_INLINE
  1082. const_iterator1 find1 (int rank, size_type i, size_type j) const {
  1083. if (rank == 1)
  1084. i = triangular_type::restrict1 (i, j, size1(), size2());
  1085. if (rank == 0)
  1086. i = triangular_type::global_restrict1 (i, size1(), j, size2());
  1087. return const_iterator1 (*this, data ().find1 (rank, i, j));
  1088. }
  1089. BOOST_UBLAS_INLINE
  1090. iterator1 find1 (int rank, size_type i, size_type j) {
  1091. if (rank == 1)
  1092. i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
  1093. if (rank == 0)
  1094. i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
  1095. return iterator1 (*this, data ().find1 (rank, i, j));
  1096. }
  1097. BOOST_UBLAS_INLINE
  1098. const_iterator2 find2 (int rank, size_type i, size_type j) const {
  1099. if (rank == 1)
  1100. j = triangular_type::restrict2 (i, j, size1(), size2());
  1101. if (rank == 0)
  1102. j = triangular_type::global_restrict2 (i, size1(), j, size2());
  1103. return const_iterator2 (*this, data ().find2 (rank, i, j));
  1104. }
  1105. BOOST_UBLAS_INLINE
  1106. iterator2 find2 (int rank, size_type i, size_type j) {
  1107. if (rank == 1)
  1108. j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
  1109. if (rank == 0)
  1110. j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
  1111. return iterator2 (*this, data ().find2 (rank, i, j));
  1112. }
  1113. // Iterators simply are indices.
  1114. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1115. class const_iterator1:
  1116. public container_const_reference<triangular_adaptor>,
  1117. public random_access_iterator_base<typename iterator_restrict_traits<
  1118. typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1119. const_iterator1, value_type> {
  1120. public:
  1121. typedef typename const_subiterator1_type::value_type value_type;
  1122. typedef typename const_subiterator1_type::difference_type difference_type;
  1123. typedef typename const_subiterator1_type::reference reference;
  1124. typedef typename const_subiterator1_type::pointer pointer;
  1125. typedef const_iterator2 dual_iterator_type;
  1126. typedef const_reverse_iterator2 dual_reverse_iterator_type;
  1127. // Construction and destruction
  1128. BOOST_UBLAS_INLINE
  1129. const_iterator1 ():
  1130. container_const_reference<self_type> (), it1_ () {}
  1131. BOOST_UBLAS_INLINE
  1132. const_iterator1 (const self_type &m, const const_subiterator1_type &it1):
  1133. container_const_reference<self_type> (m), it1_ (it1) {}
  1134. BOOST_UBLAS_INLINE
  1135. const_iterator1 (const iterator1 &it):
  1136. container_const_reference<self_type> (it ()), it1_ (it.it1_) {}
  1137. // Arithmetic
  1138. BOOST_UBLAS_INLINE
  1139. const_iterator1 &operator ++ () {
  1140. ++ it1_;
  1141. return *this;
  1142. }
  1143. BOOST_UBLAS_INLINE
  1144. const_iterator1 &operator -- () {
  1145. -- it1_;
  1146. return *this;
  1147. }
  1148. BOOST_UBLAS_INLINE
  1149. const_iterator1 &operator += (difference_type n) {
  1150. it1_ += n;
  1151. return *this;
  1152. }
  1153. BOOST_UBLAS_INLINE
  1154. const_iterator1 &operator -= (difference_type n) {
  1155. it1_ -= n;
  1156. return *this;
  1157. }
  1158. BOOST_UBLAS_INLINE
  1159. difference_type operator - (const const_iterator1 &it) const {
  1160. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1161. return it1_ - it.it1_;
  1162. }
  1163. // Dereference
  1164. BOOST_UBLAS_INLINE
  1165. const_reference operator * () const {
  1166. size_type i = index1 ();
  1167. size_type j = index2 ();
  1168. BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1169. BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1170. if (triangular_type::other (i, j))
  1171. return *it1_;
  1172. else
  1173. return (*this) () (i, j);
  1174. }
  1175. BOOST_UBLAS_INLINE
  1176. const_reference operator [] (difference_type n) const {
  1177. return *(*this + n);
  1178. }
  1179. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1180. BOOST_UBLAS_INLINE
  1181. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1182. typename self_type::
  1183. #endif
  1184. const_iterator2 begin () const {
  1185. return (*this) ().find2 (1, index1 (), 0);
  1186. }
  1187. BOOST_UBLAS_INLINE
  1188. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1189. typename self_type::
  1190. #endif
  1191. const_iterator2 end () const {
  1192. return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  1193. }
  1194. BOOST_UBLAS_INLINE
  1195. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1196. typename self_type::
  1197. #endif
  1198. const_reverse_iterator2 rbegin () const {
  1199. return const_reverse_iterator2 (end ());
  1200. }
  1201. BOOST_UBLAS_INLINE
  1202. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1203. typename self_type::
  1204. #endif
  1205. const_reverse_iterator2 rend () const {
  1206. return const_reverse_iterator2 (begin ());
  1207. }
  1208. #endif
  1209. // Indices
  1210. BOOST_UBLAS_INLINE
  1211. size_type index1 () const {
  1212. return it1_.index1 ();
  1213. }
  1214. BOOST_UBLAS_INLINE
  1215. size_type index2 () const {
  1216. return it1_.index2 ();
  1217. }
  1218. // Assignment
  1219. BOOST_UBLAS_INLINE
  1220. const_iterator1 &operator = (const const_iterator1 &it) {
  1221. container_const_reference<self_type>::assign (&it ());
  1222. it1_ = it.it1_;
  1223. return *this;
  1224. }
  1225. // Comparison
  1226. BOOST_UBLAS_INLINE
  1227. bool operator == (const const_iterator1 &it) const {
  1228. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1229. return it1_ == it.it1_;
  1230. }
  1231. BOOST_UBLAS_INLINE
  1232. bool operator < (const const_iterator1 &it) const {
  1233. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1234. return it1_ < it.it1_;
  1235. }
  1236. private:
  1237. const_subiterator1_type it1_;
  1238. };
  1239. #endif
  1240. BOOST_UBLAS_INLINE
  1241. const_iterator1 begin1 () const {
  1242. return find1 (0, 0, 0);
  1243. }
  1244. BOOST_UBLAS_INLINE
  1245. const_iterator1 end1 () const {
  1246. return find1 (0, size1 (), 0);
  1247. }
  1248. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1249. class iterator1:
  1250. public container_reference<triangular_adaptor>,
  1251. public random_access_iterator_base<typename iterator_restrict_traits<
  1252. typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1253. iterator1, value_type> {
  1254. public:
  1255. typedef typename subiterator1_type::value_type value_type;
  1256. typedef typename subiterator1_type::difference_type difference_type;
  1257. typedef typename subiterator1_type::reference reference;
  1258. typedef typename subiterator1_type::pointer pointer;
  1259. typedef iterator2 dual_iterator_type;
  1260. typedef reverse_iterator2 dual_reverse_iterator_type;
  1261. // Construction and destruction
  1262. BOOST_UBLAS_INLINE
  1263. iterator1 ():
  1264. container_reference<self_type> (), it1_ () {}
  1265. BOOST_UBLAS_INLINE
  1266. iterator1 (self_type &m, const subiterator1_type &it1):
  1267. container_reference<self_type> (m), it1_ (it1) {}
  1268. // Arithmetic
  1269. BOOST_UBLAS_INLINE
  1270. iterator1 &operator ++ () {
  1271. ++ it1_;
  1272. return *this;
  1273. }
  1274. BOOST_UBLAS_INLINE
  1275. iterator1 &operator -- () {
  1276. -- it1_;
  1277. return *this;
  1278. }
  1279. BOOST_UBLAS_INLINE
  1280. iterator1 &operator += (difference_type n) {
  1281. it1_ += n;
  1282. return *this;
  1283. }
  1284. BOOST_UBLAS_INLINE
  1285. iterator1 &operator -= (difference_type n) {
  1286. it1_ -= n;
  1287. return *this;
  1288. }
  1289. BOOST_UBLAS_INLINE
  1290. difference_type operator - (const iterator1 &it) const {
  1291. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1292. return it1_ - it.it1_;
  1293. }
  1294. // Dereference
  1295. BOOST_UBLAS_INLINE
  1296. reference operator * () const {
  1297. size_type i = index1 ();
  1298. size_type j = index2 ();
  1299. BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1300. BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1301. if (triangular_type::other (i, j))
  1302. return *it1_;
  1303. else
  1304. return (*this) () (i, j);
  1305. }
  1306. BOOST_UBLAS_INLINE
  1307. reference operator [] (difference_type n) const {
  1308. return *(*this + n);
  1309. }
  1310. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1311. BOOST_UBLAS_INLINE
  1312. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1313. typename self_type::
  1314. #endif
  1315. iterator2 begin () const {
  1316. return (*this) ().find2 (1, index1 (), 0);
  1317. }
  1318. BOOST_UBLAS_INLINE
  1319. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1320. typename self_type::
  1321. #endif
  1322. iterator2 end () const {
  1323. return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  1324. }
  1325. BOOST_UBLAS_INLINE
  1326. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1327. typename self_type::
  1328. #endif
  1329. reverse_iterator2 rbegin () const {
  1330. return reverse_iterator2 (end ());
  1331. }
  1332. BOOST_UBLAS_INLINE
  1333. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1334. typename self_type::
  1335. #endif
  1336. reverse_iterator2 rend () const {
  1337. return reverse_iterator2 (begin ());
  1338. }
  1339. #endif
  1340. // Indices
  1341. BOOST_UBLAS_INLINE
  1342. size_type index1 () const {
  1343. return it1_.index1 ();
  1344. }
  1345. BOOST_UBLAS_INLINE
  1346. size_type index2 () const {
  1347. return it1_.index2 ();
  1348. }
  1349. // Assignment
  1350. BOOST_UBLAS_INLINE
  1351. iterator1 &operator = (const iterator1 &it) {
  1352. container_reference<self_type>::assign (&it ());
  1353. it1_ = it.it1_;
  1354. return *this;
  1355. }
  1356. // Comparison
  1357. BOOST_UBLAS_INLINE
  1358. bool operator == (const iterator1 &it) const {
  1359. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1360. return it1_ == it.it1_;
  1361. }
  1362. BOOST_UBLAS_INLINE
  1363. bool operator < (const iterator1 &it) const {
  1364. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1365. return it1_ < it.it1_;
  1366. }
  1367. private:
  1368. subiterator1_type it1_;
  1369. friend class const_iterator1;
  1370. };
  1371. #endif
  1372. BOOST_UBLAS_INLINE
  1373. iterator1 begin1 () {
  1374. return find1 (0, 0, 0);
  1375. }
  1376. BOOST_UBLAS_INLINE
  1377. iterator1 end1 () {
  1378. return find1 (0, size1 (), 0);
  1379. }
  1380. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1381. class const_iterator2:
  1382. public container_const_reference<triangular_adaptor>,
  1383. public random_access_iterator_base<typename iterator_restrict_traits<
  1384. typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1385. const_iterator2, value_type> {
  1386. public:
  1387. typedef typename const_subiterator2_type::value_type value_type;
  1388. typedef typename const_subiterator2_type::difference_type difference_type;
  1389. typedef typename const_subiterator2_type::reference reference;
  1390. typedef typename const_subiterator2_type::pointer pointer;
  1391. typedef const_iterator1 dual_iterator_type;
  1392. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  1393. // Construction and destruction
  1394. BOOST_UBLAS_INLINE
  1395. const_iterator2 ():
  1396. container_const_reference<self_type> (), it2_ () {}
  1397. BOOST_UBLAS_INLINE
  1398. const_iterator2 (const self_type &m, const const_subiterator2_type &it2):
  1399. container_const_reference<self_type> (m), it2_ (it2) {}
  1400. BOOST_UBLAS_INLINE
  1401. const_iterator2 (const iterator2 &it):
  1402. container_const_reference<self_type> (it ()), it2_ (it.it2_) {}
  1403. // Arithmetic
  1404. BOOST_UBLAS_INLINE
  1405. const_iterator2 &operator ++ () {
  1406. ++ it2_;
  1407. return *this;
  1408. }
  1409. BOOST_UBLAS_INLINE
  1410. const_iterator2 &operator -- () {
  1411. -- it2_;
  1412. return *this;
  1413. }
  1414. BOOST_UBLAS_INLINE
  1415. const_iterator2 &operator += (difference_type n) {
  1416. it2_ += n;
  1417. return *this;
  1418. }
  1419. BOOST_UBLAS_INLINE
  1420. const_iterator2 &operator -= (difference_type n) {
  1421. it2_ -= n;
  1422. return *this;
  1423. }
  1424. BOOST_UBLAS_INLINE
  1425. difference_type operator - (const const_iterator2 &it) const {
  1426. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1427. return it2_ - it.it2_;
  1428. }
  1429. // Dereference
  1430. BOOST_UBLAS_INLINE
  1431. const_reference operator * () const {
  1432. size_type i = index1 ();
  1433. size_type j = index2 ();
  1434. BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1435. BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1436. if (triangular_type::other (i, j))
  1437. return *it2_;
  1438. else
  1439. return (*this) () (i, j);
  1440. }
  1441. BOOST_UBLAS_INLINE
  1442. const_reference operator [] (difference_type n) const {
  1443. return *(*this + n);
  1444. }
  1445. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1446. BOOST_UBLAS_INLINE
  1447. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1448. typename self_type::
  1449. #endif
  1450. const_iterator1 begin () const {
  1451. return (*this) ().find1 (1, 0, index2 ());
  1452. }
  1453. BOOST_UBLAS_INLINE
  1454. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1455. typename self_type::
  1456. #endif
  1457. const_iterator1 end () const {
  1458. return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
  1459. }
  1460. BOOST_UBLAS_INLINE
  1461. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1462. typename self_type::
  1463. #endif
  1464. const_reverse_iterator1 rbegin () const {
  1465. return const_reverse_iterator1 (end ());
  1466. }
  1467. BOOST_UBLAS_INLINE
  1468. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1469. typename self_type::
  1470. #endif
  1471. const_reverse_iterator1 rend () const {
  1472. return const_reverse_iterator1 (begin ());
  1473. }
  1474. #endif
  1475. // Indices
  1476. BOOST_UBLAS_INLINE
  1477. size_type index1 () const {
  1478. return it2_.index1 ();
  1479. }
  1480. BOOST_UBLAS_INLINE
  1481. size_type index2 () const {
  1482. return it2_.index2 ();
  1483. }
  1484. // Assignment
  1485. BOOST_UBLAS_INLINE
  1486. const_iterator2 &operator = (const const_iterator2 &it) {
  1487. container_const_reference<self_type>::assign (&it ());
  1488. it2_ = it.it2_;
  1489. return *this;
  1490. }
  1491. // Comparison
  1492. BOOST_UBLAS_INLINE
  1493. bool operator == (const const_iterator2 &it) const {
  1494. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1495. return it2_ == it.it2_;
  1496. }
  1497. BOOST_UBLAS_INLINE
  1498. bool operator < (const const_iterator2 &it) const {
  1499. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1500. return it2_ < it.it2_;
  1501. }
  1502. private:
  1503. const_subiterator2_type it2_;
  1504. };
  1505. #endif
  1506. BOOST_UBLAS_INLINE
  1507. const_iterator2 begin2 () const {
  1508. return find2 (0, 0, 0);
  1509. }
  1510. BOOST_UBLAS_INLINE
  1511. const_iterator2 end2 () const {
  1512. return find2 (0, 0, size2 ());
  1513. }
  1514. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1515. class iterator2:
  1516. public container_reference<triangular_adaptor>,
  1517. public random_access_iterator_base<typename iterator_restrict_traits<
  1518. typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1519. iterator2, value_type> {
  1520. public:
  1521. typedef typename subiterator2_type::value_type value_type;
  1522. typedef typename subiterator2_type::difference_type difference_type;
  1523. typedef typename subiterator2_type::reference reference;
  1524. typedef typename subiterator2_type::pointer pointer;
  1525. typedef iterator1 dual_iterator_type;
  1526. typedef reverse_iterator1 dual_reverse_iterator_type;
  1527. // Construction and destruction
  1528. BOOST_UBLAS_INLINE
  1529. iterator2 ():
  1530. container_reference<self_type> (), it2_ () {}
  1531. BOOST_UBLAS_INLINE
  1532. iterator2 (self_type &m, const subiterator2_type &it2):
  1533. container_reference<self_type> (m), it2_ (it2) {}
  1534. // Arithmetic
  1535. BOOST_UBLAS_INLINE
  1536. iterator2 &operator ++ () {
  1537. ++ it2_;
  1538. return *this;
  1539. }
  1540. BOOST_UBLAS_INLINE
  1541. iterator2 &operator -- () {
  1542. -- it2_;
  1543. return *this;
  1544. }
  1545. BOOST_UBLAS_INLINE
  1546. iterator2 &operator += (difference_type n) {
  1547. it2_ += n;
  1548. return *this;
  1549. }
  1550. BOOST_UBLAS_INLINE
  1551. iterator2 &operator -= (difference_type n) {
  1552. it2_ -= n;
  1553. return *this;
  1554. }
  1555. BOOST_UBLAS_INLINE
  1556. difference_type operator - (const iterator2 &it) const {
  1557. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1558. return it2_ - it.it2_;
  1559. }
  1560. // Dereference
  1561. BOOST_UBLAS_INLINE
  1562. reference operator * () const {
  1563. size_type i = index1 ();
  1564. size_type j = index2 ();
  1565. BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1566. BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1567. if (triangular_type::other (i, j))
  1568. return *it2_;
  1569. else
  1570. return (*this) () (i, j);
  1571. }
  1572. BOOST_UBLAS_INLINE
  1573. reference operator [] (difference_type n) const {
  1574. return *(*this + n);
  1575. }
  1576. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1577. BOOST_UBLAS_INLINE
  1578. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1579. typename self_type::
  1580. #endif
  1581. iterator1 begin () const {
  1582. return (*this) ().find1 (1, 0, index2 ());
  1583. }
  1584. BOOST_UBLAS_INLINE
  1585. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1586. typename self_type::
  1587. #endif
  1588. iterator1 end () const {
  1589. return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
  1590. }
  1591. BOOST_UBLAS_INLINE
  1592. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1593. typename self_type::
  1594. #endif
  1595. reverse_iterator1 rbegin () const {
  1596. return reverse_iterator1 (end ());
  1597. }
  1598. BOOST_UBLAS_INLINE
  1599. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1600. typename self_type::
  1601. #endif
  1602. reverse_iterator1 rend () const {
  1603. return reverse_iterator1 (begin ());
  1604. }
  1605. #endif
  1606. // Indices
  1607. BOOST_UBLAS_INLINE
  1608. size_type index1 () const {
  1609. return it2_.index1 ();
  1610. }
  1611. BOOST_UBLAS_INLINE
  1612. size_type index2 () const {
  1613. return it2_.index2 ();
  1614. }
  1615. // Assignment
  1616. BOOST_UBLAS_INLINE
  1617. iterator2 &operator = (const iterator2 &it) {
  1618. container_reference<self_type>::assign (&it ());
  1619. it2_ = it.it2_;
  1620. return *this;
  1621. }
  1622. // Comparison
  1623. BOOST_UBLAS_INLINE
  1624. bool operator == (const iterator2 &it) const {
  1625. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1626. return it2_ == it.it2_;
  1627. }
  1628. BOOST_UBLAS_INLINE
  1629. bool operator < (const iterator2 &it) const {
  1630. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1631. return it2_ < it.it2_;
  1632. }
  1633. private:
  1634. subiterator2_type it2_;
  1635. friend class const_iterator2;
  1636. };
  1637. #endif
  1638. BOOST_UBLAS_INLINE
  1639. iterator2 begin2 () {
  1640. return find2 (0, 0, 0);
  1641. }
  1642. BOOST_UBLAS_INLINE
  1643. iterator2 end2 () {
  1644. return find2 (0, 0, size2 ());
  1645. }
  1646. // Reverse iterators
  1647. BOOST_UBLAS_INLINE
  1648. const_reverse_iterator1 rbegin1 () const {
  1649. return const_reverse_iterator1 (end1 ());
  1650. }
  1651. BOOST_UBLAS_INLINE
  1652. const_reverse_iterator1 rend1 () const {
  1653. return const_reverse_iterator1 (begin1 ());
  1654. }
  1655. BOOST_UBLAS_INLINE
  1656. reverse_iterator1 rbegin1 () {
  1657. return reverse_iterator1 (end1 ());
  1658. }
  1659. BOOST_UBLAS_INLINE
  1660. reverse_iterator1 rend1 () {
  1661. return reverse_iterator1 (begin1 ());
  1662. }
  1663. BOOST_UBLAS_INLINE
  1664. const_reverse_iterator2 rbegin2 () const {
  1665. return const_reverse_iterator2 (end2 ());
  1666. }
  1667. BOOST_UBLAS_INLINE
  1668. const_reverse_iterator2 rend2 () const {
  1669. return const_reverse_iterator2 (begin2 ());
  1670. }
  1671. BOOST_UBLAS_INLINE
  1672. reverse_iterator2 rbegin2 () {
  1673. return reverse_iterator2 (end2 ());
  1674. }
  1675. BOOST_UBLAS_INLINE
  1676. reverse_iterator2 rend2 () {
  1677. return reverse_iterator2 (begin2 ());
  1678. }
  1679. private:
  1680. matrix_closure_type data_;
  1681. static const value_type zero_;
  1682. static const value_type one_;
  1683. };
  1684. template<class M, class TRI>
  1685. const typename triangular_adaptor<M, TRI>::value_type triangular_adaptor<M, TRI>::zero_ = value_type/*zero*/();
  1686. template<class M, class TRI>
  1687. const typename triangular_adaptor<M, TRI>::value_type triangular_adaptor<M, TRI>::one_ (1);
  1688. template <class M, class TRI>
  1689. struct vector_temporary_traits< triangular_adaptor<M, TRI> >
  1690. : vector_temporary_traits< typename boost::remove_const<M>::type > {} ;
  1691. template <class M, class TRI>
  1692. struct vector_temporary_traits< const triangular_adaptor<M, TRI> >
  1693. : vector_temporary_traits< typename boost::remove_const<M>::type > {} ;
  1694. template <class M, class TRI>
  1695. struct matrix_temporary_traits< triangular_adaptor<M, TRI> >
  1696. : matrix_temporary_traits< typename boost::remove_const<M>::type > {};
  1697. template <class M, class TRI>
  1698. struct matrix_temporary_traits< const triangular_adaptor<M, TRI> >
  1699. : matrix_temporary_traits< typename boost::remove_const<M>::type > {};
  1700. template<class E1, class E2>
  1701. struct matrix_vector_solve_traits {
  1702. typedef typename promote_traits<typename E1::value_type, typename E2::value_type>::promote_type promote_type;
  1703. typedef vector<promote_type> result_type;
  1704. };
  1705. // Operations:
  1706. // n * (n - 1) / 2 + n = n * (n + 1) / 2 multiplications,
  1707. // n * (n - 1) / 2 additions
  1708. // Dense (proxy) case
  1709. template<class E1, class E2>
  1710. BOOST_UBLAS_INLINE
  1711. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1712. lower_tag, column_major_tag, dense_proxy_tag) {
  1713. typedef typename E2::size_type size_type;
  1714. typedef typename E2::difference_type difference_type;
  1715. typedef typename E2::value_type value_type;
  1716. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1717. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1718. size_type size = e2 ().size ();
  1719. for (size_type n = 0; n < size; ++ n) {
  1720. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1721. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1722. #else
  1723. if (e1 () (n, n) == value_type/*zero*/())
  1724. singular ().raise ();
  1725. #endif
  1726. value_type t = e2 () (n) /= e1 () (n, n);
  1727. if (t != value_type/*zero*/()) {
  1728. for (size_type m = n + 1; m < size; ++ m)
  1729. e2 () (m) -= e1 () (m, n) * t;
  1730. }
  1731. }
  1732. }
  1733. // Packed (proxy) case
  1734. template<class E1, class E2>
  1735. BOOST_UBLAS_INLINE
  1736. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1737. lower_tag, column_major_tag, packed_proxy_tag) {
  1738. typedef typename E2::size_type size_type;
  1739. typedef typename E2::difference_type difference_type;
  1740. typedef typename E2::value_type value_type;
  1741. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1742. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1743. size_type size = e2 ().size ();
  1744. for (size_type n = 0; n < size; ++ n) {
  1745. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1746. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1747. #else
  1748. if (e1 () (n, n) == value_type/*zero*/())
  1749. singular ().raise ();
  1750. #endif
  1751. value_type t = e2 () (n) /= e1 () (n, n);
  1752. if (t != value_type/*zero*/()) {
  1753. typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
  1754. typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
  1755. difference_type m (it1e1_end - it1e1);
  1756. while (-- m >= 0)
  1757. e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
  1758. }
  1759. }
  1760. }
  1761. // Sparse (proxy) case
  1762. template<class E1, class E2>
  1763. BOOST_UBLAS_INLINE
  1764. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1765. lower_tag, column_major_tag, unknown_storage_tag) {
  1766. typedef typename E2::size_type size_type;
  1767. typedef typename E2::difference_type difference_type;
  1768. typedef typename E2::value_type value_type;
  1769. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1770. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1771. size_type size = e2 ().size ();
  1772. for (size_type n = 0; n < size; ++ n) {
  1773. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1774. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1775. #else
  1776. if (e1 () (n, n) == value_type/*zero*/())
  1777. singular ().raise ();
  1778. #endif
  1779. value_type t = e2 () (n) /= e1 () (n, n);
  1780. if (t != value_type/*zero*/()) {
  1781. typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
  1782. typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
  1783. while (it1e1 != it1e1_end)
  1784. e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
  1785. }
  1786. }
  1787. }
  1788. // Dense (proxy) case
  1789. template<class E1, class E2>
  1790. BOOST_UBLAS_INLINE
  1791. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1792. lower_tag, row_major_tag, dense_proxy_tag) {
  1793. typedef typename E2::size_type size_type;
  1794. typedef typename E2::difference_type difference_type;
  1795. typedef typename E2::value_type value_type;
  1796. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1797. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1798. size_type size = e2 ().size ();
  1799. for (size_type n = 0; n < size; ++ n) {
  1800. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1801. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1802. #else
  1803. if (e1 () (n, n) == value_type/*zero*/())
  1804. singular ().raise ();
  1805. #endif
  1806. value_type t = e2 () (n) /= e1 () (n, n);
  1807. if (t != value_type/*zero*/()) {
  1808. for (size_type m = n + 1; m < size; ++ m)
  1809. e2 () (m) -= e1 () (m, n) * t;
  1810. }
  1811. }
  1812. }
  1813. // Packed (proxy) case
  1814. template<class E1, class E2>
  1815. BOOST_UBLAS_INLINE
  1816. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1817. lower_tag, row_major_tag, packed_proxy_tag) {
  1818. typedef typename E2::size_type size_type;
  1819. typedef typename E2::difference_type difference_type;
  1820. typedef typename E2::value_type value_type;
  1821. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1822. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1823. size_type size = e2 ().size ();
  1824. for (size_type n = 0; n < size; ++ n) {
  1825. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1826. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1827. #else
  1828. if (e1 () (n, n) == value_type/*zero*/())
  1829. singular ().raise ();
  1830. #endif
  1831. value_type t = e2 () (n);
  1832. typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, 0));
  1833. typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, n));
  1834. while (it2e1 != it2e1_end) {
  1835. t -= *it2e1 * e2 () (it2e1.index2());
  1836. ++ it2e1;
  1837. }
  1838. e2() (n) = t / e1 () (n, n);
  1839. }
  1840. }
  1841. // Sparse (proxy) case
  1842. template<class E1, class E2>
  1843. BOOST_UBLAS_INLINE
  1844. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1845. lower_tag, row_major_tag, unknown_storage_tag) {
  1846. typedef typename E2::size_type size_type;
  1847. typedef typename E2::difference_type difference_type;
  1848. typedef typename E2::value_type value_type;
  1849. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1850. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1851. size_type size = e2 ().size ();
  1852. for (size_type n = 0; n < size; ++ n) {
  1853. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1854. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1855. #else
  1856. if (e1 () (n, n) == value_type/*zero*/())
  1857. singular ().raise ();
  1858. #endif
  1859. value_type t = e2 () (n);
  1860. typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, 0));
  1861. typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, n));
  1862. while (it2e1 != it2e1_end) {
  1863. t -= *it2e1 * e2 () (it2e1.index2());
  1864. ++ it2e1;
  1865. }
  1866. e2() (n) = t / e1 () (n, n);
  1867. }
  1868. }
  1869. // Redirectors :-)
  1870. template<class E1, class E2>
  1871. BOOST_UBLAS_INLINE
  1872. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1873. lower_tag, column_major_tag) {
  1874. typedef typename E1::storage_category storage_category;
  1875. inplace_solve (e1, e2,
  1876. lower_tag (), column_major_tag (), storage_category ());
  1877. }
  1878. template<class E1, class E2>
  1879. BOOST_UBLAS_INLINE
  1880. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1881. lower_tag, row_major_tag) {
  1882. typedef typename E1::storage_category storage_category;
  1883. inplace_solve (e1, e2,
  1884. lower_tag (), row_major_tag (), storage_category ());
  1885. }
  1886. // Dispatcher
  1887. template<class E1, class E2>
  1888. BOOST_UBLAS_INLINE
  1889. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1890. lower_tag) {
  1891. typedef typename E1::orientation_category orientation_category;
  1892. inplace_solve (e1, e2,
  1893. lower_tag (), orientation_category ());
  1894. }
  1895. template<class E1, class E2>
  1896. BOOST_UBLAS_INLINE
  1897. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1898. unit_lower_tag) {
  1899. typedef typename E1::orientation_category orientation_category;
  1900. inplace_solve (triangular_adaptor<const E1, unit_lower> (e1 ()), e2,
  1901. unit_lower_tag (), orientation_category ());
  1902. }
  1903. // Dense (proxy) case
  1904. template<class E1, class E2>
  1905. BOOST_UBLAS_INLINE
  1906. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1907. upper_tag, column_major_tag, dense_proxy_tag) {
  1908. typedef typename E2::size_type size_type;
  1909. typedef typename E2::difference_type difference_type;
  1910. typedef typename E2::value_type value_type;
  1911. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1912. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1913. size_type size = e2 ().size ();
  1914. for (difference_type n = size - 1; n >= 0; -- n) {
  1915. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1916. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1917. #else
  1918. if (e1 () (n, n) == value_type/*zero*/())
  1919. singular ().raise ();
  1920. #endif
  1921. value_type t = e2 () (n) /= e1 () (n, n);
  1922. if (t != value_type/*zero*/()) {
  1923. for (difference_type m = n - 1; m >= 0; -- m)
  1924. e2 () (m) -= e1 () (m, n) * t;
  1925. }
  1926. }
  1927. }
  1928. // Packed (proxy) case
  1929. template<class E1, class E2>
  1930. BOOST_UBLAS_INLINE
  1931. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1932. upper_tag, column_major_tag, packed_proxy_tag) {
  1933. typedef typename E2::size_type size_type;
  1934. typedef typename E2::difference_type difference_type;
  1935. typedef typename E2::value_type value_type;
  1936. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1937. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1938. size_type size = e2 ().size ();
  1939. for (difference_type n = size - 1; n >= 0; -- n) {
  1940. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1941. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1942. #else
  1943. if (e1 () (n, n) == value_type/*zero*/())
  1944. singular ().raise ();
  1945. #endif
  1946. value_type t = e2 () (n) /= e1 () (n, n);
  1947. if (t != value_type/*zero*/()) {
  1948. typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
  1949. typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
  1950. while (it1e1 != it1e1_rend) {
  1951. e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
  1952. }
  1953. }
  1954. }
  1955. }
  1956. // Sparse (proxy) case
  1957. template<class E1, class E2>
  1958. BOOST_UBLAS_INLINE
  1959. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1960. upper_tag, column_major_tag, unknown_storage_tag) {
  1961. typedef typename E2::size_type size_type;
  1962. typedef typename E2::difference_type difference_type;
  1963. typedef typename E2::value_type value_type;
  1964. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1965. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1966. size_type size = e2 ().size ();
  1967. for (difference_type n = size - 1; n >= 0; -- n) {
  1968. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1969. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1970. #else
  1971. if (e1 () (n, n) == value_type/*zero*/())
  1972. singular ().raise ();
  1973. #endif
  1974. value_type t = e2 () (n) /= e1 () (n, n);
  1975. if (t != value_type/*zero*/()) {
  1976. typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
  1977. typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
  1978. while (it1e1 != it1e1_rend) {
  1979. e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
  1980. }
  1981. }
  1982. }
  1983. }
  1984. // Dense (proxy) case
  1985. template<class E1, class E2>
  1986. BOOST_UBLAS_INLINE
  1987. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1988. upper_tag, row_major_tag, dense_proxy_tag) {
  1989. typedef typename E2::size_type size_type;
  1990. typedef typename E2::difference_type difference_type;
  1991. typedef typename E2::value_type value_type;
  1992. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1993. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1994. size_type size = e1 ().size1 ();
  1995. for (difference_type n = size-1; n >=0; -- n) {
  1996. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1997. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1998. #else
  1999. if (e1 () (n, n) == value_type/*zero*/())
  2000. singular ().raise ();
  2001. #endif
  2002. value_type t = e2 () (n);
  2003. for (difference_type m = n + 1; m < e1 ().size2(); ++ m) {
  2004. t -= e1 () (n, m) * e2 () (m);
  2005. }
  2006. e2() (n) = t / e1 () (n, n);
  2007. }
  2008. }
  2009. // Packed (proxy) case
  2010. template<class E1, class E2>
  2011. BOOST_UBLAS_INLINE
  2012. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2013. upper_tag, row_major_tag, packed_proxy_tag) {
  2014. typedef typename E2::size_type size_type;
  2015. typedef typename E2::difference_type difference_type;
  2016. typedef typename E2::value_type value_type;
  2017. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2018. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  2019. size_type size = e1 ().size1 ();
  2020. for (difference_type n = size-1; n >=0; -- n) {
  2021. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2022. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2023. #else
  2024. if (e1 () (n, n) == value_type/*zero*/())
  2025. singular ().raise ();
  2026. #endif
  2027. value_type t = e2 () (n);
  2028. typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, n+1));
  2029. typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, e1 ().size2 ()));
  2030. while (it2e1 != it2e1_end) {
  2031. t -= *it2e1 * e2 () (it2e1.index2());
  2032. ++ it2e1;
  2033. }
  2034. e2() (n) = t / e1 () (n, n);
  2035. }
  2036. }
  2037. // Sparse (proxy) case
  2038. template<class E1, class E2>
  2039. BOOST_UBLAS_INLINE
  2040. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2041. upper_tag, row_major_tag, unknown_storage_tag) {
  2042. typedef typename E2::size_type size_type;
  2043. typedef typename E2::difference_type difference_type;
  2044. typedef typename E2::value_type value_type;
  2045. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2046. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  2047. size_type size = e1 ().size1 ();
  2048. for (difference_type n = size-1; n >=0; -- n) {
  2049. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2050. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2051. #else
  2052. if (e1 () (n, n) == value_type/*zero*/())
  2053. singular ().raise ();
  2054. #endif
  2055. value_type t = e2 () (n);
  2056. typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, n+1));
  2057. typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, e1 ().size2 ()));
  2058. while (it2e1 != it2e1_end) {
  2059. t -= *it2e1 * e2 () (it2e1.index2());
  2060. ++ it2e1;
  2061. }
  2062. e2() (n) = t / e1 () (n, n);
  2063. }
  2064. }
  2065. // Redirectors :-)
  2066. template<class E1, class E2>
  2067. BOOST_UBLAS_INLINE
  2068. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2069. upper_tag, column_major_tag) {
  2070. typedef typename E1::storage_category storage_category;
  2071. inplace_solve (e1, e2,
  2072. upper_tag (), column_major_tag (), storage_category ());
  2073. }
  2074. template<class E1, class E2>
  2075. BOOST_UBLAS_INLINE
  2076. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2077. upper_tag, row_major_tag) {
  2078. typedef typename E1::storage_category storage_category;
  2079. inplace_solve (e1, e2,
  2080. upper_tag (), row_major_tag (), storage_category ());
  2081. }
  2082. // Dispatcher
  2083. template<class E1, class E2>
  2084. BOOST_UBLAS_INLINE
  2085. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2086. upper_tag) {
  2087. typedef typename E1::orientation_category orientation_category;
  2088. inplace_solve (e1, e2,
  2089. upper_tag (), orientation_category ());
  2090. }
  2091. template<class E1, class E2>
  2092. BOOST_UBLAS_INLINE
  2093. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2094. unit_upper_tag) {
  2095. typedef typename E1::orientation_category orientation_category;
  2096. inplace_solve (triangular_adaptor<const E1, unit_upper> (e1 ()), e2,
  2097. unit_upper_tag (), orientation_category ());
  2098. }
  2099. template<class E1, class E2, class C>
  2100. BOOST_UBLAS_INLINE
  2101. typename matrix_vector_solve_traits<E1, E2>::result_type
  2102. solve (const matrix_expression<E1> &e1,
  2103. const vector_expression<E2> &e2,
  2104. C) {
  2105. typename matrix_vector_solve_traits<E1, E2>::result_type r (e2);
  2106. inplace_solve (e1, r, C ());
  2107. return r;
  2108. }
  2109. // Redirectors :-)
  2110. template<class E1, class E2>
  2111. BOOST_UBLAS_INLINE
  2112. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2113. lower_tag, row_major_tag) {
  2114. typedef typename E2::storage_category storage_category;
  2115. inplace_solve (trans(e2), e1,
  2116. upper_tag (), column_major_tag (), storage_category ());
  2117. }
  2118. template<class E1, class E2>
  2119. BOOST_UBLAS_INLINE
  2120. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2121. lower_tag, column_major_tag) {
  2122. typedef typename E2::storage_category storage_category;
  2123. inplace_solve (trans (e2), e1,
  2124. upper_tag (), row_major_tag (), storage_category ());
  2125. }
  2126. // Dispatcher
  2127. template<class E1, class E2>
  2128. BOOST_UBLAS_INLINE
  2129. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2130. lower_tag) {
  2131. typedef typename E2::orientation_category orientation_category;
  2132. inplace_solve (e1, e2,
  2133. lower_tag (), orientation_category ());
  2134. }
  2135. template<class E1, class E2>
  2136. BOOST_UBLAS_INLINE
  2137. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2138. unit_lower_tag) {
  2139. typedef typename E2::orientation_category orientation_category;
  2140. inplace_solve (e1, triangular_adaptor<const E2, unit_lower> (e2 ()),
  2141. unit_lower_tag (), orientation_category ());
  2142. }
  2143. // Redirectors :-)
  2144. template<class E1, class E2>
  2145. BOOST_UBLAS_INLINE
  2146. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2147. upper_tag, row_major_tag) {
  2148. typedef typename E2::storage_category storage_category;
  2149. inplace_solve (trans(e2), e1,
  2150. lower_tag (), column_major_tag (), storage_category ());
  2151. }
  2152. template<class E1, class E2>
  2153. BOOST_UBLAS_INLINE
  2154. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2155. upper_tag, column_major_tag) {
  2156. typedef typename E2::storage_category storage_category;
  2157. inplace_solve (trans (e2), e1,
  2158. lower_tag (), row_major_tag (), storage_category ());
  2159. }
  2160. // Dispatcher
  2161. template<class E1, class E2>
  2162. BOOST_UBLAS_INLINE
  2163. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2164. upper_tag) {
  2165. typedef typename E2::orientation_category orientation_category;
  2166. inplace_solve (e1, e2,
  2167. upper_tag (), orientation_category ());
  2168. }
  2169. template<class E1, class E2>
  2170. BOOST_UBLAS_INLINE
  2171. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2172. unit_upper_tag) {
  2173. typedef typename E2::orientation_category orientation_category;
  2174. inplace_solve (e1, triangular_adaptor<const E2, unit_upper> (e2 ()),
  2175. unit_upper_tag (), orientation_category ());
  2176. }
  2177. template<class E1, class E2, class C>
  2178. BOOST_UBLAS_INLINE
  2179. typename matrix_vector_solve_traits<E1, E2>::result_type
  2180. solve (const vector_expression<E1> &e1,
  2181. const matrix_expression<E2> &e2,
  2182. C) {
  2183. typename matrix_vector_solve_traits<E1, E2>::result_type r (e1);
  2184. inplace_solve (r, e2, C ());
  2185. return r;
  2186. }
  2187. template<class E1, class E2>
  2188. struct matrix_matrix_solve_traits {
  2189. typedef typename promote_traits<typename E1::value_type, typename E2::value_type>::promote_type promote_type;
  2190. typedef matrix<promote_type> result_type;
  2191. };
  2192. // Operations:
  2193. // k * n * (n - 1) / 2 + k * n = k * n * (n + 1) / 2 multiplications,
  2194. // k * n * (n - 1) / 2 additions
  2195. // Dense (proxy) case
  2196. template<class E1, class E2>
  2197. BOOST_UBLAS_INLINE
  2198. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2199. lower_tag, dense_proxy_tag) {
  2200. typedef typename E2::size_type size_type;
  2201. typedef typename E2::difference_type difference_type;
  2202. typedef typename E2::value_type value_type;
  2203. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2204. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2205. size_type size1 = e2 ().size1 ();
  2206. size_type size2 = e2 ().size2 ();
  2207. for (size_type n = 0; n < size1; ++ n) {
  2208. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2209. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2210. #else
  2211. if (e1 () (n, n) == value_type/*zero*/())
  2212. singular ().raise ();
  2213. #endif
  2214. for (size_type l = 0; l < size2; ++ l) {
  2215. value_type t = e2 () (n, l) /= e1 () (n, n);
  2216. if (t != value_type/*zero*/()) {
  2217. for (size_type m = n + 1; m < size1; ++ m)
  2218. e2 () (m, l) -= e1 () (m, n) * t;
  2219. }
  2220. }
  2221. }
  2222. }
  2223. // Packed (proxy) case
  2224. template<class E1, class E2>
  2225. BOOST_UBLAS_INLINE
  2226. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2227. lower_tag, packed_proxy_tag) {
  2228. typedef typename E2::size_type size_type;
  2229. typedef typename E2::difference_type difference_type;
  2230. typedef typename E2::value_type value_type;
  2231. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2232. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2233. size_type size1 = e2 ().size1 ();
  2234. size_type size2 = e2 ().size2 ();
  2235. for (size_type n = 0; n < size1; ++ n) {
  2236. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2237. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2238. #else
  2239. if (e1 () (n, n) == value_type/*zero*/())
  2240. singular ().raise ();
  2241. #endif
  2242. for (size_type l = 0; l < size2; ++ l) {
  2243. value_type t = e2 () (n, l) /= e1 () (n, n);
  2244. if (t != value_type/*zero*/()) {
  2245. typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
  2246. typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
  2247. difference_type m (it1e1_end - it1e1);
  2248. while (-- m >= 0)
  2249. e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
  2250. }
  2251. }
  2252. }
  2253. }
  2254. // Sparse (proxy) case
  2255. template<class E1, class E2>
  2256. BOOST_UBLAS_INLINE
  2257. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2258. lower_tag, unknown_storage_tag) {
  2259. typedef typename E2::size_type size_type;
  2260. typedef typename E2::difference_type difference_type;
  2261. typedef typename E2::value_type value_type;
  2262. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2263. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2264. size_type size1 = e2 ().size1 ();
  2265. size_type size2 = e2 ().size2 ();
  2266. for (size_type n = 0; n < size1; ++ n) {
  2267. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2268. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2269. #else
  2270. if (e1 () (n, n) == value_type/*zero*/())
  2271. singular ().raise ();
  2272. #endif
  2273. for (size_type l = 0; l < size2; ++ l) {
  2274. value_type t = e2 () (n, l) /= e1 () (n, n);
  2275. if (t != value_type/*zero*/()) {
  2276. typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
  2277. typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
  2278. while (it1e1 != it1e1_end)
  2279. e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
  2280. }
  2281. }
  2282. }
  2283. }
  2284. // Dispatcher
  2285. template<class E1, class E2>
  2286. BOOST_UBLAS_INLINE
  2287. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2288. lower_tag) {
  2289. typedef typename E1::storage_category dispatch_category;
  2290. inplace_solve (e1, e2,
  2291. lower_tag (), dispatch_category ());
  2292. }
  2293. template<class E1, class E2>
  2294. BOOST_UBLAS_INLINE
  2295. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2296. unit_lower_tag) {
  2297. typedef typename E1::storage_category dispatch_category;
  2298. inplace_solve (triangular_adaptor<const E1, unit_lower> (e1 ()), e2,
  2299. unit_lower_tag (), dispatch_category ());
  2300. }
  2301. // Dense (proxy) case
  2302. template<class E1, class E2>
  2303. BOOST_UBLAS_INLINE
  2304. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2305. upper_tag, dense_proxy_tag) {
  2306. typedef typename E2::size_type size_type;
  2307. typedef typename E2::difference_type difference_type;
  2308. typedef typename E2::value_type value_type;
  2309. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2310. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2311. size_type size1 = e2 ().size1 ();
  2312. size_type size2 = e2 ().size2 ();
  2313. for (difference_type n = size1 - 1; n >= 0; -- n) {
  2314. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2315. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2316. #else
  2317. if (e1 () (n, n) == value_type/*zero*/())
  2318. singular ().raise ();
  2319. #endif
  2320. for (difference_type l = size2 - 1; l >= 0; -- l) {
  2321. value_type t = e2 () (n, l) /= e1 () (n, n);
  2322. if (t != value_type/*zero*/()) {
  2323. for (difference_type m = n - 1; m >= 0; -- m)
  2324. e2 () (m, l) -= e1 () (m, n) * t;
  2325. }
  2326. }
  2327. }
  2328. }
  2329. // Packed (proxy) case
  2330. template<class E1, class E2>
  2331. BOOST_UBLAS_INLINE
  2332. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2333. upper_tag, packed_proxy_tag) {
  2334. typedef typename E2::size_type size_type;
  2335. typedef typename E2::difference_type difference_type;
  2336. typedef typename E2::value_type value_type;
  2337. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2338. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2339. size_type size1 = e2 ().size1 ();
  2340. size_type size2 = e2 ().size2 ();
  2341. for (difference_type n = size1 - 1; n >= 0; -- n) {
  2342. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2343. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2344. #else
  2345. if (e1 () (n, n) == value_type/*zero*/())
  2346. singular ().raise ();
  2347. #endif
  2348. for (difference_type l = size2 - 1; l >= 0; -- l) {
  2349. value_type t = e2 () (n, l) /= e1 () (n, n);
  2350. if (t != value_type/*zero*/()) {
  2351. typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
  2352. typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
  2353. difference_type m (it1e1_rend - it1e1);
  2354. while (-- m >= 0)
  2355. e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
  2356. }
  2357. }
  2358. }
  2359. }
  2360. // Sparse (proxy) case
  2361. template<class E1, class E2>
  2362. BOOST_UBLAS_INLINE
  2363. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2364. upper_tag, unknown_storage_tag) {
  2365. typedef typename E2::size_type size_type;
  2366. typedef typename E2::difference_type difference_type;
  2367. typedef typename E2::value_type value_type;
  2368. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2369. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2370. size_type size1 = e2 ().size1 ();
  2371. size_type size2 = e2 ().size2 ();
  2372. for (difference_type n = size1 - 1; n >= 0; -- n) {
  2373. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2374. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2375. #else
  2376. if (e1 () (n, n) == value_type/*zero*/())
  2377. singular ().raise ();
  2378. #endif
  2379. for (difference_type l = size2 - 1; l >= 0; -- l) {
  2380. value_type t = e2 () (n, l) /= e1 () (n, n);
  2381. if (t != value_type/*zero*/()) {
  2382. typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
  2383. typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
  2384. while (it1e1 != it1e1_rend)
  2385. e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
  2386. }
  2387. }
  2388. }
  2389. }
  2390. // Dispatcher
  2391. template<class E1, class E2>
  2392. BOOST_UBLAS_INLINE
  2393. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2394. upper_tag) {
  2395. typedef typename E1::storage_category dispatch_category;
  2396. inplace_solve (e1, e2,
  2397. upper_tag (), dispatch_category ());
  2398. }
  2399. template<class E1, class E2>
  2400. BOOST_UBLAS_INLINE
  2401. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2402. unit_upper_tag) {
  2403. typedef typename E1::storage_category dispatch_category;
  2404. inplace_solve (triangular_adaptor<const E1, unit_upper> (e1 ()), e2,
  2405. unit_upper_tag (), dispatch_category ());
  2406. }
  2407. template<class E1, class E2, class C>
  2408. BOOST_UBLAS_INLINE
  2409. typename matrix_matrix_solve_traits<E1, E2>::result_type
  2410. solve (const matrix_expression<E1> &e1,
  2411. const matrix_expression<E2> &e2,
  2412. C) {
  2413. typename matrix_matrix_solve_traits<E1, E2>::result_type r (e2);
  2414. inplace_solve (e1, r, C ());
  2415. return r;
  2416. }
  2417. }}}
  2418. #endif