triangular.hpp 103 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775
  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 cbegin () const {
  395. return begin ();
  396. }
  397. BOOST_UBLAS_INLINE
  398. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  399. typename self_type::
  400. #endif
  401. const_iterator2 end () const {
  402. return (*this) ().find2 (1, it1_, (*this) ().size2 ());
  403. }
  404. BOOST_UBLAS_INLINE
  405. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  406. typename self_type::
  407. #endif
  408. const_iterator2 cend () const {
  409. return end ();
  410. }
  411. BOOST_UBLAS_INLINE
  412. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  413. typename self_type::
  414. #endif
  415. const_reverse_iterator2 rbegin () const {
  416. return const_reverse_iterator2 (end ());
  417. }
  418. BOOST_UBLAS_INLINE
  419. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  420. typename self_type::
  421. #endif
  422. const_reverse_iterator2 crbegin () const {
  423. return rbegin ();
  424. }
  425. BOOST_UBLAS_INLINE
  426. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  427. typename self_type::
  428. #endif
  429. const_reverse_iterator2 rend () const {
  430. return const_reverse_iterator2 (begin ());
  431. }
  432. BOOST_UBLAS_INLINE
  433. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  434. typename self_type::
  435. #endif
  436. const_reverse_iterator2 crend () const {
  437. return rend ();
  438. }
  439. #endif
  440. // Indices
  441. BOOST_UBLAS_INLINE
  442. size_type index1 () const {
  443. return it1_;
  444. }
  445. BOOST_UBLAS_INLINE
  446. size_type index2 () const {
  447. return it2_;
  448. }
  449. // Assignment
  450. BOOST_UBLAS_INLINE
  451. const_iterator1 &operator = (const const_iterator1 &it) {
  452. container_const_reference<self_type>::assign (&it ());
  453. it1_ = it.it1_;
  454. it2_ = it.it2_;
  455. return *this;
  456. }
  457. // Comparison
  458. BOOST_UBLAS_INLINE
  459. bool operator == (const const_iterator1 &it) const {
  460. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  461. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  462. return it1_ == it.it1_;
  463. }
  464. BOOST_UBLAS_INLINE
  465. bool operator < (const const_iterator1 &it) const {
  466. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  467. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  468. return it1_ < it.it1_;
  469. }
  470. private:
  471. size_type it1_;
  472. size_type it2_;
  473. };
  474. #endif
  475. BOOST_UBLAS_INLINE
  476. const_iterator1 begin1 () const {
  477. return find1 (0, 0, 0);
  478. }
  479. BOOST_UBLAS_INLINE
  480. const_iterator1 cbegin1 () const {
  481. return begin1 ();
  482. }
  483. BOOST_UBLAS_INLINE
  484. const_iterator1 end1 () const {
  485. return find1 (0, size1_, 0);
  486. }
  487. BOOST_UBLAS_INLINE
  488. const_iterator1 cend1 () const {
  489. return end1 ();
  490. }
  491. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  492. class iterator1:
  493. public container_reference<triangular_matrix>,
  494. public random_access_iterator_base<packed_random_access_iterator_tag,
  495. iterator1, value_type> {
  496. public:
  497. typedef typename triangular_matrix::value_type value_type;
  498. typedef typename triangular_matrix::difference_type difference_type;
  499. typedef typename triangular_matrix::reference reference;
  500. typedef typename triangular_matrix::pointer pointer;
  501. typedef iterator2 dual_iterator_type;
  502. typedef reverse_iterator2 dual_reverse_iterator_type;
  503. // Construction and destruction
  504. BOOST_UBLAS_INLINE
  505. iterator1 ():
  506. container_reference<self_type> (), it1_ (), it2_ () {}
  507. BOOST_UBLAS_INLINE
  508. iterator1 (self_type &m, size_type it1, size_type it2):
  509. container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  510. // Arithmetic
  511. BOOST_UBLAS_INLINE
  512. iterator1 &operator ++ () {
  513. ++ it1_;
  514. return *this;
  515. }
  516. BOOST_UBLAS_INLINE
  517. iterator1 &operator -- () {
  518. -- it1_;
  519. return *this;
  520. }
  521. BOOST_UBLAS_INLINE
  522. iterator1 &operator += (difference_type n) {
  523. it1_ += n;
  524. return *this;
  525. }
  526. BOOST_UBLAS_INLINE
  527. iterator1 &operator -= (difference_type n) {
  528. it1_ -= n;
  529. return *this;
  530. }
  531. BOOST_UBLAS_INLINE
  532. difference_type operator - (const iterator1 &it) const {
  533. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  534. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  535. return it1_ - it.it1_;
  536. }
  537. // Dereference
  538. BOOST_UBLAS_INLINE
  539. reference operator * () const {
  540. return (*this) () (it1_, it2_);
  541. }
  542. BOOST_UBLAS_INLINE
  543. reference operator [] (difference_type n) const {
  544. return *(*this + n);
  545. }
  546. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  547. BOOST_UBLAS_INLINE
  548. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  549. typename self_type::
  550. #endif
  551. iterator2 begin () const {
  552. return (*this) ().find2 (1, it1_, 0);
  553. }
  554. BOOST_UBLAS_INLINE
  555. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  556. typename self_type::
  557. #endif
  558. iterator2 end () const {
  559. return (*this) ().find2 (1, it1_, (*this) ().size2 ());
  560. }
  561. BOOST_UBLAS_INLINE
  562. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  563. typename self_type::
  564. #endif
  565. reverse_iterator2 rbegin () const {
  566. return reverse_iterator2 (end ());
  567. }
  568. BOOST_UBLAS_INLINE
  569. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  570. typename self_type::
  571. #endif
  572. reverse_iterator2 rend () const {
  573. return reverse_iterator2 (begin ());
  574. }
  575. #endif
  576. // Indices
  577. BOOST_UBLAS_INLINE
  578. size_type index1 () const {
  579. return it1_;
  580. }
  581. BOOST_UBLAS_INLINE
  582. size_type index2 () const {
  583. return it2_;
  584. }
  585. // Assignment
  586. BOOST_UBLAS_INLINE
  587. iterator1 &operator = (const iterator1 &it) {
  588. container_reference<self_type>::assign (&it ());
  589. it1_ = it.it1_;
  590. it2_ = it.it2_;
  591. return *this;
  592. }
  593. // Comparison
  594. BOOST_UBLAS_INLINE
  595. bool operator == (const iterator1 &it) const {
  596. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  597. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  598. return it1_ == it.it1_;
  599. }
  600. BOOST_UBLAS_INLINE
  601. bool operator < (const iterator1 &it) const {
  602. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  603. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  604. return it1_ < it.it1_;
  605. }
  606. private:
  607. size_type it1_;
  608. size_type it2_;
  609. friend class const_iterator1;
  610. };
  611. #endif
  612. BOOST_UBLAS_INLINE
  613. iterator1 begin1 () {
  614. return find1 (0, 0, 0);
  615. }
  616. BOOST_UBLAS_INLINE
  617. iterator1 end1 () {
  618. return find1 (0, size1_, 0);
  619. }
  620. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  621. class const_iterator2:
  622. public container_const_reference<triangular_matrix>,
  623. public random_access_iterator_base<packed_random_access_iterator_tag,
  624. const_iterator2, value_type> {
  625. public:
  626. typedef typename triangular_matrix::value_type value_type;
  627. typedef typename triangular_matrix::difference_type difference_type;
  628. typedef typename triangular_matrix::const_reference reference;
  629. typedef const typename triangular_matrix::pointer pointer;
  630. typedef const_iterator1 dual_iterator_type;
  631. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  632. // Construction and destruction
  633. BOOST_UBLAS_INLINE
  634. const_iterator2 ():
  635. container_const_reference<self_type> (), it1_ (), it2_ () {}
  636. BOOST_UBLAS_INLINE
  637. const_iterator2 (const self_type &m, size_type it1, size_type it2):
  638. container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  639. BOOST_UBLAS_INLINE
  640. const_iterator2 (const iterator2 &it):
  641. container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
  642. // Arithmetic
  643. BOOST_UBLAS_INLINE
  644. const_iterator2 &operator ++ () {
  645. ++ it2_;
  646. return *this;
  647. }
  648. BOOST_UBLAS_INLINE
  649. const_iterator2 &operator -- () {
  650. -- it2_;
  651. return *this;
  652. }
  653. BOOST_UBLAS_INLINE
  654. const_iterator2 &operator += (difference_type n) {
  655. it2_ += n;
  656. return *this;
  657. }
  658. BOOST_UBLAS_INLINE
  659. const_iterator2 &operator -= (difference_type n) {
  660. it2_ -= n;
  661. return *this;
  662. }
  663. BOOST_UBLAS_INLINE
  664. difference_type operator - (const const_iterator2 &it) const {
  665. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  666. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  667. return it2_ - it.it2_;
  668. }
  669. // Dereference
  670. BOOST_UBLAS_INLINE
  671. const_reference operator * () const {
  672. return (*this) () (it1_, it2_);
  673. }
  674. BOOST_UBLAS_INLINE
  675. const_reference operator [] (difference_type n) const {
  676. return *(*this + n);
  677. }
  678. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  679. BOOST_UBLAS_INLINE
  680. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  681. typename self_type::
  682. #endif
  683. const_iterator1 begin () const {
  684. return (*this) ().find1 (1, 0, it2_);
  685. }
  686. BOOST_UBLAS_INLINE
  687. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  688. typename self_type::
  689. #endif
  690. const_iterator1 cbegin () const {
  691. return begin ();
  692. }
  693. BOOST_UBLAS_INLINE
  694. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  695. typename self_type::
  696. #endif
  697. const_iterator1 end () const {
  698. return (*this) ().find1 (1, (*this) ().size1 (), it2_);
  699. }
  700. BOOST_UBLAS_INLINE
  701. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  702. typename self_type::
  703. #endif
  704. const_iterator1 cend () const {
  705. return end ();
  706. }
  707. BOOST_UBLAS_INLINE
  708. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  709. typename self_type::
  710. #endif
  711. const_reverse_iterator1 rbegin () const {
  712. return const_reverse_iterator1 (end ());
  713. }
  714. BOOST_UBLAS_INLINE
  715. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  716. typename self_type::
  717. #endif
  718. const_reverse_iterator1 crbegin () const {
  719. return rbegin ();
  720. }
  721. BOOST_UBLAS_INLINE
  722. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  723. typename self_type::
  724. #endif
  725. const_reverse_iterator1 rend () const {
  726. return const_reverse_iterator1 (begin ());
  727. }
  728. BOOST_UBLAS_INLINE
  729. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  730. typename self_type::
  731. #endif
  732. const_reverse_iterator1 crend () const {
  733. return rend ();
  734. }
  735. #endif
  736. // Indices
  737. BOOST_UBLAS_INLINE
  738. size_type index1 () const {
  739. return it1_;
  740. }
  741. BOOST_UBLAS_INLINE
  742. size_type index2 () const {
  743. return it2_;
  744. }
  745. // Assignment
  746. BOOST_UBLAS_INLINE
  747. const_iterator2 &operator = (const const_iterator2 &it) {
  748. container_const_reference<self_type>::assign (&it ());
  749. it1_ = it.it1_;
  750. it2_ = it.it2_;
  751. return *this;
  752. }
  753. // Comparison
  754. BOOST_UBLAS_INLINE
  755. bool operator == (const const_iterator2 &it) const {
  756. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  757. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  758. return it2_ == it.it2_;
  759. }
  760. BOOST_UBLAS_INLINE
  761. bool operator < (const const_iterator2 &it) const {
  762. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  763. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  764. return it2_ < it.it2_;
  765. }
  766. private:
  767. size_type it1_;
  768. size_type it2_;
  769. };
  770. #endif
  771. BOOST_UBLAS_INLINE
  772. const_iterator2 begin2 () const {
  773. return find2 (0, 0, 0);
  774. }
  775. BOOST_UBLAS_INLINE
  776. const_iterator2 cbegin2 () const {
  777. return begin2 ();
  778. }
  779. BOOST_UBLAS_INLINE
  780. const_iterator2 end2 () const {
  781. return find2 (0, 0, size2_);
  782. }
  783. BOOST_UBLAS_INLINE
  784. const_iterator2 cend2 () const {
  785. return end2 ();
  786. }
  787. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  788. class iterator2:
  789. public container_reference<triangular_matrix>,
  790. public random_access_iterator_base<packed_random_access_iterator_tag,
  791. iterator2, value_type> {
  792. public:
  793. typedef typename triangular_matrix::value_type value_type;
  794. typedef typename triangular_matrix::difference_type difference_type;
  795. typedef typename triangular_matrix::reference reference;
  796. typedef typename triangular_matrix::pointer pointer;
  797. typedef iterator1 dual_iterator_type;
  798. typedef reverse_iterator1 dual_reverse_iterator_type;
  799. // Construction and destruction
  800. BOOST_UBLAS_INLINE
  801. iterator2 ():
  802. container_reference<self_type> (), it1_ (), it2_ () {}
  803. BOOST_UBLAS_INLINE
  804. iterator2 (self_type &m, size_type it1, size_type it2):
  805. container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  806. // Arithmetic
  807. BOOST_UBLAS_INLINE
  808. iterator2 &operator ++ () {
  809. ++ it2_;
  810. return *this;
  811. }
  812. BOOST_UBLAS_INLINE
  813. iterator2 &operator -- () {
  814. -- it2_;
  815. return *this;
  816. }
  817. BOOST_UBLAS_INLINE
  818. iterator2 &operator += (difference_type n) {
  819. it2_ += n;
  820. return *this;
  821. }
  822. BOOST_UBLAS_INLINE
  823. iterator2 &operator -= (difference_type n) {
  824. it2_ -= n;
  825. return *this;
  826. }
  827. BOOST_UBLAS_INLINE
  828. difference_type operator - (const iterator2 &it) const {
  829. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  830. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  831. return it2_ - it.it2_;
  832. }
  833. // Dereference
  834. BOOST_UBLAS_INLINE
  835. reference operator * () const {
  836. return (*this) () (it1_, it2_);
  837. }
  838. BOOST_UBLAS_INLINE
  839. reference operator [] (difference_type n) const {
  840. return *(*this + n);
  841. }
  842. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  843. BOOST_UBLAS_INLINE
  844. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  845. typename self_type::
  846. #endif
  847. iterator1 begin () const {
  848. return (*this) ().find1 (1, 0, it2_);
  849. }
  850. BOOST_UBLAS_INLINE
  851. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  852. typename self_type::
  853. #endif
  854. iterator1 end () const {
  855. return (*this) ().find1 (1, (*this) ().size1 (), it2_);
  856. }
  857. BOOST_UBLAS_INLINE
  858. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  859. typename self_type::
  860. #endif
  861. reverse_iterator1 rbegin () const {
  862. return reverse_iterator1 (end ());
  863. }
  864. BOOST_UBLAS_INLINE
  865. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  866. typename self_type::
  867. #endif
  868. reverse_iterator1 rend () const {
  869. return reverse_iterator1 (begin ());
  870. }
  871. #endif
  872. // Indices
  873. BOOST_UBLAS_INLINE
  874. size_type index1 () const {
  875. return it1_;
  876. }
  877. BOOST_UBLAS_INLINE
  878. size_type index2 () const {
  879. return it2_;
  880. }
  881. // Assignment
  882. BOOST_UBLAS_INLINE
  883. iterator2 &operator = (const iterator2 &it) {
  884. container_reference<self_type>::assign (&it ());
  885. it1_ = it.it1_;
  886. it2_ = it.it2_;
  887. return *this;
  888. }
  889. // Comparison
  890. BOOST_UBLAS_INLINE
  891. bool operator == (const iterator2 &it) const {
  892. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  893. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  894. return it2_ == it.it2_;
  895. }
  896. BOOST_UBLAS_INLINE
  897. bool operator < (const iterator2 &it) const {
  898. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  899. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  900. return it2_ < it.it2_;
  901. }
  902. private:
  903. size_type it1_;
  904. size_type it2_;
  905. friend class const_iterator2;
  906. };
  907. #endif
  908. BOOST_UBLAS_INLINE
  909. iterator2 begin2 () {
  910. return find2 (0, 0, 0);
  911. }
  912. BOOST_UBLAS_INLINE
  913. iterator2 end2 () {
  914. return find2 (0, 0, size2_);
  915. }
  916. // Reverse iterators
  917. BOOST_UBLAS_INLINE
  918. const_reverse_iterator1 rbegin1 () const {
  919. return const_reverse_iterator1 (end1 ());
  920. }
  921. BOOST_UBLAS_INLINE
  922. const_reverse_iterator1 crbegin1 () const {
  923. return rbegin1 ();
  924. }
  925. BOOST_UBLAS_INLINE
  926. const_reverse_iterator1 rend1 () const {
  927. return const_reverse_iterator1 (begin1 ());
  928. }
  929. BOOST_UBLAS_INLINE
  930. const_reverse_iterator1 crend1 () const {
  931. return rend1 ();
  932. }
  933. BOOST_UBLAS_INLINE
  934. reverse_iterator1 rbegin1 () {
  935. return reverse_iterator1 (end1 ());
  936. }
  937. BOOST_UBLAS_INLINE
  938. reverse_iterator1 rend1 () {
  939. return reverse_iterator1 (begin1 ());
  940. }
  941. BOOST_UBLAS_INLINE
  942. const_reverse_iterator2 rbegin2 () const {
  943. return const_reverse_iterator2 (end2 ());
  944. }
  945. BOOST_UBLAS_INLINE
  946. const_reverse_iterator2 crbegin2 () const {
  947. return rbegin2 ();
  948. }
  949. BOOST_UBLAS_INLINE
  950. const_reverse_iterator2 rend2 () const {
  951. return const_reverse_iterator2 (begin2 ());
  952. }
  953. BOOST_UBLAS_INLINE
  954. const_reverse_iterator2 crend2 () const {
  955. return rend2 ();
  956. }
  957. BOOST_UBLAS_INLINE
  958. reverse_iterator2 rbegin2 () {
  959. return reverse_iterator2 (end2 ());
  960. }
  961. BOOST_UBLAS_INLINE
  962. reverse_iterator2 rend2 () {
  963. return reverse_iterator2 (begin2 ());
  964. }
  965. private:
  966. size_type size1_;
  967. size_type size2_;
  968. array_type data_;
  969. static const value_type zero_;
  970. static const value_type one_;
  971. };
  972. template<class T, class TRI, class L, class A>
  973. const typename triangular_matrix<T, TRI, L, A>::value_type triangular_matrix<T, TRI, L, A>::zero_ = value_type/*zero*/();
  974. template<class T, class TRI, class L, class A>
  975. const typename triangular_matrix<T, TRI, L, A>::value_type triangular_matrix<T, TRI, L, A>::one_ (1);
  976. // Triangular matrix adaptor class
  977. template<class M, class TRI>
  978. class triangular_adaptor:
  979. public matrix_expression<triangular_adaptor<M, TRI> > {
  980. typedef triangular_adaptor<M, TRI> self_type;
  981. public:
  982. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  983. using matrix_expression<self_type>::operator ();
  984. #endif
  985. typedef const M const_matrix_type;
  986. typedef M matrix_type;
  987. typedef TRI triangular_type;
  988. typedef typename M::size_type size_type;
  989. typedef typename M::difference_type difference_type;
  990. typedef typename M::value_type value_type;
  991. typedef typename M::const_reference const_reference;
  992. typedef typename boost::mpl::if_<boost::is_const<M>,
  993. typename M::const_reference,
  994. typename M::reference>::type reference;
  995. typedef typename boost::mpl::if_<boost::is_const<M>,
  996. typename M::const_closure_type,
  997. typename M::closure_type>::type matrix_closure_type;
  998. typedef const self_type const_closure_type;
  999. typedef self_type closure_type;
  1000. // Replaced by _temporary_traits to avoid type requirements on M
  1001. //typedef typename M::vector_temporary_type vector_temporary_type;
  1002. //typedef typename M::matrix_temporary_type matrix_temporary_type;
  1003. typedef typename storage_restrict_traits<typename M::storage_category,
  1004. packed_proxy_tag>::storage_category storage_category;
  1005. typedef typename M::orientation_category orientation_category;
  1006. // Construction and destruction
  1007. BOOST_UBLAS_INLINE
  1008. triangular_adaptor (matrix_type &data):
  1009. matrix_expression<self_type> (),
  1010. data_ (data) {}
  1011. BOOST_UBLAS_INLINE
  1012. triangular_adaptor (const triangular_adaptor &m):
  1013. matrix_expression<self_type> (),
  1014. data_ (m.data_) {}
  1015. // Accessors
  1016. BOOST_UBLAS_INLINE
  1017. size_type size1 () const {
  1018. return data_.size1 ();
  1019. }
  1020. BOOST_UBLAS_INLINE
  1021. size_type size2 () const {
  1022. return data_.size2 ();
  1023. }
  1024. // Storage accessors
  1025. BOOST_UBLAS_INLINE
  1026. const matrix_closure_type &data () const {
  1027. return data_;
  1028. }
  1029. BOOST_UBLAS_INLINE
  1030. matrix_closure_type &data () {
  1031. return data_;
  1032. }
  1033. // Element access
  1034. #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
  1035. BOOST_UBLAS_INLINE
  1036. const_reference operator () (size_type i, size_type j) const {
  1037. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1038. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1039. if (triangular_type::other (i, j))
  1040. return data () (i, j);
  1041. else if (triangular_type::one (i, j))
  1042. return one_;
  1043. else
  1044. return zero_;
  1045. }
  1046. BOOST_UBLAS_INLINE
  1047. reference operator () (size_type i, size_type j) {
  1048. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1049. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1050. if (!triangular_type::other (i, j)) {
  1051. bad_index ().raise ();
  1052. // NEVER reached
  1053. }
  1054. return data () (i, j);
  1055. }
  1056. #else
  1057. BOOST_UBLAS_INLINE
  1058. reference operator () (size_type i, size_type j) const {
  1059. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1060. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1061. if (!triangular_type::other (i, j)) {
  1062. bad_index ().raise ();
  1063. // NEVER reached
  1064. }
  1065. return data () (i, j);
  1066. }
  1067. #endif
  1068. // Assignment
  1069. BOOST_UBLAS_INLINE
  1070. triangular_adaptor &operator = (const triangular_adaptor &m) {
  1071. matrix_assign<scalar_assign> (*this, m);
  1072. return *this;
  1073. }
  1074. BOOST_UBLAS_INLINE
  1075. triangular_adaptor &assign_temporary (triangular_adaptor &m) {
  1076. *this = m;
  1077. return *this;
  1078. }
  1079. template<class AE>
  1080. BOOST_UBLAS_INLINE
  1081. triangular_adaptor &operator = (const matrix_expression<AE> &ae) {
  1082. matrix_assign<scalar_assign> (*this, matrix<value_type> (ae));
  1083. return *this;
  1084. }
  1085. template<class AE>
  1086. BOOST_UBLAS_INLINE
  1087. triangular_adaptor &assign (const matrix_expression<AE> &ae) {
  1088. matrix_assign<scalar_assign> (*this, ae);
  1089. return *this;
  1090. }
  1091. template<class AE>
  1092. BOOST_UBLAS_INLINE
  1093. triangular_adaptor& operator += (const matrix_expression<AE> &ae) {
  1094. matrix_assign<scalar_assign> (*this, matrix<value_type> (*this + ae));
  1095. return *this;
  1096. }
  1097. template<class AE>
  1098. BOOST_UBLAS_INLINE
  1099. triangular_adaptor &plus_assign (const matrix_expression<AE> &ae) {
  1100. matrix_assign<scalar_plus_assign> (*this, ae);
  1101. return *this;
  1102. }
  1103. template<class AE>
  1104. BOOST_UBLAS_INLINE
  1105. triangular_adaptor& operator -= (const matrix_expression<AE> &ae) {
  1106. matrix_assign<scalar_assign> (*this, matrix<value_type> (*this - ae));
  1107. return *this;
  1108. }
  1109. template<class AE>
  1110. BOOST_UBLAS_INLINE
  1111. triangular_adaptor &minus_assign (const matrix_expression<AE> &ae) {
  1112. matrix_assign<scalar_minus_assign> (*this, ae);
  1113. return *this;
  1114. }
  1115. template<class AT>
  1116. BOOST_UBLAS_INLINE
  1117. triangular_adaptor& operator *= (const AT &at) {
  1118. matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  1119. return *this;
  1120. }
  1121. template<class AT>
  1122. BOOST_UBLAS_INLINE
  1123. triangular_adaptor& operator /= (const AT &at) {
  1124. matrix_assign_scalar<scalar_divides_assign> (*this, at);
  1125. return *this;
  1126. }
  1127. // Closure comparison
  1128. BOOST_UBLAS_INLINE
  1129. bool same_closure (const triangular_adaptor &ta) const {
  1130. return (*this).data ().same_closure (ta.data ());
  1131. }
  1132. // Swapping
  1133. BOOST_UBLAS_INLINE
  1134. void swap (triangular_adaptor &m) {
  1135. if (this != &m)
  1136. matrix_swap<scalar_swap> (*this, m);
  1137. }
  1138. BOOST_UBLAS_INLINE
  1139. friend void swap (triangular_adaptor &m1, triangular_adaptor &m2) {
  1140. m1.swap (m2);
  1141. }
  1142. // Iterator types
  1143. private:
  1144. typedef typename M::const_iterator1 const_subiterator1_type;
  1145. typedef typename boost::mpl::if_<boost::is_const<M>,
  1146. typename M::const_iterator1,
  1147. typename M::iterator1>::type subiterator1_type;
  1148. typedef typename M::const_iterator2 const_subiterator2_type;
  1149. typedef typename boost::mpl::if_<boost::is_const<M>,
  1150. typename M::const_iterator2,
  1151. typename M::iterator2>::type subiterator2_type;
  1152. public:
  1153. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1154. typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
  1155. typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
  1156. typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
  1157. typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
  1158. #else
  1159. class const_iterator1;
  1160. class iterator1;
  1161. class const_iterator2;
  1162. class iterator2;
  1163. #endif
  1164. typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  1165. typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  1166. typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  1167. typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  1168. // Element lookup
  1169. BOOST_UBLAS_INLINE
  1170. const_iterator1 find1 (int rank, size_type i, size_type j) const {
  1171. if (rank == 1)
  1172. i = triangular_type::restrict1 (i, j, size1(), size2());
  1173. if (rank == 0)
  1174. i = triangular_type::global_restrict1 (i, size1(), j, size2());
  1175. return const_iterator1 (*this, data ().find1 (rank, i, j));
  1176. }
  1177. BOOST_UBLAS_INLINE
  1178. iterator1 find1 (int rank, size_type i, size_type j) {
  1179. if (rank == 1)
  1180. i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
  1181. if (rank == 0)
  1182. i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
  1183. return iterator1 (*this, data ().find1 (rank, i, j));
  1184. }
  1185. BOOST_UBLAS_INLINE
  1186. const_iterator2 find2 (int rank, size_type i, size_type j) const {
  1187. if (rank == 1)
  1188. j = triangular_type::restrict2 (i, j, size1(), size2());
  1189. if (rank == 0)
  1190. j = triangular_type::global_restrict2 (i, size1(), j, size2());
  1191. return const_iterator2 (*this, data ().find2 (rank, i, j));
  1192. }
  1193. BOOST_UBLAS_INLINE
  1194. iterator2 find2 (int rank, size_type i, size_type j) {
  1195. if (rank == 1)
  1196. j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
  1197. if (rank == 0)
  1198. j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
  1199. return iterator2 (*this, data ().find2 (rank, i, j));
  1200. }
  1201. // Iterators simply are indices.
  1202. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1203. class const_iterator1:
  1204. public container_const_reference<triangular_adaptor>,
  1205. public random_access_iterator_base<typename iterator_restrict_traits<
  1206. typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1207. const_iterator1, value_type> {
  1208. public:
  1209. typedef typename const_subiterator1_type::value_type value_type;
  1210. typedef typename const_subiterator1_type::difference_type difference_type;
  1211. typedef typename const_subiterator1_type::reference reference;
  1212. typedef typename const_subiterator1_type::pointer pointer;
  1213. typedef const_iterator2 dual_iterator_type;
  1214. typedef const_reverse_iterator2 dual_reverse_iterator_type;
  1215. // Construction and destruction
  1216. BOOST_UBLAS_INLINE
  1217. const_iterator1 ():
  1218. container_const_reference<self_type> (), it1_ () {}
  1219. BOOST_UBLAS_INLINE
  1220. const_iterator1 (const self_type &m, const const_subiterator1_type &it1):
  1221. container_const_reference<self_type> (m), it1_ (it1) {}
  1222. BOOST_UBLAS_INLINE
  1223. const_iterator1 (const iterator1 &it):
  1224. container_const_reference<self_type> (it ()), it1_ (it.it1_) {}
  1225. // Arithmetic
  1226. BOOST_UBLAS_INLINE
  1227. const_iterator1 &operator ++ () {
  1228. ++ it1_;
  1229. return *this;
  1230. }
  1231. BOOST_UBLAS_INLINE
  1232. const_iterator1 &operator -- () {
  1233. -- it1_;
  1234. return *this;
  1235. }
  1236. BOOST_UBLAS_INLINE
  1237. const_iterator1 &operator += (difference_type n) {
  1238. it1_ += n;
  1239. return *this;
  1240. }
  1241. BOOST_UBLAS_INLINE
  1242. const_iterator1 &operator -= (difference_type n) {
  1243. it1_ -= n;
  1244. return *this;
  1245. }
  1246. BOOST_UBLAS_INLINE
  1247. difference_type operator - (const const_iterator1 &it) const {
  1248. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1249. return it1_ - it.it1_;
  1250. }
  1251. // Dereference
  1252. BOOST_UBLAS_INLINE
  1253. const_reference operator * () const {
  1254. size_type i = index1 ();
  1255. size_type j = index2 ();
  1256. BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1257. BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1258. if (triangular_type::other (i, j))
  1259. return *it1_;
  1260. else
  1261. return (*this) () (i, j);
  1262. }
  1263. BOOST_UBLAS_INLINE
  1264. const_reference operator [] (difference_type n) const {
  1265. return *(*this + n);
  1266. }
  1267. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1268. BOOST_UBLAS_INLINE
  1269. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1270. typename self_type::
  1271. #endif
  1272. const_iterator2 begin () const {
  1273. return (*this) ().find2 (1, index1 (), 0);
  1274. }
  1275. BOOST_UBLAS_INLINE
  1276. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1277. typename self_type::
  1278. #endif
  1279. const_iterator2 cbegin () const {
  1280. return begin ();
  1281. }
  1282. BOOST_UBLAS_INLINE
  1283. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1284. typename self_type::
  1285. #endif
  1286. const_iterator2 end () const {
  1287. return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  1288. }
  1289. BOOST_UBLAS_INLINE
  1290. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1291. typename self_type::
  1292. #endif
  1293. const_iterator2 cend () const {
  1294. return end ();
  1295. }
  1296. BOOST_UBLAS_INLINE
  1297. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1298. typename self_type::
  1299. #endif
  1300. const_reverse_iterator2 rbegin () const {
  1301. return const_reverse_iterator2 (end ());
  1302. }
  1303. BOOST_UBLAS_INLINE
  1304. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1305. typename self_type::
  1306. #endif
  1307. const_reverse_iterator2 crbegin () const {
  1308. return rbegin ();
  1309. }
  1310. BOOST_UBLAS_INLINE
  1311. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1312. typename self_type::
  1313. #endif
  1314. const_reverse_iterator2 rend () const {
  1315. return const_reverse_iterator2 (begin ());
  1316. }
  1317. BOOST_UBLAS_INLINE
  1318. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1319. typename self_type::
  1320. #endif
  1321. const_reverse_iterator2 crend () const {
  1322. return rend ();
  1323. }
  1324. #endif
  1325. // Indices
  1326. BOOST_UBLAS_INLINE
  1327. size_type index1 () const {
  1328. return it1_.index1 ();
  1329. }
  1330. BOOST_UBLAS_INLINE
  1331. size_type index2 () const {
  1332. return it1_.index2 ();
  1333. }
  1334. // Assignment
  1335. BOOST_UBLAS_INLINE
  1336. const_iterator1 &operator = (const const_iterator1 &it) {
  1337. container_const_reference<self_type>::assign (&it ());
  1338. it1_ = it.it1_;
  1339. return *this;
  1340. }
  1341. // Comparison
  1342. BOOST_UBLAS_INLINE
  1343. bool operator == (const const_iterator1 &it) const {
  1344. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1345. return it1_ == it.it1_;
  1346. }
  1347. BOOST_UBLAS_INLINE
  1348. bool operator < (const const_iterator1 &it) const {
  1349. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1350. return it1_ < it.it1_;
  1351. }
  1352. private:
  1353. const_subiterator1_type it1_;
  1354. };
  1355. #endif
  1356. BOOST_UBLAS_INLINE
  1357. const_iterator1 begin1 () const {
  1358. return find1 (0, 0, 0);
  1359. }
  1360. BOOST_UBLAS_INLINE
  1361. const_iterator1 cbegin1 () const {
  1362. return begin1 ();
  1363. }
  1364. BOOST_UBLAS_INLINE
  1365. const_iterator1 end1 () const {
  1366. return find1 (0, size1 (), 0);
  1367. }
  1368. BOOST_UBLAS_INLINE
  1369. const_iterator1 cend1 () const {
  1370. return end1 ();
  1371. }
  1372. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1373. class iterator1:
  1374. public container_reference<triangular_adaptor>,
  1375. public random_access_iterator_base<typename iterator_restrict_traits<
  1376. typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1377. iterator1, value_type> {
  1378. public:
  1379. typedef typename subiterator1_type::value_type value_type;
  1380. typedef typename subiterator1_type::difference_type difference_type;
  1381. typedef typename subiterator1_type::reference reference;
  1382. typedef typename subiterator1_type::pointer pointer;
  1383. typedef iterator2 dual_iterator_type;
  1384. typedef reverse_iterator2 dual_reverse_iterator_type;
  1385. // Construction and destruction
  1386. BOOST_UBLAS_INLINE
  1387. iterator1 ():
  1388. container_reference<self_type> (), it1_ () {}
  1389. BOOST_UBLAS_INLINE
  1390. iterator1 (self_type &m, const subiterator1_type &it1):
  1391. container_reference<self_type> (m), it1_ (it1) {}
  1392. // Arithmetic
  1393. BOOST_UBLAS_INLINE
  1394. iterator1 &operator ++ () {
  1395. ++ it1_;
  1396. return *this;
  1397. }
  1398. BOOST_UBLAS_INLINE
  1399. iterator1 &operator -- () {
  1400. -- it1_;
  1401. return *this;
  1402. }
  1403. BOOST_UBLAS_INLINE
  1404. iterator1 &operator += (difference_type n) {
  1405. it1_ += n;
  1406. return *this;
  1407. }
  1408. BOOST_UBLAS_INLINE
  1409. iterator1 &operator -= (difference_type n) {
  1410. it1_ -= n;
  1411. return *this;
  1412. }
  1413. BOOST_UBLAS_INLINE
  1414. difference_type operator - (const iterator1 &it) const {
  1415. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1416. return it1_ - it.it1_;
  1417. }
  1418. // Dereference
  1419. BOOST_UBLAS_INLINE
  1420. reference operator * () const {
  1421. size_type i = index1 ();
  1422. size_type j = index2 ();
  1423. BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1424. BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1425. if (triangular_type::other (i, j))
  1426. return *it1_;
  1427. else
  1428. return (*this) () (i, j);
  1429. }
  1430. BOOST_UBLAS_INLINE
  1431. reference operator [] (difference_type n) const {
  1432. return *(*this + n);
  1433. }
  1434. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1435. BOOST_UBLAS_INLINE
  1436. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1437. typename self_type::
  1438. #endif
  1439. iterator2 begin () const {
  1440. return (*this) ().find2 (1, index1 (), 0);
  1441. }
  1442. BOOST_UBLAS_INLINE
  1443. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1444. typename self_type::
  1445. #endif
  1446. iterator2 end () const {
  1447. return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  1448. }
  1449. BOOST_UBLAS_INLINE
  1450. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1451. typename self_type::
  1452. #endif
  1453. reverse_iterator2 rbegin () const {
  1454. return reverse_iterator2 (end ());
  1455. }
  1456. BOOST_UBLAS_INLINE
  1457. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1458. typename self_type::
  1459. #endif
  1460. reverse_iterator2 rend () const {
  1461. return reverse_iterator2 (begin ());
  1462. }
  1463. #endif
  1464. // Indices
  1465. BOOST_UBLAS_INLINE
  1466. size_type index1 () const {
  1467. return it1_.index1 ();
  1468. }
  1469. BOOST_UBLAS_INLINE
  1470. size_type index2 () const {
  1471. return it1_.index2 ();
  1472. }
  1473. // Assignment
  1474. BOOST_UBLAS_INLINE
  1475. iterator1 &operator = (const iterator1 &it) {
  1476. container_reference<self_type>::assign (&it ());
  1477. it1_ = it.it1_;
  1478. return *this;
  1479. }
  1480. // Comparison
  1481. BOOST_UBLAS_INLINE
  1482. bool operator == (const iterator1 &it) const {
  1483. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1484. return it1_ == it.it1_;
  1485. }
  1486. BOOST_UBLAS_INLINE
  1487. bool operator < (const iterator1 &it) const {
  1488. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1489. return it1_ < it.it1_;
  1490. }
  1491. private:
  1492. subiterator1_type it1_;
  1493. friend class const_iterator1;
  1494. };
  1495. #endif
  1496. BOOST_UBLAS_INLINE
  1497. iterator1 begin1 () {
  1498. return find1 (0, 0, 0);
  1499. }
  1500. BOOST_UBLAS_INLINE
  1501. iterator1 end1 () {
  1502. return find1 (0, size1 (), 0);
  1503. }
  1504. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1505. class const_iterator2:
  1506. public container_const_reference<triangular_adaptor>,
  1507. public random_access_iterator_base<typename iterator_restrict_traits<
  1508. typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1509. const_iterator2, value_type> {
  1510. public:
  1511. typedef typename const_subiterator2_type::value_type value_type;
  1512. typedef typename const_subiterator2_type::difference_type difference_type;
  1513. typedef typename const_subiterator2_type::reference reference;
  1514. typedef typename const_subiterator2_type::pointer pointer;
  1515. typedef const_iterator1 dual_iterator_type;
  1516. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  1517. // Construction and destruction
  1518. BOOST_UBLAS_INLINE
  1519. const_iterator2 ():
  1520. container_const_reference<self_type> (), it2_ () {}
  1521. BOOST_UBLAS_INLINE
  1522. const_iterator2 (const self_type &m, const const_subiterator2_type &it2):
  1523. container_const_reference<self_type> (m), it2_ (it2) {}
  1524. BOOST_UBLAS_INLINE
  1525. const_iterator2 (const iterator2 &it):
  1526. container_const_reference<self_type> (it ()), it2_ (it.it2_) {}
  1527. // Arithmetic
  1528. BOOST_UBLAS_INLINE
  1529. const_iterator2 &operator ++ () {
  1530. ++ it2_;
  1531. return *this;
  1532. }
  1533. BOOST_UBLAS_INLINE
  1534. const_iterator2 &operator -- () {
  1535. -- it2_;
  1536. return *this;
  1537. }
  1538. BOOST_UBLAS_INLINE
  1539. const_iterator2 &operator += (difference_type n) {
  1540. it2_ += n;
  1541. return *this;
  1542. }
  1543. BOOST_UBLAS_INLINE
  1544. const_iterator2 &operator -= (difference_type n) {
  1545. it2_ -= n;
  1546. return *this;
  1547. }
  1548. BOOST_UBLAS_INLINE
  1549. difference_type operator - (const const_iterator2 &it) const {
  1550. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1551. return it2_ - it.it2_;
  1552. }
  1553. // Dereference
  1554. BOOST_UBLAS_INLINE
  1555. const_reference operator * () const {
  1556. size_type i = index1 ();
  1557. size_type j = index2 ();
  1558. BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1559. BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1560. if (triangular_type::other (i, j))
  1561. return *it2_;
  1562. else
  1563. return (*this) () (i, j);
  1564. }
  1565. BOOST_UBLAS_INLINE
  1566. const_reference operator [] (difference_type n) const {
  1567. return *(*this + n);
  1568. }
  1569. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1570. BOOST_UBLAS_INLINE
  1571. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1572. typename self_type::
  1573. #endif
  1574. const_iterator1 begin () const {
  1575. return (*this) ().find1 (1, 0, index2 ());
  1576. }
  1577. BOOST_UBLAS_INLINE
  1578. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1579. typename self_type::
  1580. #endif
  1581. const_iterator1 cbegin () const {
  1582. return begin ();
  1583. }
  1584. BOOST_UBLAS_INLINE
  1585. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1586. typename self_type::
  1587. #endif
  1588. const_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. const_iterator1 cend () const {
  1596. return end ();
  1597. }
  1598. BOOST_UBLAS_INLINE
  1599. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1600. typename self_type::
  1601. #endif
  1602. const_reverse_iterator1 rbegin () const {
  1603. return const_reverse_iterator1 (end ());
  1604. }
  1605. BOOST_UBLAS_INLINE
  1606. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1607. typename self_type::
  1608. #endif
  1609. const_reverse_iterator1 crbegin () const {
  1610. return rbegin ();
  1611. }
  1612. BOOST_UBLAS_INLINE
  1613. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1614. typename self_type::
  1615. #endif
  1616. const_reverse_iterator1 rend () const {
  1617. return const_reverse_iterator1 (begin ());
  1618. }
  1619. BOOST_UBLAS_INLINE
  1620. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1621. typename self_type::
  1622. #endif
  1623. const_reverse_iterator1 crend () const {
  1624. return rend ();
  1625. }
  1626. #endif
  1627. // Indices
  1628. BOOST_UBLAS_INLINE
  1629. size_type index1 () const {
  1630. return it2_.index1 ();
  1631. }
  1632. BOOST_UBLAS_INLINE
  1633. size_type index2 () const {
  1634. return it2_.index2 ();
  1635. }
  1636. // Assignment
  1637. BOOST_UBLAS_INLINE
  1638. const_iterator2 &operator = (const const_iterator2 &it) {
  1639. container_const_reference<self_type>::assign (&it ());
  1640. it2_ = it.it2_;
  1641. return *this;
  1642. }
  1643. // Comparison
  1644. BOOST_UBLAS_INLINE
  1645. bool operator == (const const_iterator2 &it) const {
  1646. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1647. return it2_ == it.it2_;
  1648. }
  1649. BOOST_UBLAS_INLINE
  1650. bool operator < (const const_iterator2 &it) const {
  1651. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1652. return it2_ < it.it2_;
  1653. }
  1654. private:
  1655. const_subiterator2_type it2_;
  1656. };
  1657. #endif
  1658. BOOST_UBLAS_INLINE
  1659. const_iterator2 begin2 () const {
  1660. return find2 (0, 0, 0);
  1661. }
  1662. BOOST_UBLAS_INLINE
  1663. const_iterator2 cbegin2 () const {
  1664. return begin2 ();
  1665. }
  1666. BOOST_UBLAS_INLINE
  1667. const_iterator2 end2 () const {
  1668. return find2 (0, 0, size2 ());
  1669. }
  1670. BOOST_UBLAS_INLINE
  1671. const_iterator2 cend2 () const {
  1672. return end2 ();
  1673. }
  1674. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1675. class iterator2:
  1676. public container_reference<triangular_adaptor>,
  1677. public random_access_iterator_base<typename iterator_restrict_traits<
  1678. typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1679. iterator2, value_type> {
  1680. public:
  1681. typedef typename subiterator2_type::value_type value_type;
  1682. typedef typename subiterator2_type::difference_type difference_type;
  1683. typedef typename subiterator2_type::reference reference;
  1684. typedef typename subiterator2_type::pointer pointer;
  1685. typedef iterator1 dual_iterator_type;
  1686. typedef reverse_iterator1 dual_reverse_iterator_type;
  1687. // Construction and destruction
  1688. BOOST_UBLAS_INLINE
  1689. iterator2 ():
  1690. container_reference<self_type> (), it2_ () {}
  1691. BOOST_UBLAS_INLINE
  1692. iterator2 (self_type &m, const subiterator2_type &it2):
  1693. container_reference<self_type> (m), it2_ (it2) {}
  1694. // Arithmetic
  1695. BOOST_UBLAS_INLINE
  1696. iterator2 &operator ++ () {
  1697. ++ it2_;
  1698. return *this;
  1699. }
  1700. BOOST_UBLAS_INLINE
  1701. iterator2 &operator -- () {
  1702. -- it2_;
  1703. return *this;
  1704. }
  1705. BOOST_UBLAS_INLINE
  1706. iterator2 &operator += (difference_type n) {
  1707. it2_ += n;
  1708. return *this;
  1709. }
  1710. BOOST_UBLAS_INLINE
  1711. iterator2 &operator -= (difference_type n) {
  1712. it2_ -= n;
  1713. return *this;
  1714. }
  1715. BOOST_UBLAS_INLINE
  1716. difference_type operator - (const iterator2 &it) const {
  1717. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1718. return it2_ - it.it2_;
  1719. }
  1720. // Dereference
  1721. BOOST_UBLAS_INLINE
  1722. reference operator * () const {
  1723. size_type i = index1 ();
  1724. size_type j = index2 ();
  1725. BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
  1726. BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
  1727. if (triangular_type::other (i, j))
  1728. return *it2_;
  1729. else
  1730. return (*this) () (i, j);
  1731. }
  1732. BOOST_UBLAS_INLINE
  1733. reference operator [] (difference_type n) const {
  1734. return *(*this + n);
  1735. }
  1736. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1737. BOOST_UBLAS_INLINE
  1738. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1739. typename self_type::
  1740. #endif
  1741. iterator1 begin () const {
  1742. return (*this) ().find1 (1, 0, index2 ());
  1743. }
  1744. BOOST_UBLAS_INLINE
  1745. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1746. typename self_type::
  1747. #endif
  1748. iterator1 end () const {
  1749. return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
  1750. }
  1751. BOOST_UBLAS_INLINE
  1752. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1753. typename self_type::
  1754. #endif
  1755. reverse_iterator1 rbegin () const {
  1756. return reverse_iterator1 (end ());
  1757. }
  1758. BOOST_UBLAS_INLINE
  1759. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1760. typename self_type::
  1761. #endif
  1762. reverse_iterator1 rend () const {
  1763. return reverse_iterator1 (begin ());
  1764. }
  1765. #endif
  1766. // Indices
  1767. BOOST_UBLAS_INLINE
  1768. size_type index1 () const {
  1769. return it2_.index1 ();
  1770. }
  1771. BOOST_UBLAS_INLINE
  1772. size_type index2 () const {
  1773. return it2_.index2 ();
  1774. }
  1775. // Assignment
  1776. BOOST_UBLAS_INLINE
  1777. iterator2 &operator = (const iterator2 &it) {
  1778. container_reference<self_type>::assign (&it ());
  1779. it2_ = it.it2_;
  1780. return *this;
  1781. }
  1782. // Comparison
  1783. BOOST_UBLAS_INLINE
  1784. bool operator == (const iterator2 &it) const {
  1785. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1786. return it2_ == it.it2_;
  1787. }
  1788. BOOST_UBLAS_INLINE
  1789. bool operator < (const iterator2 &it) const {
  1790. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1791. return it2_ < it.it2_;
  1792. }
  1793. private:
  1794. subiterator2_type it2_;
  1795. friend class const_iterator2;
  1796. };
  1797. #endif
  1798. BOOST_UBLAS_INLINE
  1799. iterator2 begin2 () {
  1800. return find2 (0, 0, 0);
  1801. }
  1802. BOOST_UBLAS_INLINE
  1803. iterator2 end2 () {
  1804. return find2 (0, 0, size2 ());
  1805. }
  1806. // Reverse iterators
  1807. BOOST_UBLAS_INLINE
  1808. const_reverse_iterator1 rbegin1 () const {
  1809. return const_reverse_iterator1 (end1 ());
  1810. }
  1811. BOOST_UBLAS_INLINE
  1812. const_reverse_iterator1 crbegin1 () const {
  1813. return rbegin1 ();
  1814. }
  1815. BOOST_UBLAS_INLINE
  1816. const_reverse_iterator1 rend1 () const {
  1817. return const_reverse_iterator1 (begin1 ());
  1818. }
  1819. BOOST_UBLAS_INLINE
  1820. const_reverse_iterator1 crend1 () const {
  1821. return rend1 ();
  1822. }
  1823. BOOST_UBLAS_INLINE
  1824. reverse_iterator1 rbegin1 () {
  1825. return reverse_iterator1 (end1 ());
  1826. }
  1827. BOOST_UBLAS_INLINE
  1828. reverse_iterator1 rend1 () {
  1829. return reverse_iterator1 (begin1 ());
  1830. }
  1831. BOOST_UBLAS_INLINE
  1832. const_reverse_iterator2 rbegin2 () const {
  1833. return const_reverse_iterator2 (end2 ());
  1834. }
  1835. BOOST_UBLAS_INLINE
  1836. const_reverse_iterator2 crbegin2 () const {
  1837. return rbegin2 ();
  1838. }
  1839. BOOST_UBLAS_INLINE
  1840. const_reverse_iterator2 rend2 () const {
  1841. return const_reverse_iterator2 (begin2 ());
  1842. }
  1843. BOOST_UBLAS_INLINE
  1844. const_reverse_iterator2 crend2 () const {
  1845. return rend2 ();
  1846. }
  1847. BOOST_UBLAS_INLINE
  1848. reverse_iterator2 rbegin2 () {
  1849. return reverse_iterator2 (end2 ());
  1850. }
  1851. BOOST_UBLAS_INLINE
  1852. reverse_iterator2 rend2 () {
  1853. return reverse_iterator2 (begin2 ());
  1854. }
  1855. private:
  1856. matrix_closure_type data_;
  1857. static const value_type zero_;
  1858. static const value_type one_;
  1859. };
  1860. template<class M, class TRI>
  1861. const typename triangular_adaptor<M, TRI>::value_type triangular_adaptor<M, TRI>::zero_ = value_type/*zero*/();
  1862. template<class M, class TRI>
  1863. const typename triangular_adaptor<M, TRI>::value_type triangular_adaptor<M, TRI>::one_ (1);
  1864. template <class M, class TRI>
  1865. struct vector_temporary_traits< triangular_adaptor<M, TRI> >
  1866. : vector_temporary_traits< typename boost::remove_const<M>::type > {} ;
  1867. template <class M, class TRI>
  1868. struct vector_temporary_traits< const triangular_adaptor<M, TRI> >
  1869. : vector_temporary_traits< typename boost::remove_const<M>::type > {} ;
  1870. template <class M, class TRI>
  1871. struct matrix_temporary_traits< triangular_adaptor<M, TRI> >
  1872. : matrix_temporary_traits< typename boost::remove_const<M>::type > {};
  1873. template <class M, class TRI>
  1874. struct matrix_temporary_traits< const triangular_adaptor<M, TRI> >
  1875. : matrix_temporary_traits< typename boost::remove_const<M>::type > {};
  1876. template<class E1, class E2>
  1877. struct matrix_vector_solve_traits {
  1878. typedef typename promote_traits<typename E1::value_type, typename E2::value_type>::promote_type promote_type;
  1879. typedef vector<promote_type> result_type;
  1880. };
  1881. // Operations:
  1882. // n * (n - 1) / 2 + n = n * (n + 1) / 2 multiplications,
  1883. // n * (n - 1) / 2 additions
  1884. // Dense (proxy) case
  1885. template<class E1, class E2>
  1886. BOOST_UBLAS_INLINE
  1887. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1888. lower_tag, column_major_tag, dense_proxy_tag) {
  1889. typedef typename E2::size_type size_type;
  1890. typedef typename E2::value_type value_type;
  1891. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1892. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1893. size_type size = e2 ().size ();
  1894. for (size_type n = 0; n < size; ++ n) {
  1895. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1896. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1897. #else
  1898. if (e1 () (n, n) == value_type/*zero*/())
  1899. singular ().raise ();
  1900. #endif
  1901. value_type t = e2 () (n) /= e1 () (n, n);
  1902. if (t != value_type/*zero*/()) {
  1903. for (size_type m = n + 1; m < size; ++ m)
  1904. e2 () (m) -= e1 () (m, n) * t;
  1905. }
  1906. }
  1907. }
  1908. // Packed (proxy) case
  1909. template<class E1, class E2>
  1910. BOOST_UBLAS_INLINE
  1911. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1912. lower_tag, column_major_tag, packed_proxy_tag) {
  1913. typedef typename E2::size_type size_type;
  1914. typedef typename E2::difference_type difference_type;
  1915. typedef typename E2::value_type value_type;
  1916. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1917. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1918. size_type size = e2 ().size ();
  1919. for (size_type n = 0; n < size; ++ n) {
  1920. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1921. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1922. #else
  1923. if (e1 () (n, n) == value_type/*zero*/())
  1924. singular ().raise ();
  1925. #endif
  1926. value_type t = e2 () (n) /= e1 () (n, n);
  1927. if (t != value_type/*zero*/()) {
  1928. typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
  1929. typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
  1930. difference_type m (it1e1_end - it1e1);
  1931. while (-- m >= 0)
  1932. e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
  1933. }
  1934. }
  1935. }
  1936. // Sparse (proxy) case
  1937. template<class E1, class E2>
  1938. BOOST_UBLAS_INLINE
  1939. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1940. lower_tag, column_major_tag, unknown_storage_tag) {
  1941. typedef typename E2::size_type size_type;
  1942. typedef typename E2::value_type value_type;
  1943. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1944. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1945. size_type size = e2 ().size ();
  1946. for (size_type n = 0; n < size; ++ n) {
  1947. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1948. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1949. #else
  1950. if (e1 () (n, n) == value_type/*zero*/())
  1951. singular ().raise ();
  1952. #endif
  1953. value_type t = e2 () (n) /= e1 () (n, n);
  1954. if (t != value_type/*zero*/()) {
  1955. typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
  1956. typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
  1957. while (it1e1 != it1e1_end)
  1958. e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
  1959. }
  1960. }
  1961. }
  1962. // Dense (proxy) case
  1963. template<class E1, class E2>
  1964. BOOST_UBLAS_INLINE
  1965. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1966. lower_tag, row_major_tag, dense_proxy_tag) {
  1967. typedef typename E2::size_type size_type;
  1968. typedef typename E2::value_type value_type;
  1969. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1970. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1971. size_type size = e2 ().size ();
  1972. for (size_type n = 0; n < size; ++ n) {
  1973. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1974. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1975. #else
  1976. if (e1 () (n, n) == value_type/*zero*/())
  1977. singular ().raise ();
  1978. #endif
  1979. value_type t = e2 () (n) /= e1 () (n, n);
  1980. if (t != value_type/*zero*/()) {
  1981. for (size_type m = n + 1; m < size; ++ m)
  1982. e2 () (m) -= e1 () (m, n) * t;
  1983. }
  1984. }
  1985. }
  1986. // Packed (proxy) case
  1987. template<class E1, class E2>
  1988. BOOST_UBLAS_INLINE
  1989. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  1990. lower_tag, row_major_tag, packed_proxy_tag) {
  1991. typedef typename E2::size_type size_type;
  1992. typedef typename E2::value_type value_type;
  1993. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  1994. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  1995. size_type size = e2 ().size ();
  1996. for (size_type n = 0; n < size; ++ n) {
  1997. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  1998. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  1999. #else
  2000. if (e1 () (n, n) == value_type/*zero*/())
  2001. singular ().raise ();
  2002. #endif
  2003. value_type t = e2 () (n);
  2004. typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, 0));
  2005. typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, n));
  2006. while (it2e1 != it2e1_end) {
  2007. t -= *it2e1 * e2 () (it2e1.index2());
  2008. ++ it2e1;
  2009. }
  2010. e2() (n) = t / e1 () (n, n);
  2011. }
  2012. }
  2013. // Sparse (proxy) case
  2014. template<class E1, class E2>
  2015. BOOST_UBLAS_INLINE
  2016. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2017. lower_tag, row_major_tag, unknown_storage_tag) {
  2018. typedef typename E2::size_type size_type;
  2019. typedef typename E2::value_type value_type;
  2020. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2021. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  2022. size_type size = e2 ().size ();
  2023. for (size_type n = 0; n < size; ++ n) {
  2024. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2025. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2026. #else
  2027. if (e1 () (n, n) == value_type/*zero*/())
  2028. singular ().raise ();
  2029. #endif
  2030. value_type t = e2 () (n);
  2031. typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, 0));
  2032. typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, n));
  2033. while (it2e1 != it2e1_end) {
  2034. t -= *it2e1 * e2 () (it2e1.index2());
  2035. ++ it2e1;
  2036. }
  2037. e2() (n) = t / e1 () (n, n);
  2038. }
  2039. }
  2040. // Redirectors :-)
  2041. template<class E1, class E2>
  2042. BOOST_UBLAS_INLINE
  2043. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2044. lower_tag, column_major_tag) {
  2045. typedef typename E1::storage_category storage_category;
  2046. inplace_solve (e1, e2,
  2047. lower_tag (), column_major_tag (), storage_category ());
  2048. }
  2049. template<class E1, class E2>
  2050. BOOST_UBLAS_INLINE
  2051. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2052. lower_tag, row_major_tag) {
  2053. typedef typename E1::storage_category storage_category;
  2054. inplace_solve (e1, e2,
  2055. lower_tag (), row_major_tag (), storage_category ());
  2056. }
  2057. // Dispatcher
  2058. template<class E1, class E2>
  2059. BOOST_UBLAS_INLINE
  2060. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2061. lower_tag) {
  2062. typedef typename E1::orientation_category orientation_category;
  2063. inplace_solve (e1, e2,
  2064. lower_tag (), orientation_category ());
  2065. }
  2066. template<class E1, class E2>
  2067. BOOST_UBLAS_INLINE
  2068. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2069. unit_lower_tag) {
  2070. typedef typename E1::orientation_category orientation_category;
  2071. inplace_solve (triangular_adaptor<const E1, unit_lower> (e1 ()), e2,
  2072. unit_lower_tag (), orientation_category ());
  2073. }
  2074. // Dense (proxy) case
  2075. template<class E1, class E2>
  2076. BOOST_UBLAS_INLINE
  2077. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2078. upper_tag, column_major_tag, dense_proxy_tag) {
  2079. typedef typename E2::size_type size_type;
  2080. typedef typename E2::difference_type difference_type;
  2081. typedef typename E2::value_type value_type;
  2082. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2083. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  2084. size_type size = e2 ().size ();
  2085. for (difference_type n = size - 1; n >= 0; -- n) {
  2086. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2087. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2088. #else
  2089. if (e1 () (n, n) == value_type/*zero*/())
  2090. singular ().raise ();
  2091. #endif
  2092. value_type t = e2 () (n) /= e1 () (n, n);
  2093. if (t != value_type/*zero*/()) {
  2094. for (difference_type m = n - 1; m >= 0; -- m)
  2095. e2 () (m) -= e1 () (m, n) * t;
  2096. }
  2097. }
  2098. }
  2099. // Packed (proxy) case
  2100. template<class E1, class E2>
  2101. BOOST_UBLAS_INLINE
  2102. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2103. upper_tag, column_major_tag, packed_proxy_tag) {
  2104. typedef typename E2::size_type size_type;
  2105. typedef typename E2::difference_type difference_type;
  2106. typedef typename E2::value_type value_type;
  2107. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2108. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  2109. size_type size = e2 ().size ();
  2110. for (difference_type n = size - 1; n >= 0; -- n) {
  2111. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2112. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2113. #else
  2114. if (e1 () (n, n) == value_type/*zero*/())
  2115. singular ().raise ();
  2116. #endif
  2117. value_type t = e2 () (n) /= e1 () (n, n);
  2118. if (t != value_type/*zero*/()) {
  2119. typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
  2120. typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
  2121. while (it1e1 != it1e1_rend) {
  2122. e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
  2123. }
  2124. }
  2125. }
  2126. }
  2127. // Sparse (proxy) case
  2128. template<class E1, class E2>
  2129. BOOST_UBLAS_INLINE
  2130. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2131. upper_tag, column_major_tag, unknown_storage_tag) {
  2132. typedef typename E2::size_type size_type;
  2133. typedef typename E2::difference_type difference_type;
  2134. typedef typename E2::value_type value_type;
  2135. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2136. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  2137. size_type size = e2 ().size ();
  2138. for (difference_type n = size - 1; n >= 0; -- n) {
  2139. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2140. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2141. #else
  2142. if (e1 () (n, n) == value_type/*zero*/())
  2143. singular ().raise ();
  2144. #endif
  2145. value_type t = e2 () (n) /= e1 () (n, n);
  2146. if (t != value_type/*zero*/()) {
  2147. typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
  2148. typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
  2149. while (it1e1 != it1e1_rend) {
  2150. e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
  2151. }
  2152. }
  2153. }
  2154. }
  2155. // Dense (proxy) case
  2156. template<class E1, class E2>
  2157. BOOST_UBLAS_INLINE
  2158. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2159. upper_tag, row_major_tag, dense_proxy_tag) {
  2160. typedef typename E2::size_type size_type;
  2161. typedef typename E2::difference_type difference_type;
  2162. typedef typename E2::value_type value_type;
  2163. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2164. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  2165. size_type size = e1 ().size1 ();
  2166. for (difference_type n = size-1; n >=0; -- n) {
  2167. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2168. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2169. #else
  2170. if (e1 () (n, n) == value_type/*zero*/())
  2171. singular ().raise ();
  2172. #endif
  2173. value_type t = e2 () (n);
  2174. for (difference_type m = n + 1; m < static_cast<difference_type>(e1 ().size2()); ++ m) {
  2175. t -= e1 () (n, m) * e2 () (m);
  2176. }
  2177. e2() (n) = t / e1 () (n, n);
  2178. }
  2179. }
  2180. // Packed (proxy) case
  2181. template<class E1, class E2>
  2182. BOOST_UBLAS_INLINE
  2183. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2184. upper_tag, row_major_tag, packed_proxy_tag) {
  2185. typedef typename E2::size_type size_type;
  2186. typedef typename E2::difference_type difference_type;
  2187. typedef typename E2::value_type value_type;
  2188. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2189. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  2190. size_type size = e1 ().size1 ();
  2191. for (difference_type n = size-1; n >=0; -- n) {
  2192. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2193. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2194. #else
  2195. if (e1 () (n, n) == value_type/*zero*/())
  2196. singular ().raise ();
  2197. #endif
  2198. value_type t = e2 () (n);
  2199. typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, n+1));
  2200. typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, e1 ().size2 ()));
  2201. while (it2e1 != it2e1_end) {
  2202. t -= *it2e1 * e2 () (it2e1.index2());
  2203. ++ it2e1;
  2204. }
  2205. e2() (n) = t / e1 () (n, n);
  2206. }
  2207. }
  2208. // Sparse (proxy) case
  2209. template<class E1, class E2>
  2210. BOOST_UBLAS_INLINE
  2211. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2212. upper_tag, row_major_tag, unknown_storage_tag) {
  2213. typedef typename E2::size_type size_type;
  2214. typedef typename E2::difference_type difference_type;
  2215. typedef typename E2::value_type value_type;
  2216. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2217. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
  2218. size_type size = e1 ().size1 ();
  2219. for (difference_type n = size-1; n >=0; -- n) {
  2220. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2221. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2222. #else
  2223. if (e1 () (n, n) == value_type/*zero*/())
  2224. singular ().raise ();
  2225. #endif
  2226. value_type t = e2 () (n);
  2227. typename E1::const_iterator2 it2e1 (e1 ().find2 (1, n, n+1));
  2228. typename E1::const_iterator2 it2e1_end (e1 ().find2 (1, n, e1 ().size2 ()));
  2229. while (it2e1 != it2e1_end) {
  2230. t -= *it2e1 * e2 () (it2e1.index2());
  2231. ++ it2e1;
  2232. }
  2233. e2() (n) = t / e1 () (n, n);
  2234. }
  2235. }
  2236. // Redirectors :-)
  2237. template<class E1, class E2>
  2238. BOOST_UBLAS_INLINE
  2239. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2240. upper_tag, column_major_tag) {
  2241. typedef typename E1::storage_category storage_category;
  2242. inplace_solve (e1, e2,
  2243. upper_tag (), column_major_tag (), storage_category ());
  2244. }
  2245. template<class E1, class E2>
  2246. BOOST_UBLAS_INLINE
  2247. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2248. upper_tag, row_major_tag) {
  2249. typedef typename E1::storage_category storage_category;
  2250. inplace_solve (e1, e2,
  2251. upper_tag (), row_major_tag (), storage_category ());
  2252. }
  2253. // Dispatcher
  2254. template<class E1, class E2>
  2255. BOOST_UBLAS_INLINE
  2256. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2257. upper_tag) {
  2258. typedef typename E1::orientation_category orientation_category;
  2259. inplace_solve (e1, e2,
  2260. upper_tag (), orientation_category ());
  2261. }
  2262. template<class E1, class E2>
  2263. BOOST_UBLAS_INLINE
  2264. void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
  2265. unit_upper_tag) {
  2266. typedef typename E1::orientation_category orientation_category;
  2267. inplace_solve (triangular_adaptor<const E1, unit_upper> (e1 ()), e2,
  2268. unit_upper_tag (), orientation_category ());
  2269. }
  2270. template<class E1, class E2, class C>
  2271. BOOST_UBLAS_INLINE
  2272. typename matrix_vector_solve_traits<E1, E2>::result_type
  2273. solve (const matrix_expression<E1> &e1,
  2274. const vector_expression<E2> &e2,
  2275. C) {
  2276. typename matrix_vector_solve_traits<E1, E2>::result_type r (e2);
  2277. inplace_solve (e1, r, C ());
  2278. return r;
  2279. }
  2280. // Redirectors :-)
  2281. template<class E1, class E2>
  2282. BOOST_UBLAS_INLINE
  2283. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2284. lower_tag, row_major_tag) {
  2285. typedef typename E2::storage_category storage_category;
  2286. inplace_solve (trans(e2), e1,
  2287. upper_tag (), column_major_tag (), storage_category ());
  2288. }
  2289. template<class E1, class E2>
  2290. BOOST_UBLAS_INLINE
  2291. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2292. lower_tag, column_major_tag) {
  2293. typedef typename E2::storage_category storage_category;
  2294. inplace_solve (trans (e2), e1,
  2295. upper_tag (), row_major_tag (), storage_category ());
  2296. }
  2297. // Dispatcher
  2298. template<class E1, class E2>
  2299. BOOST_UBLAS_INLINE
  2300. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2301. lower_tag) {
  2302. typedef typename E2::orientation_category orientation_category;
  2303. inplace_solve (e1, e2,
  2304. lower_tag (), orientation_category ());
  2305. }
  2306. template<class E1, class E2>
  2307. BOOST_UBLAS_INLINE
  2308. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2309. unit_lower_tag) {
  2310. typedef typename E2::orientation_category orientation_category;
  2311. inplace_solve (e1, triangular_adaptor<const E2, unit_lower> (e2 ()),
  2312. unit_lower_tag (), orientation_category ());
  2313. }
  2314. // Redirectors :-)
  2315. template<class E1, class E2>
  2316. BOOST_UBLAS_INLINE
  2317. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2318. upper_tag, row_major_tag) {
  2319. typedef typename E2::storage_category storage_category;
  2320. inplace_solve (trans(e2), e1,
  2321. lower_tag (), column_major_tag (), storage_category ());
  2322. }
  2323. template<class E1, class E2>
  2324. BOOST_UBLAS_INLINE
  2325. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2326. upper_tag, column_major_tag) {
  2327. typedef typename E2::storage_category storage_category;
  2328. inplace_solve (trans (e2), e1,
  2329. lower_tag (), row_major_tag (), storage_category ());
  2330. }
  2331. // Dispatcher
  2332. template<class E1, class E2>
  2333. BOOST_UBLAS_INLINE
  2334. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2335. upper_tag) {
  2336. typedef typename E2::orientation_category orientation_category;
  2337. inplace_solve (e1, e2,
  2338. upper_tag (), orientation_category ());
  2339. }
  2340. template<class E1, class E2>
  2341. BOOST_UBLAS_INLINE
  2342. void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
  2343. unit_upper_tag) {
  2344. typedef typename E2::orientation_category orientation_category;
  2345. inplace_solve (e1, triangular_adaptor<const E2, unit_upper> (e2 ()),
  2346. unit_upper_tag (), orientation_category ());
  2347. }
  2348. template<class E1, class E2, class C>
  2349. BOOST_UBLAS_INLINE
  2350. typename matrix_vector_solve_traits<E1, E2>::result_type
  2351. solve (const vector_expression<E1> &e1,
  2352. const matrix_expression<E2> &e2,
  2353. C) {
  2354. typename matrix_vector_solve_traits<E1, E2>::result_type r (e1);
  2355. inplace_solve (r, e2, C ());
  2356. return r;
  2357. }
  2358. template<class E1, class E2>
  2359. struct matrix_matrix_solve_traits {
  2360. typedef typename promote_traits<typename E1::value_type, typename E2::value_type>::promote_type promote_type;
  2361. typedef matrix<promote_type> result_type;
  2362. };
  2363. // Operations:
  2364. // k * n * (n - 1) / 2 + k * n = k * n * (n + 1) / 2 multiplications,
  2365. // k * n * (n - 1) / 2 additions
  2366. // Dense (proxy) case
  2367. template<class E1, class E2>
  2368. BOOST_UBLAS_INLINE
  2369. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2370. lower_tag, dense_proxy_tag) {
  2371. typedef typename E2::size_type size_type;
  2372. typedef typename E2::value_type value_type;
  2373. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2374. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2375. size_type size1 = e2 ().size1 ();
  2376. size_type size2 = e2 ().size2 ();
  2377. for (size_type n = 0; n < size1; ++ n) {
  2378. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2379. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2380. #else
  2381. if (e1 () (n, n) == value_type/*zero*/())
  2382. singular ().raise ();
  2383. #endif
  2384. for (size_type l = 0; l < size2; ++ l) {
  2385. value_type t = e2 () (n, l) /= e1 () (n, n);
  2386. if (t != value_type/*zero*/()) {
  2387. for (size_type m = n + 1; m < size1; ++ m)
  2388. e2 () (m, l) -= e1 () (m, n) * t;
  2389. }
  2390. }
  2391. }
  2392. }
  2393. // Packed (proxy) case
  2394. template<class E1, class E2>
  2395. BOOST_UBLAS_INLINE
  2396. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2397. lower_tag, packed_proxy_tag) {
  2398. typedef typename E2::size_type size_type;
  2399. typedef typename E2::difference_type difference_type;
  2400. typedef typename E2::value_type value_type;
  2401. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2402. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2403. size_type size1 = e2 ().size1 ();
  2404. size_type size2 = e2 ().size2 ();
  2405. for (size_type n = 0; n < size1; ++ n) {
  2406. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2407. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2408. #else
  2409. if (e1 () (n, n) == value_type/*zero*/())
  2410. singular ().raise ();
  2411. #endif
  2412. for (size_type l = 0; l < size2; ++ l) {
  2413. value_type t = e2 () (n, l) /= e1 () (n, n);
  2414. if (t != value_type/*zero*/()) {
  2415. typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
  2416. typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
  2417. difference_type m (it1e1_end - it1e1);
  2418. while (-- m >= 0)
  2419. e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
  2420. }
  2421. }
  2422. }
  2423. }
  2424. // Sparse (proxy) case
  2425. template<class E1, class E2>
  2426. BOOST_UBLAS_INLINE
  2427. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2428. lower_tag, unknown_storage_tag) {
  2429. typedef typename E2::size_type size_type;
  2430. typedef typename E2::value_type value_type;
  2431. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2432. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2433. size_type size1 = e2 ().size1 ();
  2434. size_type size2 = e2 ().size2 ();
  2435. for (size_type n = 0; n < size1; ++ n) {
  2436. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2437. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2438. #else
  2439. if (e1 () (n, n) == value_type/*zero*/())
  2440. singular ().raise ();
  2441. #endif
  2442. for (size_type l = 0; l < size2; ++ l) {
  2443. value_type t = e2 () (n, l) /= e1 () (n, n);
  2444. if (t != value_type/*zero*/()) {
  2445. typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
  2446. typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
  2447. while (it1e1 != it1e1_end)
  2448. e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
  2449. }
  2450. }
  2451. }
  2452. }
  2453. // Dispatcher
  2454. template<class E1, class E2>
  2455. BOOST_UBLAS_INLINE
  2456. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2457. lower_tag) {
  2458. typedef typename E1::storage_category dispatch_category;
  2459. inplace_solve (e1, e2,
  2460. lower_tag (), dispatch_category ());
  2461. }
  2462. template<class E1, class E2>
  2463. BOOST_UBLAS_INLINE
  2464. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2465. unit_lower_tag) {
  2466. typedef typename E1::storage_category dispatch_category;
  2467. inplace_solve (triangular_adaptor<const E1, unit_lower> (e1 ()), e2,
  2468. unit_lower_tag (), dispatch_category ());
  2469. }
  2470. // Dense (proxy) case
  2471. template<class E1, class E2>
  2472. BOOST_UBLAS_INLINE
  2473. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2474. upper_tag, dense_proxy_tag) {
  2475. typedef typename E2::size_type size_type;
  2476. typedef typename E2::difference_type difference_type;
  2477. typedef typename E2::value_type value_type;
  2478. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2479. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2480. size_type size1 = e2 ().size1 ();
  2481. size_type size2 = e2 ().size2 ();
  2482. for (difference_type n = size1 - 1; n >= 0; -- n) {
  2483. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2484. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2485. #else
  2486. if (e1 () (n, n) == value_type/*zero*/())
  2487. singular ().raise ();
  2488. #endif
  2489. for (difference_type l = size2 - 1; l >= 0; -- l) {
  2490. value_type t = e2 () (n, l) /= e1 () (n, n);
  2491. if (t != value_type/*zero*/()) {
  2492. for (difference_type m = n - 1; m >= 0; -- m)
  2493. e2 () (m, l) -= e1 () (m, n) * t;
  2494. }
  2495. }
  2496. }
  2497. }
  2498. // Packed (proxy) case
  2499. template<class E1, class E2>
  2500. BOOST_UBLAS_INLINE
  2501. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2502. upper_tag, packed_proxy_tag) {
  2503. typedef typename E2::size_type size_type;
  2504. typedef typename E2::difference_type difference_type;
  2505. typedef typename E2::value_type value_type;
  2506. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2507. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2508. size_type size1 = e2 ().size1 ();
  2509. size_type size2 = e2 ().size2 ();
  2510. for (difference_type n = size1 - 1; n >= 0; -- n) {
  2511. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2512. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2513. #else
  2514. if (e1 () (n, n) == value_type/*zero*/())
  2515. singular ().raise ();
  2516. #endif
  2517. for (difference_type l = size2 - 1; l >= 0; -- l) {
  2518. value_type t = e2 () (n, l) /= e1 () (n, n);
  2519. if (t != value_type/*zero*/()) {
  2520. typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
  2521. typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
  2522. difference_type m (it1e1_rend - it1e1);
  2523. while (-- m >= 0)
  2524. e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
  2525. }
  2526. }
  2527. }
  2528. }
  2529. // Sparse (proxy) case
  2530. template<class E1, class E2>
  2531. BOOST_UBLAS_INLINE
  2532. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2533. upper_tag, unknown_storage_tag) {
  2534. typedef typename E2::size_type size_type;
  2535. typedef typename E2::difference_type difference_type;
  2536. typedef typename E2::value_type value_type;
  2537. BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
  2538. BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
  2539. size_type size1 = e2 ().size1 ();
  2540. size_type size2 = e2 ().size2 ();
  2541. for (difference_type n = size1 - 1; n >= 0; -- n) {
  2542. #ifndef BOOST_UBLAS_SINGULAR_CHECK
  2543. BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
  2544. #else
  2545. if (e1 () (n, n) == value_type/*zero*/())
  2546. singular ().raise ();
  2547. #endif
  2548. for (difference_type l = size2 - 1; l >= 0; -- l) {
  2549. value_type t = e2 () (n, l) /= e1 () (n, n);
  2550. if (t != value_type/*zero*/()) {
  2551. typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
  2552. typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
  2553. while (it1e1 != it1e1_rend)
  2554. e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
  2555. }
  2556. }
  2557. }
  2558. }
  2559. // Dispatcher
  2560. template<class E1, class E2>
  2561. BOOST_UBLAS_INLINE
  2562. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2563. upper_tag) {
  2564. typedef typename E1::storage_category dispatch_category;
  2565. inplace_solve (e1, e2,
  2566. upper_tag (), dispatch_category ());
  2567. }
  2568. template<class E1, class E2>
  2569. BOOST_UBLAS_INLINE
  2570. void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
  2571. unit_upper_tag) {
  2572. typedef typename E1::storage_category dispatch_category;
  2573. inplace_solve (triangular_adaptor<const E1, unit_upper> (e1 ()), e2,
  2574. unit_upper_tag (), dispatch_category ());
  2575. }
  2576. template<class E1, class E2, class C>
  2577. BOOST_UBLAS_INLINE
  2578. typename matrix_matrix_solve_traits<E1, E2>::result_type
  2579. solve (const matrix_expression<E1> &e1,
  2580. const matrix_expression<E2> &e2,
  2581. C) {
  2582. typename matrix_matrix_solve_traits<E1, E2>::result_type r (e2);
  2583. inplace_solve (e1, r, C ());
  2584. return r;
  2585. }
  2586. }}}
  2587. #endif