matrix_sparse.hpp 216 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421
  1. //
  2. // Copyright (c) 2000-2007
  3. // Joerg Walter, Mathias Koch, Gunter Winkler
  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_MATRIX_SPARSE_
  13. #define _BOOST_UBLAS_MATRIX_SPARSE_
  14. #include <boost/numeric/ublas/vector_sparse.hpp>
  15. #include <boost/numeric/ublas/matrix_expression.hpp>
  16. #include <boost/numeric/ublas/detail/matrix_assign.hpp>
  17. #if BOOST_UBLAS_TYPE_CHECK
  18. #include <boost/numeric/ublas/matrix.hpp>
  19. #endif
  20. // Iterators based on ideas of Jeremy Siek
  21. namespace boost { namespace numeric { namespace ublas {
  22. #ifdef BOOST_UBLAS_STRICT_MATRIX_SPARSE
  23. template<class M>
  24. class sparse_matrix_element:
  25. public container_reference<M> {
  26. public:
  27. typedef M matrix_type;
  28. typedef typename M::size_type size_type;
  29. typedef typename M::value_type value_type;
  30. typedef const value_type &const_reference;
  31. typedef value_type *pointer;
  32. typedef const value_type *const_pointer;
  33. private:
  34. // Proxied element operations
  35. void get_d () const {
  36. const_pointer p = (*this) ().find_element (i_, j_);
  37. if (p)
  38. d_ = *p;
  39. else
  40. d_ = value_type/*zero*/();
  41. }
  42. void set (const value_type &s) const {
  43. pointer p = (*this) ().find_element (i_, j_);
  44. if (!p)
  45. (*this) ().insert_element (i_, j_, s);
  46. else
  47. *p = s;
  48. }
  49. public:
  50. // Construction and destruction
  51. BOOST_UBLAS_INLINE
  52. sparse_matrix_element (matrix_type &m, size_type i, size_type j):
  53. container_reference<matrix_type> (m), i_ (i), j_ (j) {
  54. }
  55. BOOST_UBLAS_INLINE
  56. sparse_matrix_element (const sparse_matrix_element &p):
  57. container_reference<matrix_type> (p), i_ (p.i_), j_ (p.j_) {}
  58. BOOST_UBLAS_INLINE
  59. ~sparse_matrix_element () {
  60. }
  61. // Assignment
  62. BOOST_UBLAS_INLINE
  63. sparse_matrix_element &operator = (const sparse_matrix_element &p) {
  64. // Overide the implict copy assignment
  65. p.get_d ();
  66. set (p.d_);
  67. return *this;
  68. }
  69. template<class D>
  70. BOOST_UBLAS_INLINE
  71. sparse_matrix_element &operator = (const D &d) {
  72. set (d);
  73. return *this;
  74. }
  75. template<class D>
  76. BOOST_UBLAS_INLINE
  77. sparse_matrix_element &operator += (const D &d) {
  78. get_d ();
  79. d_ += d;
  80. set (d_);
  81. return *this;
  82. }
  83. template<class D>
  84. BOOST_UBLAS_INLINE
  85. sparse_matrix_element &operator -= (const D &d) {
  86. get_d ();
  87. d_ -= d;
  88. set (d_);
  89. return *this;
  90. }
  91. template<class D>
  92. BOOST_UBLAS_INLINE
  93. sparse_matrix_element &operator *= (const D &d) {
  94. get_d ();
  95. d_ *= d;
  96. set (d_);
  97. return *this;
  98. }
  99. template<class D>
  100. BOOST_UBLAS_INLINE
  101. sparse_matrix_element &operator /= (const D &d) {
  102. get_d ();
  103. d_ /= d;
  104. set (d_);
  105. return *this;
  106. }
  107. // Comparison
  108. template<class D>
  109. BOOST_UBLAS_INLINE
  110. bool operator == (const D &d) const {
  111. get_d ();
  112. return d_ == d;
  113. }
  114. template<class D>
  115. BOOST_UBLAS_INLINE
  116. bool operator != (const D &d) const {
  117. get_d ();
  118. return d_ != d;
  119. }
  120. // Conversion - weak link in proxy as d_ is not a perfect alias for the element
  121. BOOST_UBLAS_INLINE
  122. operator const_reference () const {
  123. get_d ();
  124. return d_;
  125. }
  126. // Conversion to reference - may be invalidated
  127. BOOST_UBLAS_INLINE
  128. value_type& ref () const {
  129. const pointer p = (*this) ().find_element (i_, j_);
  130. if (!p)
  131. return (*this) ().insert_element (i_, j_, value_type/*zero*/());
  132. else
  133. return *p;
  134. }
  135. private:
  136. size_type i_;
  137. size_type j_;
  138. mutable value_type d_;
  139. };
  140. /*
  141. * Generalise explicit reference access
  142. */
  143. namespace detail {
  144. template <class V>
  145. struct element_reference<sparse_matrix_element<V> > {
  146. typedef typename V::value_type& reference;
  147. static reference get_reference (const sparse_matrix_element<V>& sve)
  148. {
  149. return sve.ref ();
  150. }
  151. };
  152. }
  153. template<class M>
  154. struct type_traits<sparse_matrix_element<M> > {
  155. typedef typename M::value_type element_type;
  156. typedef type_traits<sparse_matrix_element<M> > self_type;
  157. typedef typename type_traits<element_type>::value_type value_type;
  158. typedef typename type_traits<element_type>::const_reference const_reference;
  159. typedef sparse_matrix_element<M> reference;
  160. typedef typename type_traits<element_type>::real_type real_type;
  161. typedef typename type_traits<element_type>::precision_type precision_type;
  162. static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
  163. static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
  164. static
  165. BOOST_UBLAS_INLINE
  166. real_type real (const_reference t) {
  167. return type_traits<element_type>::real (t);
  168. }
  169. static
  170. BOOST_UBLAS_INLINE
  171. real_type imag (const_reference t) {
  172. return type_traits<element_type>::imag (t);
  173. }
  174. static
  175. BOOST_UBLAS_INLINE
  176. value_type conj (const_reference t) {
  177. return type_traits<element_type>::conj (t);
  178. }
  179. static
  180. BOOST_UBLAS_INLINE
  181. real_type type_abs (const_reference t) {
  182. return type_traits<element_type>::type_abs (t);
  183. }
  184. static
  185. BOOST_UBLAS_INLINE
  186. value_type type_sqrt (const_reference t) {
  187. return type_traits<element_type>::type_sqrt (t);
  188. }
  189. static
  190. BOOST_UBLAS_INLINE
  191. real_type norm_1 (const_reference t) {
  192. return type_traits<element_type>::norm_1 (t);
  193. }
  194. static
  195. BOOST_UBLAS_INLINE
  196. real_type norm_2 (const_reference t) {
  197. return type_traits<element_type>::norm_2 (t);
  198. }
  199. static
  200. BOOST_UBLAS_INLINE
  201. real_type norm_inf (const_reference t) {
  202. return type_traits<element_type>::norm_inf (t);
  203. }
  204. static
  205. BOOST_UBLAS_INLINE
  206. bool equals (const_reference t1, const_reference t2) {
  207. return type_traits<element_type>::equals (t1, t2);
  208. }
  209. };
  210. template<class M1, class T2>
  211. struct promote_traits<sparse_matrix_element<M1>, T2> {
  212. typedef typename promote_traits<typename sparse_matrix_element<M1>::value_type, T2>::promote_type promote_type;
  213. };
  214. template<class T1, class M2>
  215. struct promote_traits<T1, sparse_matrix_element<M2> > {
  216. typedef typename promote_traits<T1, typename sparse_matrix_element<M2>::value_type>::promote_type promote_type;
  217. };
  218. template<class M1, class M2>
  219. struct promote_traits<sparse_matrix_element<M1>, sparse_matrix_element<M2> > {
  220. typedef typename promote_traits<typename sparse_matrix_element<M1>::value_type,
  221. typename sparse_matrix_element<M2>::value_type>::promote_type promote_type;
  222. };
  223. #endif
  224. /** \brief Index map based sparse matrix of values of type \c T
  225. *
  226. * This class represents a matrix by using a \c key to value mapping. The default type is
  227. * \code template<class T, class L = row_major, class A = map_std<std::size_t, T> > class mapped_matrix; \endcode
  228. * So, by default a STL map container is used to associate keys and values. The key is computed depending on
  229. * the layout type \c L as \code key = layout_type::element(i, size1_, j, size2_); \endcode
  230. * which means \code key = (i*size2+j) \endcode for a row major matrix.
  231. * Limitations: The matrix size must not exceed \f$(size1*size2) < \f$ \code std::limits<std::size_t> \endcode.
  232. * The \ref find1() and \ref find2() operations have a complexity of at least \f$\mathcal{O}(log(nnz))\f$, depending
  233. * on the efficiency of \c std::lower_bound on the key set of the map.
  234. * Orientation and storage can also be specified, otherwise a row major orientation is used.
  235. * It is \b not required by the storage to initialize elements of the matrix. By default, the orientation is \c row_major.
  236. *
  237. * \sa fwd.hpp, storage_sparse.hpp
  238. *
  239. * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
  240. * \tparam L the storage organization. It can be either \c row_major or \c column_major. By default it is \c row_major
  241. */
  242. template<class T, class L, class A>
  243. class mapped_matrix:
  244. public matrix_container<mapped_matrix<T, L, A> > {
  245. typedef T &true_reference;
  246. typedef T *pointer;
  247. typedef const T * const_pointer;
  248. typedef L layout_type;
  249. typedef mapped_matrix<T, L, A> self_type;
  250. public:
  251. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  252. using matrix_container<self_type>::operator ();
  253. #endif
  254. typedef typename A::size_type size_type;
  255. typedef typename A::difference_type difference_type;
  256. typedef T value_type;
  257. typedef A array_type;
  258. typedef const T &const_reference;
  259. #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
  260. typedef typename detail::map_traits<A, T>::reference reference;
  261. #else
  262. typedef sparse_matrix_element<self_type> reference;
  263. #endif
  264. typedef const matrix_reference<const self_type> const_closure_type;
  265. typedef matrix_reference<self_type> closure_type;
  266. typedef mapped_vector<T, A> vector_temporary_type;
  267. typedef self_type matrix_temporary_type;
  268. typedef sparse_tag storage_category;
  269. typedef typename L::orientation_category orientation_category;
  270. // Construction and destruction
  271. BOOST_UBLAS_INLINE
  272. mapped_matrix ():
  273. matrix_container<self_type> (),
  274. size1_ (0), size2_ (0), data_ () {}
  275. BOOST_UBLAS_INLINE
  276. mapped_matrix (size_type size1, size_type size2, size_type non_zeros = 0):
  277. matrix_container<self_type> (),
  278. size1_ (size1), size2_ (size2), data_ () {
  279. detail::map_reserve (data (), restrict_capacity (non_zeros));
  280. }
  281. BOOST_UBLAS_INLINE
  282. mapped_matrix (const mapped_matrix &m):
  283. matrix_container<self_type> (),
  284. size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
  285. template<class AE>
  286. BOOST_UBLAS_INLINE
  287. mapped_matrix (const matrix_expression<AE> &ae, size_type non_zeros = 0):
  288. matrix_container<self_type> (),
  289. size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () {
  290. detail::map_reserve (data (), restrict_capacity (non_zeros));
  291. matrix_assign<scalar_assign> (*this, ae);
  292. }
  293. // Accessors
  294. BOOST_UBLAS_INLINE
  295. size_type size1 () const {
  296. return size1_;
  297. }
  298. BOOST_UBLAS_INLINE
  299. size_type size2 () const {
  300. return size2_;
  301. }
  302. BOOST_UBLAS_INLINE
  303. size_type nnz_capacity () const {
  304. return detail::map_capacity (data ());
  305. }
  306. BOOST_UBLAS_INLINE
  307. size_type nnz () const {
  308. return data (). size ();
  309. }
  310. // Storage accessors
  311. BOOST_UBLAS_INLINE
  312. const array_type &data () const {
  313. return data_;
  314. }
  315. BOOST_UBLAS_INLINE
  316. array_type &data () {
  317. return data_;
  318. }
  319. // Resizing
  320. private:
  321. BOOST_UBLAS_INLINE
  322. size_type restrict_capacity (size_type non_zeros) const {
  323. // Guarding against overflow - thanks to Alexei Novakov for the hint.
  324. // non_zeros = (std::min) (non_zeros, size1_ * size2_);
  325. if (size1_ > 0 && non_zeros / size1_ >= size2_)
  326. non_zeros = size1_ * size2_;
  327. return non_zeros;
  328. }
  329. public:
  330. BOOST_UBLAS_INLINE
  331. void resize (size_type size1, size_type size2, bool preserve = true) {
  332. // FIXME preserve unimplemented
  333. BOOST_UBLAS_CHECK (!preserve, internal_logic ());
  334. size1_ = size1;
  335. size2_ = size2;
  336. data ().clear ();
  337. }
  338. // Reserving
  339. BOOST_UBLAS_INLINE
  340. void reserve (size_type non_zeros, bool preserve = true) {
  341. detail::map_reserve (data (), restrict_capacity (non_zeros));
  342. }
  343. // Element support
  344. BOOST_UBLAS_INLINE
  345. pointer find_element (size_type i, size_type j) {
  346. return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
  347. }
  348. BOOST_UBLAS_INLINE
  349. const_pointer find_element (size_type i, size_type j) const {
  350. const size_type element = layout_type::element (i, size1_, j, size2_);
  351. const_subiterator_type it (data ().find (element));
  352. if (it == data ().end ())
  353. return 0;
  354. BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
  355. return &(*it).second;
  356. }
  357. // Element access
  358. BOOST_UBLAS_INLINE
  359. const_reference operator () (size_type i, size_type j) const {
  360. const size_type element = layout_type::element (i, size1_, j, size2_);
  361. const_subiterator_type it (data ().find (element));
  362. if (it == data ().end ())
  363. return zero_;
  364. BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
  365. return (*it).second;
  366. }
  367. BOOST_UBLAS_INLINE
  368. reference operator () (size_type i, size_type j) {
  369. #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
  370. const size_type element = layout_type::element (i, size1_, j, size2_);
  371. std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (element, value_type/*zero*/())));
  372. BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map
  373. return (ii.first)->second;
  374. #else
  375. return reference (*this, i, j);
  376. #endif
  377. }
  378. // Element assingment
  379. BOOST_UBLAS_INLINE
  380. true_reference insert_element (size_type i, size_type j, const_reference t) {
  381. BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
  382. const size_type element = layout_type::element (i, size1_, j, size2_);
  383. std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (element, t)));
  384. BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map
  385. if (!ii.second) // existing element
  386. (ii.first)->second = t;
  387. return (ii.first)->second;
  388. }
  389. BOOST_UBLAS_INLINE
  390. void erase_element (size_type i, size_type j) {
  391. subiterator_type it = data ().find (layout_type::element (i, size1_, j, size2_));
  392. if (it == data ().end ())
  393. return;
  394. data ().erase (it);
  395. }
  396. // Zeroing
  397. BOOST_UBLAS_INLINE
  398. void clear () {
  399. data ().clear ();
  400. }
  401. // Assignment
  402. BOOST_UBLAS_INLINE
  403. mapped_matrix &operator = (const mapped_matrix &m) {
  404. if (this != &m) {
  405. size1_ = m.size1_;
  406. size2_ = m.size2_;
  407. data () = m.data ();
  408. }
  409. return *this;
  410. }
  411. template<class C> // Container assignment without temporary
  412. BOOST_UBLAS_INLINE
  413. mapped_matrix &operator = (const matrix_container<C> &m) {
  414. resize (m ().size1 (), m ().size2 (), false);
  415. assign (m);
  416. return *this;
  417. }
  418. BOOST_UBLAS_INLINE
  419. mapped_matrix &assign_temporary (mapped_matrix &m) {
  420. swap (m);
  421. return *this;
  422. }
  423. template<class AE>
  424. BOOST_UBLAS_INLINE
  425. mapped_matrix &operator = (const matrix_expression<AE> &ae) {
  426. self_type temporary (ae, detail::map_capacity (data ()));
  427. return assign_temporary (temporary);
  428. }
  429. template<class AE>
  430. BOOST_UBLAS_INLINE
  431. mapped_matrix &assign (const matrix_expression<AE> &ae) {
  432. matrix_assign<scalar_assign> (*this, ae);
  433. return *this;
  434. }
  435. template<class AE>
  436. BOOST_UBLAS_INLINE
  437. mapped_matrix& operator += (const matrix_expression<AE> &ae) {
  438. self_type temporary (*this + ae, detail::map_capacity (data ()));
  439. return assign_temporary (temporary);
  440. }
  441. template<class C> // Container assignment without temporary
  442. BOOST_UBLAS_INLINE
  443. mapped_matrix &operator += (const matrix_container<C> &m) {
  444. plus_assign (m);
  445. return *this;
  446. }
  447. template<class AE>
  448. BOOST_UBLAS_INLINE
  449. mapped_matrix &plus_assign (const matrix_expression<AE> &ae) {
  450. matrix_assign<scalar_plus_assign> (*this, ae);
  451. return *this;
  452. }
  453. template<class AE>
  454. BOOST_UBLAS_INLINE
  455. mapped_matrix& operator -= (const matrix_expression<AE> &ae) {
  456. self_type temporary (*this - ae, detail::map_capacity (data ()));
  457. return assign_temporary (temporary);
  458. }
  459. template<class C> // Container assignment without temporary
  460. BOOST_UBLAS_INLINE
  461. mapped_matrix &operator -= (const matrix_container<C> &m) {
  462. minus_assign (m);
  463. return *this;
  464. }
  465. template<class AE>
  466. BOOST_UBLAS_INLINE
  467. mapped_matrix &minus_assign (const matrix_expression<AE> &ae) {
  468. matrix_assign<scalar_minus_assign> (*this, ae);
  469. return *this;
  470. }
  471. template<class AT>
  472. BOOST_UBLAS_INLINE
  473. mapped_matrix& operator *= (const AT &at) {
  474. matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  475. return *this;
  476. }
  477. template<class AT>
  478. BOOST_UBLAS_INLINE
  479. mapped_matrix& operator /= (const AT &at) {
  480. matrix_assign_scalar<scalar_divides_assign> (*this, at);
  481. return *this;
  482. }
  483. // Swapping
  484. BOOST_UBLAS_INLINE
  485. void swap (mapped_matrix &m) {
  486. if (this != &m) {
  487. std::swap (size1_, m.size1_);
  488. std::swap (size2_, m.size2_);
  489. data ().swap (m.data ());
  490. }
  491. }
  492. BOOST_UBLAS_INLINE
  493. friend void swap (mapped_matrix &m1, mapped_matrix &m2) {
  494. m1.swap (m2);
  495. }
  496. // Iterator types
  497. private:
  498. // Use storage iterator
  499. typedef typename A::const_iterator const_subiterator_type;
  500. typedef typename A::iterator subiterator_type;
  501. BOOST_UBLAS_INLINE
  502. true_reference at_element (size_type i, size_type j) {
  503. const size_type element = layout_type::element (i, size1_, j, size2_);
  504. subiterator_type it (data ().find (element));
  505. BOOST_UBLAS_CHECK (it != data ().end(), bad_index ());
  506. BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
  507. return it->second;
  508. }
  509. public:
  510. class const_iterator1;
  511. class iterator1;
  512. class const_iterator2;
  513. class iterator2;
  514. typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  515. typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  516. typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  517. typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  518. // Element lookup
  519. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  520. const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
  521. const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
  522. const_subiterator_type it_end (data ().end ());
  523. size_type index1 = size_type (-1);
  524. size_type index2 = size_type (-1);
  525. while (rank == 1 && it != it_end) {
  526. index1 = layout_type::index_i ((*it).first, size1_, size2_);
  527. index2 = layout_type::index_j ((*it).first, size1_, size2_);
  528. if (direction > 0) {
  529. if ((index1 >= i && index2 == j) || (i >= size1_))
  530. break;
  531. ++ i;
  532. } else /* if (direction < 0) */ {
  533. if ((index1 <= i && index2 == j) || (i == 0))
  534. break;
  535. -- i;
  536. }
  537. it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
  538. }
  539. if (rank == 1 && index2 != j) {
  540. if (direction > 0)
  541. i = size1_;
  542. else /* if (direction < 0) */
  543. i = 0;
  544. rank = 0;
  545. }
  546. return const_iterator1 (*this, rank, i, j, it);
  547. }
  548. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  549. iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
  550. subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
  551. subiterator_type it_end (data ().end ());
  552. size_type index1 = size_type (-1);
  553. size_type index2 = size_type (-1);
  554. while (rank == 1 && it != it_end) {
  555. index1 = layout_type::index_i ((*it).first, size1_, size2_);
  556. index2 = layout_type::index_j ((*it).first, size1_, size2_);
  557. if (direction > 0) {
  558. if ((index1 >= i && index2 == j) || (i >= size1_))
  559. break;
  560. ++ i;
  561. } else /* if (direction < 0) */ {
  562. if ((index1 <= i && index2 == j) || (i == 0))
  563. break;
  564. -- i;
  565. }
  566. it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
  567. }
  568. if (rank == 1 && index2 != j) {
  569. if (direction > 0)
  570. i = size1_;
  571. else /* if (direction < 0) */
  572. i = 0;
  573. rank = 0;
  574. }
  575. return iterator1 (*this, rank, i, j, it);
  576. }
  577. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  578. const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
  579. const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
  580. const_subiterator_type it_end (data ().end ());
  581. size_type index1 = size_type (-1);
  582. size_type index2 = size_type (-1);
  583. while (rank == 1 && it != it_end) {
  584. index1 = layout_type::index_i ((*it).first, size1_, size2_);
  585. index2 = layout_type::index_j ((*it).first, size1_, size2_);
  586. if (direction > 0) {
  587. if ((index2 >= j && index1 == i) || (j >= size2_))
  588. break;
  589. ++ j;
  590. } else /* if (direction < 0) */ {
  591. if ((index2 <= j && index1 == i) || (j == 0))
  592. break;
  593. -- j;
  594. }
  595. it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
  596. }
  597. if (rank == 1 && index1 != i) {
  598. if (direction > 0)
  599. j = size2_;
  600. else /* if (direction < 0) */
  601. j = 0;
  602. rank = 0;
  603. }
  604. return const_iterator2 (*this, rank, i, j, it);
  605. }
  606. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  607. iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
  608. subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
  609. subiterator_type it_end (data ().end ());
  610. size_type index1 = size_type (-1);
  611. size_type index2 = size_type (-1);
  612. while (rank == 1 && it != it_end) {
  613. index1 = layout_type::index_i ((*it).first, size1_, size2_);
  614. index2 = layout_type::index_j ((*it).first, size1_, size2_);
  615. if (direction > 0) {
  616. if ((index2 >= j && index1 == i) || (j >= size2_))
  617. break;
  618. ++ j;
  619. } else /* if (direction < 0) */ {
  620. if ((index2 <= j && index1 == i) || (j == 0))
  621. break;
  622. -- j;
  623. }
  624. it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
  625. }
  626. if (rank == 1 && index1 != i) {
  627. if (direction > 0)
  628. j = size2_;
  629. else /* if (direction < 0) */
  630. j = 0;
  631. rank = 0;
  632. }
  633. return iterator2 (*this, rank, i, j, it);
  634. }
  635. class const_iterator1:
  636. public container_const_reference<mapped_matrix>,
  637. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  638. const_iterator1, value_type> {
  639. public:
  640. typedef typename mapped_matrix::value_type value_type;
  641. typedef typename mapped_matrix::difference_type difference_type;
  642. typedef typename mapped_matrix::const_reference reference;
  643. typedef const typename mapped_matrix::pointer pointer;
  644. typedef const_iterator2 dual_iterator_type;
  645. typedef const_reverse_iterator2 dual_reverse_iterator_type;
  646. // Construction and destruction
  647. BOOST_UBLAS_INLINE
  648. const_iterator1 ():
  649. container_const_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
  650. BOOST_UBLAS_INLINE
  651. const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it):
  652. container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
  653. BOOST_UBLAS_INLINE
  654. const_iterator1 (const iterator1 &it):
  655. container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
  656. // Arithmetic
  657. BOOST_UBLAS_INLINE
  658. const_iterator1 &operator ++ () {
  659. if (rank_ == 1 && layout_type::fast_i ())
  660. ++ it_;
  661. else
  662. *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1);
  663. return *this;
  664. }
  665. BOOST_UBLAS_INLINE
  666. const_iterator1 &operator -- () {
  667. if (rank_ == 1 && layout_type::fast_i ())
  668. -- it_;
  669. else
  670. *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1);
  671. return *this;
  672. }
  673. // Dereference
  674. BOOST_UBLAS_INLINE
  675. const_reference operator * () const {
  676. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  677. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  678. if (rank_ == 1) {
  679. return (*it_).second;
  680. } else {
  681. return (*this) () (i_, j_);
  682. }
  683. }
  684. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  685. BOOST_UBLAS_INLINE
  686. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  687. typename self_type::
  688. #endif
  689. const_iterator2 begin () const {
  690. const self_type &m = (*this) ();
  691. return m.find2 (1, index1 (), 0);
  692. }
  693. BOOST_UBLAS_INLINE
  694. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  695. typename self_type::
  696. #endif
  697. const_iterator2 end () const {
  698. const self_type &m = (*this) ();
  699. return m.find2 (1, index1 (), m.size2 ());
  700. }
  701. BOOST_UBLAS_INLINE
  702. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  703. typename self_type::
  704. #endif
  705. const_reverse_iterator2 rbegin () const {
  706. return const_reverse_iterator2 (end ());
  707. }
  708. BOOST_UBLAS_INLINE
  709. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  710. typename self_type::
  711. #endif
  712. const_reverse_iterator2 rend () const {
  713. return const_reverse_iterator2 (begin ());
  714. }
  715. #endif
  716. // Indices
  717. BOOST_UBLAS_INLINE
  718. size_type index1 () const {
  719. BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
  720. if (rank_ == 1) {
  721. const self_type &m = (*this) ();
  722. BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
  723. return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
  724. } else {
  725. return i_;
  726. }
  727. }
  728. BOOST_UBLAS_INLINE
  729. size_type index2 () const {
  730. if (rank_ == 1) {
  731. const self_type &m = (*this) ();
  732. BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
  733. return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
  734. } else {
  735. return j_;
  736. }
  737. }
  738. // Assignment
  739. BOOST_UBLAS_INLINE
  740. const_iterator1 &operator = (const const_iterator1 &it) {
  741. container_const_reference<self_type>::assign (&it ());
  742. rank_ = it.rank_;
  743. i_ = it.i_;
  744. j_ = it.j_;
  745. it_ = it.it_;
  746. return *this;
  747. }
  748. // Comparison
  749. BOOST_UBLAS_INLINE
  750. bool operator == (const const_iterator1 &it) const {
  751. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  752. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  753. if (rank_ == 1 || it.rank_ == 1) {
  754. return it_ == it.it_;
  755. } else {
  756. return i_ == it.i_ && j_ == it.j_;
  757. }
  758. }
  759. private:
  760. int rank_;
  761. size_type i_;
  762. size_type j_;
  763. const_subiterator_type it_;
  764. };
  765. BOOST_UBLAS_INLINE
  766. const_iterator1 begin1 () const {
  767. return find1 (0, 0, 0);
  768. }
  769. BOOST_UBLAS_INLINE
  770. const_iterator1 end1 () const {
  771. return find1 (0, size1_, 0);
  772. }
  773. class iterator1:
  774. public container_reference<mapped_matrix>,
  775. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  776. iterator1, value_type> {
  777. public:
  778. typedef typename mapped_matrix::value_type value_type;
  779. typedef typename mapped_matrix::difference_type difference_type;
  780. typedef typename mapped_matrix::true_reference reference;
  781. typedef typename mapped_matrix::pointer pointer;
  782. typedef iterator2 dual_iterator_type;
  783. typedef reverse_iterator2 dual_reverse_iterator_type;
  784. // Construction and destruction
  785. BOOST_UBLAS_INLINE
  786. iterator1 ():
  787. container_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
  788. BOOST_UBLAS_INLINE
  789. iterator1 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it):
  790. container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
  791. // Arithmetic
  792. BOOST_UBLAS_INLINE
  793. iterator1 &operator ++ () {
  794. if (rank_ == 1 && layout_type::fast_i ())
  795. ++ it_;
  796. else
  797. *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1);
  798. return *this;
  799. }
  800. BOOST_UBLAS_INLINE
  801. iterator1 &operator -- () {
  802. if (rank_ == 1 && layout_type::fast_i ())
  803. -- it_;
  804. else
  805. *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1);
  806. return *this;
  807. }
  808. // Dereference
  809. BOOST_UBLAS_INLINE
  810. reference operator * () const {
  811. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  812. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  813. if (rank_ == 1) {
  814. return (*it_).second;
  815. } else {
  816. return (*this) ().at_element (i_, j_);
  817. }
  818. }
  819. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  820. BOOST_UBLAS_INLINE
  821. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  822. typename self_type::
  823. #endif
  824. iterator2 begin () const {
  825. self_type &m = (*this) ();
  826. return m.find2 (1, index1 (), 0);
  827. }
  828. BOOST_UBLAS_INLINE
  829. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  830. typename self_type::
  831. #endif
  832. iterator2 end () const {
  833. self_type &m = (*this) ();
  834. return m.find2 (1, index1 (), m.size2 ());
  835. }
  836. BOOST_UBLAS_INLINE
  837. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  838. typename self_type::
  839. #endif
  840. reverse_iterator2 rbegin () const {
  841. return reverse_iterator2 (end ());
  842. }
  843. BOOST_UBLAS_INLINE
  844. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  845. typename self_type::
  846. #endif
  847. reverse_iterator2 rend () const {
  848. return reverse_iterator2 (begin ());
  849. }
  850. #endif
  851. // Indices
  852. BOOST_UBLAS_INLINE
  853. size_type index1 () const {
  854. BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
  855. if (rank_ == 1) {
  856. const self_type &m = (*this) ();
  857. BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
  858. return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
  859. } else {
  860. return i_;
  861. }
  862. }
  863. BOOST_UBLAS_INLINE
  864. size_type index2 () const {
  865. if (rank_ == 1) {
  866. const self_type &m = (*this) ();
  867. BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
  868. return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
  869. } else {
  870. return j_;
  871. }
  872. }
  873. // Assignment
  874. BOOST_UBLAS_INLINE
  875. iterator1 &operator = (const iterator1 &it) {
  876. container_reference<self_type>::assign (&it ());
  877. rank_ = it.rank_;
  878. i_ = it.i_;
  879. j_ = it.j_;
  880. it_ = it.it_;
  881. return *this;
  882. }
  883. // Comparison
  884. BOOST_UBLAS_INLINE
  885. bool operator == (const iterator1 &it) const {
  886. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  887. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  888. if (rank_ == 1 || it.rank_ == 1) {
  889. return it_ == it.it_;
  890. } else {
  891. return i_ == it.i_ && j_ == it.j_;
  892. }
  893. }
  894. private:
  895. int rank_;
  896. size_type i_;
  897. size_type j_;
  898. subiterator_type it_;
  899. friend class const_iterator1;
  900. };
  901. BOOST_UBLAS_INLINE
  902. iterator1 begin1 () {
  903. return find1 (0, 0, 0);
  904. }
  905. BOOST_UBLAS_INLINE
  906. iterator1 end1 () {
  907. return find1 (0, size1_, 0);
  908. }
  909. class const_iterator2:
  910. public container_const_reference<mapped_matrix>,
  911. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  912. const_iterator2, value_type> {
  913. public:
  914. typedef typename mapped_matrix::value_type value_type;
  915. typedef typename mapped_matrix::difference_type difference_type;
  916. typedef typename mapped_matrix::const_reference reference;
  917. typedef const typename mapped_matrix::pointer pointer;
  918. typedef const_iterator1 dual_iterator_type;
  919. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  920. // Construction and destruction
  921. BOOST_UBLAS_INLINE
  922. const_iterator2 ():
  923. container_const_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
  924. BOOST_UBLAS_INLINE
  925. const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it):
  926. container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
  927. BOOST_UBLAS_INLINE
  928. const_iterator2 (const iterator2 &it):
  929. container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
  930. // Arithmetic
  931. BOOST_UBLAS_INLINE
  932. const_iterator2 &operator ++ () {
  933. if (rank_ == 1 && layout_type::fast_j ())
  934. ++ it_;
  935. else
  936. *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1);
  937. return *this;
  938. }
  939. BOOST_UBLAS_INLINE
  940. const_iterator2 &operator -- () {
  941. if (rank_ == 1 && layout_type::fast_j ())
  942. -- it_;
  943. else
  944. *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1);
  945. return *this;
  946. }
  947. // Dereference
  948. BOOST_UBLAS_INLINE
  949. const_reference operator * () const {
  950. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  951. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  952. if (rank_ == 1) {
  953. return (*it_).second;
  954. } else {
  955. return (*this) () (i_, j_);
  956. }
  957. }
  958. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  959. BOOST_UBLAS_INLINE
  960. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  961. typename self_type::
  962. #endif
  963. const_iterator1 begin () const {
  964. const self_type &m = (*this) ();
  965. return m.find1 (1, 0, index2 ());
  966. }
  967. BOOST_UBLAS_INLINE
  968. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  969. typename self_type::
  970. #endif
  971. const_iterator1 end () const {
  972. const self_type &m = (*this) ();
  973. return m.find1 (1, m.size1 (), index2 ());
  974. }
  975. BOOST_UBLAS_INLINE
  976. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  977. typename self_type::
  978. #endif
  979. const_reverse_iterator1 rbegin () const {
  980. return const_reverse_iterator1 (end ());
  981. }
  982. BOOST_UBLAS_INLINE
  983. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  984. typename self_type::
  985. #endif
  986. const_reverse_iterator1 rend () const {
  987. return const_reverse_iterator1 (begin ());
  988. }
  989. #endif
  990. // Indices
  991. BOOST_UBLAS_INLINE
  992. size_type index1 () const {
  993. if (rank_ == 1) {
  994. const self_type &m = (*this) ();
  995. BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
  996. return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
  997. } else {
  998. return i_;
  999. }
  1000. }
  1001. BOOST_UBLAS_INLINE
  1002. size_type index2 () const {
  1003. BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
  1004. if (rank_ == 1) {
  1005. const self_type &m = (*this) ();
  1006. BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
  1007. return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
  1008. } else {
  1009. return j_;
  1010. }
  1011. }
  1012. // Assignment
  1013. BOOST_UBLAS_INLINE
  1014. const_iterator2 &operator = (const const_iterator2 &it) {
  1015. container_const_reference<self_type>::assign (&it ());
  1016. rank_ = it.rank_;
  1017. i_ = it.i_;
  1018. j_ = it.j_;
  1019. it_ = it.it_;
  1020. return *this;
  1021. }
  1022. // Comparison
  1023. BOOST_UBLAS_INLINE
  1024. bool operator == (const const_iterator2 &it) const {
  1025. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1026. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  1027. if (rank_ == 1 || it.rank_ == 1) {
  1028. return it_ == it.it_;
  1029. } else {
  1030. return i_ == it.i_ && j_ == it.j_;
  1031. }
  1032. }
  1033. private:
  1034. int rank_;
  1035. size_type i_;
  1036. size_type j_;
  1037. const_subiterator_type it_;
  1038. };
  1039. BOOST_UBLAS_INLINE
  1040. const_iterator2 begin2 () const {
  1041. return find2 (0, 0, 0);
  1042. }
  1043. BOOST_UBLAS_INLINE
  1044. const_iterator2 end2 () const {
  1045. return find2 (0, 0, size2_);
  1046. }
  1047. class iterator2:
  1048. public container_reference<mapped_matrix>,
  1049. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  1050. iterator2, value_type> {
  1051. public:
  1052. typedef typename mapped_matrix::value_type value_type;
  1053. typedef typename mapped_matrix::difference_type difference_type;
  1054. typedef typename mapped_matrix::true_reference reference;
  1055. typedef typename mapped_matrix::pointer pointer;
  1056. typedef iterator1 dual_iterator_type;
  1057. typedef reverse_iterator1 dual_reverse_iterator_type;
  1058. // Construction and destruction
  1059. BOOST_UBLAS_INLINE
  1060. iterator2 ():
  1061. container_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
  1062. BOOST_UBLAS_INLINE
  1063. iterator2 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it):
  1064. container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
  1065. // Arithmetic
  1066. BOOST_UBLAS_INLINE
  1067. iterator2 &operator ++ () {
  1068. if (rank_ == 1 && layout_type::fast_j ())
  1069. ++ it_;
  1070. else
  1071. *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1);
  1072. return *this;
  1073. }
  1074. BOOST_UBLAS_INLINE
  1075. iterator2 &operator -- () {
  1076. if (rank_ == 1 && layout_type::fast_j ())
  1077. -- it_;
  1078. else
  1079. *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1);
  1080. return *this;
  1081. }
  1082. // Dereference
  1083. BOOST_UBLAS_INLINE
  1084. reference operator * () const {
  1085. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  1086. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  1087. if (rank_ == 1) {
  1088. return (*it_).second;
  1089. } else {
  1090. return (*this) ().at_element (i_, j_);
  1091. }
  1092. }
  1093. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1094. BOOST_UBLAS_INLINE
  1095. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1096. typename self_type::
  1097. #endif
  1098. iterator1 begin () const {
  1099. self_type &m = (*this) ();
  1100. return m.find1 (1, 0, index2 ());
  1101. }
  1102. BOOST_UBLAS_INLINE
  1103. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1104. typename self_type::
  1105. #endif
  1106. iterator1 end () const {
  1107. self_type &m = (*this) ();
  1108. return m.find1 (1, m.size1 (), index2 ());
  1109. }
  1110. BOOST_UBLAS_INLINE
  1111. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1112. typename self_type::
  1113. #endif
  1114. reverse_iterator1 rbegin () const {
  1115. return reverse_iterator1 (end ());
  1116. }
  1117. BOOST_UBLAS_INLINE
  1118. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1119. typename self_type::
  1120. #endif
  1121. reverse_iterator1 rend () const {
  1122. return reverse_iterator1 (begin ());
  1123. }
  1124. #endif
  1125. // Indices
  1126. BOOST_UBLAS_INLINE
  1127. size_type index1 () const {
  1128. if (rank_ == 1) {
  1129. const self_type &m = (*this) ();
  1130. BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
  1131. return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
  1132. } else {
  1133. return i_;
  1134. }
  1135. }
  1136. BOOST_UBLAS_INLINE
  1137. size_type index2 () const {
  1138. BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
  1139. if (rank_ == 1) {
  1140. const self_type &m = (*this) ();
  1141. BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
  1142. return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
  1143. } else {
  1144. return j_;
  1145. }
  1146. }
  1147. // Assignment
  1148. BOOST_UBLAS_INLINE
  1149. iterator2 &operator = (const iterator2 &it) {
  1150. container_reference<self_type>::assign (&it ());
  1151. rank_ = it.rank_;
  1152. i_ = it.i_;
  1153. j_ = it.j_;
  1154. it_ = it.it_;
  1155. return *this;
  1156. }
  1157. // Comparison
  1158. BOOST_UBLAS_INLINE
  1159. bool operator == (const iterator2 &it) const {
  1160. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1161. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  1162. if (rank_ == 1 || it.rank_ == 1) {
  1163. return it_ == it.it_;
  1164. } else {
  1165. return i_ == it.i_ && j_ == it.j_;
  1166. }
  1167. }
  1168. private:
  1169. int rank_;
  1170. size_type i_;
  1171. size_type j_;
  1172. subiterator_type it_;
  1173. friend class const_iterator2;
  1174. };
  1175. BOOST_UBLAS_INLINE
  1176. iterator2 begin2 () {
  1177. return find2 (0, 0, 0);
  1178. }
  1179. BOOST_UBLAS_INLINE
  1180. iterator2 end2 () {
  1181. return find2 (0, 0, size2_);
  1182. }
  1183. // Reverse iterators
  1184. BOOST_UBLAS_INLINE
  1185. const_reverse_iterator1 rbegin1 () const {
  1186. return const_reverse_iterator1 (end1 ());
  1187. }
  1188. BOOST_UBLAS_INLINE
  1189. const_reverse_iterator1 rend1 () const {
  1190. return const_reverse_iterator1 (begin1 ());
  1191. }
  1192. BOOST_UBLAS_INLINE
  1193. reverse_iterator1 rbegin1 () {
  1194. return reverse_iterator1 (end1 ());
  1195. }
  1196. BOOST_UBLAS_INLINE
  1197. reverse_iterator1 rend1 () {
  1198. return reverse_iterator1 (begin1 ());
  1199. }
  1200. BOOST_UBLAS_INLINE
  1201. const_reverse_iterator2 rbegin2 () const {
  1202. return const_reverse_iterator2 (end2 ());
  1203. }
  1204. BOOST_UBLAS_INLINE
  1205. const_reverse_iterator2 rend2 () const {
  1206. return const_reverse_iterator2 (begin2 ());
  1207. }
  1208. BOOST_UBLAS_INLINE
  1209. reverse_iterator2 rbegin2 () {
  1210. return reverse_iterator2 (end2 ());
  1211. }
  1212. BOOST_UBLAS_INLINE
  1213. reverse_iterator2 rend2 () {
  1214. return reverse_iterator2 (begin2 ());
  1215. }
  1216. // Serialization
  1217. template<class Archive>
  1218. void serialize(Archive & ar, const unsigned int /* file_version */){
  1219. serialization::collection_size_type s1 (size1_);
  1220. serialization::collection_size_type s2 (size2_);
  1221. ar & serialization::make_nvp("size1",s1);
  1222. ar & serialization::make_nvp("size2",s2);
  1223. if (Archive::is_loading::value) {
  1224. size1_ = s1;
  1225. size2_ = s2;
  1226. }
  1227. ar & serialization::make_nvp("data", data_);
  1228. }
  1229. private:
  1230. size_type size1_;
  1231. size_type size2_;
  1232. array_type data_;
  1233. static const value_type zero_;
  1234. };
  1235. template<class T, class L, class A>
  1236. const typename mapped_matrix<T, L, A>::value_type mapped_matrix<T, L, A>::zero_ = value_type/*zero*/();
  1237. // Vector index map based sparse matrix class
  1238. template<class T, class L, class A>
  1239. class mapped_vector_of_mapped_vector:
  1240. public matrix_container<mapped_vector_of_mapped_vector<T, L, A> > {
  1241. typedef T &true_reference;
  1242. typedef T *pointer;
  1243. typedef const T *const_pointer;
  1244. typedef A array_type;
  1245. typedef const A const_array_type;
  1246. typedef L layout_type;
  1247. typedef mapped_vector_of_mapped_vector<T, L, A> self_type;
  1248. public:
  1249. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  1250. using matrix_container<self_type>::operator ();
  1251. #endif
  1252. typedef typename A::size_type size_type;
  1253. typedef typename A::difference_type difference_type;
  1254. typedef T value_type;
  1255. typedef const T &const_reference;
  1256. #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
  1257. typedef typename detail::map_traits<typename A::data_value_type, T>::reference reference;
  1258. #else
  1259. typedef sparse_matrix_element<self_type> reference;
  1260. #endif
  1261. typedef const matrix_reference<const self_type> const_closure_type;
  1262. typedef matrix_reference<self_type> closure_type;
  1263. typedef mapped_vector<T> vector_temporary_type;
  1264. typedef self_type matrix_temporary_type;
  1265. typedef typename A::value_type::second_type vector_data_value_type;
  1266. typedef sparse_tag storage_category;
  1267. typedef typename L::orientation_category orientation_category;
  1268. // Construction and destruction
  1269. BOOST_UBLAS_INLINE
  1270. mapped_vector_of_mapped_vector ():
  1271. matrix_container<self_type> (),
  1272. size1_ (0), size2_ (0), data_ () {
  1273. data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
  1274. }
  1275. BOOST_UBLAS_INLINE
  1276. mapped_vector_of_mapped_vector (size_type size1, size_type size2, size_type non_zeros = 0):
  1277. matrix_container<self_type> (),
  1278. size1_ (size1), size2_ (size2), data_ () {
  1279. data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
  1280. }
  1281. BOOST_UBLAS_INLINE
  1282. mapped_vector_of_mapped_vector (const mapped_vector_of_mapped_vector &m):
  1283. matrix_container<self_type> (),
  1284. size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
  1285. template<class AE>
  1286. BOOST_UBLAS_INLINE
  1287. mapped_vector_of_mapped_vector (const matrix_expression<AE> &ae, size_type non_zeros = 0):
  1288. matrix_container<self_type> (),
  1289. size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () {
  1290. data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
  1291. matrix_assign<scalar_assign> (*this, ae);
  1292. }
  1293. // Accessors
  1294. BOOST_UBLAS_INLINE
  1295. size_type size1 () const {
  1296. return size1_;
  1297. }
  1298. BOOST_UBLAS_INLINE
  1299. size_type size2 () const {
  1300. return size2_;
  1301. }
  1302. BOOST_UBLAS_INLINE
  1303. size_type nnz_capacity () const {
  1304. size_type non_zeros = 0;
  1305. for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv)
  1306. non_zeros += detail::map_capacity (*itv);
  1307. return non_zeros;
  1308. }
  1309. BOOST_UBLAS_INLINE
  1310. size_type nnz () const {
  1311. size_type filled = 0;
  1312. for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv)
  1313. filled += (*itv).size ();
  1314. return filled;
  1315. }
  1316. // Storage accessors
  1317. BOOST_UBLAS_INLINE
  1318. const_array_type &data () const {
  1319. return data_;
  1320. }
  1321. BOOST_UBLAS_INLINE
  1322. array_type &data () {
  1323. return data_;
  1324. }
  1325. // Resizing
  1326. BOOST_UBLAS_INLINE
  1327. void resize (size_type size1, size_type size2, bool preserve = true) {
  1328. // FIXME preserve unimplemented
  1329. BOOST_UBLAS_CHECK (!preserve, internal_logic ());
  1330. size1_ = size1;
  1331. size2_ = size2;
  1332. data ().clear ();
  1333. data () [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
  1334. }
  1335. // Element support
  1336. BOOST_UBLAS_INLINE
  1337. pointer find_element (size_type i, size_type j) {
  1338. return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
  1339. }
  1340. BOOST_UBLAS_INLINE
  1341. const_pointer find_element (size_type i, size_type j) const {
  1342. const size_type element1 = layout_type::index_M (i, j);
  1343. const size_type element2 = layout_type::index_m (i, j);
  1344. vector_const_subiterator_type itv (data ().find (element1));
  1345. if (itv == data ().end ())
  1346. return 0;
  1347. BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
  1348. const_subiterator_type it ((*itv).second.find (element2));
  1349. if (it == (*itv).second.end ())
  1350. return 0;
  1351. BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ()); // broken map
  1352. return &(*it).second;
  1353. }
  1354. // Element access
  1355. BOOST_UBLAS_INLINE
  1356. const_reference operator () (size_type i, size_type j) const {
  1357. const size_type element1 = layout_type::index_M (i, j);
  1358. const size_type element2 = layout_type::index_m (i, j);
  1359. vector_const_subiterator_type itv (data ().find (element1));
  1360. if (itv == data ().end ())
  1361. return zero_;
  1362. BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
  1363. const_subiterator_type it ((*itv).second.find (element2));
  1364. if (it == (*itv).second.end ())
  1365. return zero_;
  1366. BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
  1367. return (*it).second;
  1368. }
  1369. BOOST_UBLAS_INLINE
  1370. reference operator () (size_type i, size_type j) {
  1371. #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
  1372. const size_type element1 = layout_type::index_M (i, j);
  1373. const size_type element2 = layout_type::index_m (i, j);
  1374. vector_data_value_type& vd (data () [element1]);
  1375. std::pair<subiterator_type, bool> ii (vd.insert (typename array_type::value_type::second_type::value_type (element2, value_type/*zero*/())));
  1376. BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ()); // broken map
  1377. return (ii.first)->second;
  1378. #else
  1379. return reference (*this, i, j);
  1380. #endif
  1381. }
  1382. // Element assignment
  1383. BOOST_UBLAS_INLINE
  1384. true_reference insert_element (size_type i, size_type j, const_reference t) {
  1385. BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
  1386. const size_type element1 = layout_type::index_M (i, j);
  1387. const size_type element2 = layout_type::index_m (i, j);
  1388. vector_data_value_type& vd (data () [element1]);
  1389. std::pair<subiterator_type, bool> ii (vd.insert (typename vector_data_value_type::value_type (element2, t)));
  1390. BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ()); // broken map
  1391. if (!ii.second) // existing element
  1392. (ii.first)->second = t;
  1393. return (ii.first)->second;
  1394. }
  1395. BOOST_UBLAS_INLINE
  1396. void erase_element (size_type i, size_type j) {
  1397. vector_subiterator_type itv (data ().find (layout_type::index_M (i, j)));
  1398. if (itv == data ().end ())
  1399. return;
  1400. subiterator_type it ((*itv).second.find (layout_type::index_m (i, j)));
  1401. if (it == (*itv).second.end ())
  1402. return;
  1403. (*itv).second.erase (it);
  1404. }
  1405. // Zeroing
  1406. BOOST_UBLAS_INLINE
  1407. void clear () {
  1408. data ().clear ();
  1409. data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
  1410. }
  1411. // Assignment
  1412. BOOST_UBLAS_INLINE
  1413. mapped_vector_of_mapped_vector &operator = (const mapped_vector_of_mapped_vector &m) {
  1414. if (this != &m) {
  1415. size1_ = m.size1_;
  1416. size2_ = m.size2_;
  1417. data () = m.data ();
  1418. }
  1419. return *this;
  1420. }
  1421. template<class C> // Container assignment without temporary
  1422. BOOST_UBLAS_INLINE
  1423. mapped_vector_of_mapped_vector &operator = (const matrix_container<C> &m) {
  1424. resize (m ().size1 (), m ().size2 (), false);
  1425. assign (m);
  1426. return *this;
  1427. }
  1428. BOOST_UBLAS_INLINE
  1429. mapped_vector_of_mapped_vector &assign_temporary (mapped_vector_of_mapped_vector &m) {
  1430. swap (m);
  1431. return *this;
  1432. }
  1433. template<class AE>
  1434. BOOST_UBLAS_INLINE
  1435. mapped_vector_of_mapped_vector &operator = (const matrix_expression<AE> &ae) {
  1436. self_type temporary (ae);
  1437. return assign_temporary (temporary);
  1438. }
  1439. template<class AE>
  1440. BOOST_UBLAS_INLINE
  1441. mapped_vector_of_mapped_vector &assign (const matrix_expression<AE> &ae) {
  1442. matrix_assign<scalar_assign> (*this, ae);
  1443. return *this;
  1444. }
  1445. template<class AE>
  1446. BOOST_UBLAS_INLINE
  1447. mapped_vector_of_mapped_vector& operator += (const matrix_expression<AE> &ae) {
  1448. self_type temporary (*this + ae);
  1449. return assign_temporary (temporary);
  1450. }
  1451. template<class C> // Container assignment without temporary
  1452. BOOST_UBLAS_INLINE
  1453. mapped_vector_of_mapped_vector &operator += (const matrix_container<C> &m) {
  1454. plus_assign (m);
  1455. return *this;
  1456. }
  1457. template<class AE>
  1458. BOOST_UBLAS_INLINE
  1459. mapped_vector_of_mapped_vector &plus_assign (const matrix_expression<AE> &ae) {
  1460. matrix_assign<scalar_plus_assign> (*this, ae);
  1461. return *this;
  1462. }
  1463. template<class AE>
  1464. BOOST_UBLAS_INLINE
  1465. mapped_vector_of_mapped_vector& operator -= (const matrix_expression<AE> &ae) {
  1466. self_type temporary (*this - ae);
  1467. return assign_temporary (temporary);
  1468. }
  1469. template<class C> // Container assignment without temporary
  1470. BOOST_UBLAS_INLINE
  1471. mapped_vector_of_mapped_vector &operator -= (const matrix_container<C> &m) {
  1472. minus_assign (m);
  1473. return *this;
  1474. }
  1475. template<class AE>
  1476. BOOST_UBLAS_INLINE
  1477. mapped_vector_of_mapped_vector &minus_assign (const matrix_expression<AE> &ae) {
  1478. matrix_assign<scalar_minus_assign> (*this, ae);
  1479. return *this;
  1480. }
  1481. template<class AT>
  1482. BOOST_UBLAS_INLINE
  1483. mapped_vector_of_mapped_vector& operator *= (const AT &at) {
  1484. matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  1485. return *this;
  1486. }
  1487. template<class AT>
  1488. BOOST_UBLAS_INLINE
  1489. mapped_vector_of_mapped_vector& operator /= (const AT &at) {
  1490. matrix_assign_scalar<scalar_divides_assign> (*this, at);
  1491. return *this;
  1492. }
  1493. // Swapping
  1494. BOOST_UBLAS_INLINE
  1495. void swap (mapped_vector_of_mapped_vector &m) {
  1496. if (this != &m) {
  1497. std::swap (size1_, m.size1_);
  1498. std::swap (size2_, m.size2_);
  1499. data ().swap (m.data ());
  1500. }
  1501. }
  1502. BOOST_UBLAS_INLINE
  1503. friend void swap (mapped_vector_of_mapped_vector &m1, mapped_vector_of_mapped_vector &m2) {
  1504. m1.swap (m2);
  1505. }
  1506. // Iterator types
  1507. private:
  1508. // Use storage iterators
  1509. typedef typename A::const_iterator vector_const_subiterator_type;
  1510. typedef typename A::iterator vector_subiterator_type;
  1511. typedef typename A::value_type::second_type::const_iterator const_subiterator_type;
  1512. typedef typename A::value_type::second_type::iterator subiterator_type;
  1513. BOOST_UBLAS_INLINE
  1514. true_reference at_element (size_type i, size_type j) {
  1515. const size_type element1 = layout_type::index_M (i, j);
  1516. const size_type element2 = layout_type::index_m (i, j);
  1517. vector_subiterator_type itv (data ().find (element1));
  1518. BOOST_UBLAS_CHECK (itv != data ().end(), bad_index ());
  1519. BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
  1520. subiterator_type it ((*itv).second.find (element2));
  1521. BOOST_UBLAS_CHECK (it != (*itv).second.end (), bad_index ());
  1522. BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ()); // broken map
  1523. return it->second;
  1524. }
  1525. public:
  1526. class const_iterator1;
  1527. class iterator1;
  1528. class const_iterator2;
  1529. class iterator2;
  1530. typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  1531. typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  1532. typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  1533. typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  1534. // Element lookup
  1535. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  1536. const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
  1537. BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
  1538. for (;;) {
  1539. vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
  1540. vector_const_subiterator_type itv_end (data ().end ());
  1541. if (itv == itv_end)
  1542. return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
  1543. const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
  1544. const_subiterator_type it_end ((*itv).second.end ());
  1545. if (rank == 0) {
  1546. // advance to the first available major index
  1547. size_type M = itv->first;
  1548. size_type m;
  1549. if (it != it_end) {
  1550. m = it->first;
  1551. } else {
  1552. m = layout_type::size_m(size1_, size2_);
  1553. }
  1554. size_type first_i = layout_type::index_M(M,m);
  1555. return const_iterator1 (*this, rank, first_i, j, itv, it);
  1556. }
  1557. if (it != it_end && (*it).first == layout_type::index_m (i, j))
  1558. return const_iterator1 (*this, rank, i, j, itv, it);
  1559. if (direction > 0) {
  1560. if (layout_type::fast_i ()) {
  1561. if (it == it_end)
  1562. return const_iterator1 (*this, rank, i, j, itv, it);
  1563. i = (*it).first;
  1564. } else {
  1565. if (i >= size1_)
  1566. return const_iterator1 (*this, rank, i, j, itv, it);
  1567. ++ i;
  1568. }
  1569. } else /* if (direction < 0) */ {
  1570. if (layout_type::fast_i ()) {
  1571. if (it == (*itv).second.begin ())
  1572. return const_iterator1 (*this, rank, i, j, itv, it);
  1573. -- it;
  1574. i = (*it).first;
  1575. } else {
  1576. if (i == 0)
  1577. return const_iterator1 (*this, rank, i, j, itv, it);
  1578. -- i;
  1579. }
  1580. }
  1581. }
  1582. }
  1583. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  1584. iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
  1585. BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
  1586. for (;;) {
  1587. vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
  1588. vector_subiterator_type itv_end (data ().end ());
  1589. if (itv == itv_end)
  1590. return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
  1591. subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
  1592. subiterator_type it_end ((*itv).second.end ());
  1593. if (rank == 0) {
  1594. // advance to the first available major index
  1595. size_type M = itv->first;
  1596. size_type m;
  1597. if (it != it_end) {
  1598. m = it->first;
  1599. } else {
  1600. m = layout_type::size_m(size1_, size2_);
  1601. }
  1602. size_type first_i = layout_type::index_M(M,m);
  1603. return iterator1 (*this, rank, first_i, j, itv, it);
  1604. }
  1605. if (it != it_end && (*it).first == layout_type::index_m (i, j))
  1606. return iterator1 (*this, rank, i, j, itv, it);
  1607. if (direction > 0) {
  1608. if (layout_type::fast_i ()) {
  1609. if (it == it_end)
  1610. return iterator1 (*this, rank, i, j, itv, it);
  1611. i = (*it).first;
  1612. } else {
  1613. if (i >= size1_)
  1614. return iterator1 (*this, rank, i, j, itv, it);
  1615. ++ i;
  1616. }
  1617. } else /* if (direction < 0) */ {
  1618. if (layout_type::fast_i ()) {
  1619. if (it == (*itv).second.begin ())
  1620. return iterator1 (*this, rank, i, j, itv, it);
  1621. -- it;
  1622. i = (*it).first;
  1623. } else {
  1624. if (i == 0)
  1625. return iterator1 (*this, rank, i, j, itv, it);
  1626. -- i;
  1627. }
  1628. }
  1629. }
  1630. }
  1631. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  1632. const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
  1633. BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
  1634. for (;;) {
  1635. vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
  1636. vector_const_subiterator_type itv_end (data ().end ());
  1637. if (itv == itv_end)
  1638. return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
  1639. const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
  1640. const_subiterator_type it_end ((*itv).second.end ());
  1641. if (rank == 0) {
  1642. // advance to the first available major index
  1643. size_type M = itv->first;
  1644. size_type m;
  1645. if (it != it_end) {
  1646. m = it->first;
  1647. } else {
  1648. m = layout_type::size_m(size1_, size2_);
  1649. }
  1650. size_type first_j = layout_type::index_m(M,m);
  1651. return const_iterator2 (*this, rank, i, first_j, itv, it);
  1652. }
  1653. if (it != it_end && (*it).first == layout_type::index_m (i, j))
  1654. return const_iterator2 (*this, rank, i, j, itv, it);
  1655. if (direction > 0) {
  1656. if (layout_type::fast_j ()) {
  1657. if (it == it_end)
  1658. return const_iterator2 (*this, rank, i, j, itv, it);
  1659. j = (*it).first;
  1660. } else {
  1661. if (j >= size2_)
  1662. return const_iterator2 (*this, rank, i, j, itv, it);
  1663. ++ j;
  1664. }
  1665. } else /* if (direction < 0) */ {
  1666. if (layout_type::fast_j ()) {
  1667. if (it == (*itv).second.begin ())
  1668. return const_iterator2 (*this, rank, i, j, itv, it);
  1669. -- it;
  1670. j = (*it).first;
  1671. } else {
  1672. if (j == 0)
  1673. return const_iterator2 (*this, rank, i, j, itv, it);
  1674. -- j;
  1675. }
  1676. }
  1677. }
  1678. }
  1679. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  1680. iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
  1681. BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
  1682. for (;;) {
  1683. vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
  1684. vector_subiterator_type itv_end (data ().end ());
  1685. if (itv == itv_end)
  1686. return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
  1687. subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
  1688. subiterator_type it_end ((*itv).second.end ());
  1689. if (rank == 0) {
  1690. // advance to the first available major index
  1691. size_type M = itv->first;
  1692. size_type m;
  1693. if (it != it_end) {
  1694. m = it->first;
  1695. } else {
  1696. m = layout_type::size_m(size1_, size2_);
  1697. }
  1698. size_type first_j = layout_type::index_m(M,m);
  1699. return iterator2 (*this, rank, i, first_j, itv, it);
  1700. }
  1701. if (it != it_end && (*it).first == layout_type::index_m (i, j))
  1702. return iterator2 (*this, rank, i, j, itv, it);
  1703. if (direction > 0) {
  1704. if (layout_type::fast_j ()) {
  1705. if (it == it_end)
  1706. return iterator2 (*this, rank, i, j, itv, it);
  1707. j = (*it).first;
  1708. } else {
  1709. if (j >= size2_)
  1710. return iterator2 (*this, rank, i, j, itv, it);
  1711. ++ j;
  1712. }
  1713. } else /* if (direction < 0) */ {
  1714. if (layout_type::fast_j ()) {
  1715. if (it == (*itv).second.begin ())
  1716. return iterator2 (*this, rank, i, j, itv, it);
  1717. -- it;
  1718. j = (*it).first;
  1719. } else {
  1720. if (j == 0)
  1721. return iterator2 (*this, rank, i, j, itv, it);
  1722. -- j;
  1723. }
  1724. }
  1725. }
  1726. }
  1727. class const_iterator1:
  1728. public container_const_reference<mapped_vector_of_mapped_vector>,
  1729. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  1730. const_iterator1, value_type> {
  1731. public:
  1732. typedef typename mapped_vector_of_mapped_vector::value_type value_type;
  1733. typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
  1734. typedef typename mapped_vector_of_mapped_vector::const_reference reference;
  1735. typedef const typename mapped_vector_of_mapped_vector::pointer pointer;
  1736. typedef const_iterator2 dual_iterator_type;
  1737. typedef const_reverse_iterator2 dual_reverse_iterator_type;
  1738. // Construction and destruction
  1739. BOOST_UBLAS_INLINE
  1740. const_iterator1 ():
  1741. container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  1742. BOOST_UBLAS_INLINE
  1743. const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
  1744. container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  1745. BOOST_UBLAS_INLINE
  1746. const_iterator1 (const iterator1 &it):
  1747. container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
  1748. // Arithmetic
  1749. BOOST_UBLAS_INLINE
  1750. const_iterator1 &operator ++ () {
  1751. if (rank_ == 1 && layout_type::fast_i ())
  1752. ++ it_;
  1753. else {
  1754. const self_type &m = (*this) ();
  1755. if (rank_ == 0) {
  1756. ++ itv_;
  1757. i_ = itv_->first;
  1758. } else {
  1759. i_ = index1 () + 1;
  1760. }
  1761. if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
  1762. *this = m.find1 (rank_, i_, j_, 1);
  1763. else if (rank_ == 1) {
  1764. it_ = (*itv_).second.begin ();
  1765. if (it_ == (*itv_).second.end () || index2 () != j_)
  1766. *this = m.find1 (rank_, i_, j_, 1);
  1767. }
  1768. }
  1769. return *this;
  1770. }
  1771. BOOST_UBLAS_INLINE
  1772. const_iterator1 &operator -- () {
  1773. if (rank_ == 1 && layout_type::fast_i ())
  1774. -- it_;
  1775. else {
  1776. const self_type &m = (*this) ();
  1777. if (rank_ == 0) {
  1778. -- itv_;
  1779. i_ = itv_->first;
  1780. } else {
  1781. i_ = index1 () - 1;
  1782. }
  1783. // FIXME: this expression should never become true!
  1784. if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
  1785. *this = m.find1 (rank_, i_, j_, -1);
  1786. else if (rank_ == 1) {
  1787. it_ = (*itv_).second.begin ();
  1788. if (it_ == (*itv_).second.end () || index2 () != j_)
  1789. *this = m.find1 (rank_, i_, j_, -1);
  1790. }
  1791. }
  1792. return *this;
  1793. }
  1794. // Dereference
  1795. BOOST_UBLAS_INLINE
  1796. const_reference operator * () const {
  1797. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  1798. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  1799. if (rank_ == 1) {
  1800. return (*it_).second;
  1801. } else {
  1802. return (*this) () (i_, j_);
  1803. }
  1804. }
  1805. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1806. BOOST_UBLAS_INLINE
  1807. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1808. typename self_type::
  1809. #endif
  1810. const_iterator2 begin () const {
  1811. const self_type &m = (*this) ();
  1812. return m.find2 (1, index1 (), 0);
  1813. }
  1814. BOOST_UBLAS_INLINE
  1815. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1816. typename self_type::
  1817. #endif
  1818. const_iterator2 end () const {
  1819. const self_type &m = (*this) ();
  1820. return m.find2 (1, index1 (), m.size2 ());
  1821. }
  1822. BOOST_UBLAS_INLINE
  1823. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1824. typename self_type::
  1825. #endif
  1826. const_reverse_iterator2 rbegin () const {
  1827. return const_reverse_iterator2 (end ());
  1828. }
  1829. BOOST_UBLAS_INLINE
  1830. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1831. typename self_type::
  1832. #endif
  1833. const_reverse_iterator2 rend () const {
  1834. return const_reverse_iterator2 (begin ());
  1835. }
  1836. #endif
  1837. // Indices
  1838. BOOST_UBLAS_INLINE
  1839. size_type index1 () const {
  1840. BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
  1841. if (rank_ == 1) {
  1842. BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
  1843. return layout_type::index_M ((*itv_).first, (*it_).first);
  1844. } else {
  1845. return i_;
  1846. }
  1847. }
  1848. BOOST_UBLAS_INLINE
  1849. size_type index2 () const {
  1850. if (rank_ == 1) {
  1851. BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
  1852. return layout_type::index_m ((*itv_).first, (*it_).first);
  1853. } else {
  1854. return j_;
  1855. }
  1856. }
  1857. // Assignment
  1858. BOOST_UBLAS_INLINE
  1859. const_iterator1 &operator = (const const_iterator1 &it) {
  1860. container_const_reference<self_type>::assign (&it ());
  1861. rank_ = it.rank_;
  1862. i_ = it.i_;
  1863. j_ = it.j_;
  1864. itv_ = it.itv_;
  1865. it_ = it.it_;
  1866. return *this;
  1867. }
  1868. // Comparison
  1869. BOOST_UBLAS_INLINE
  1870. bool operator == (const const_iterator1 &it) const {
  1871. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1872. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  1873. if (rank_ == 1 || it.rank_ == 1) {
  1874. return it_ == it.it_;
  1875. } else {
  1876. return i_ == it.i_ && j_ == it.j_;
  1877. }
  1878. }
  1879. private:
  1880. int rank_;
  1881. size_type i_;
  1882. size_type j_;
  1883. vector_const_subiterator_type itv_;
  1884. const_subiterator_type it_;
  1885. };
  1886. BOOST_UBLAS_INLINE
  1887. const_iterator1 begin1 () const {
  1888. return find1 (0, 0, 0);
  1889. }
  1890. BOOST_UBLAS_INLINE
  1891. const_iterator1 end1 () const {
  1892. return find1 (0, size1_, 0);
  1893. }
  1894. class iterator1:
  1895. public container_reference<mapped_vector_of_mapped_vector>,
  1896. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  1897. iterator1, value_type> {
  1898. public:
  1899. typedef typename mapped_vector_of_mapped_vector::value_type value_type;
  1900. typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
  1901. typedef typename mapped_vector_of_mapped_vector::true_reference reference;
  1902. typedef typename mapped_vector_of_mapped_vector::pointer pointer;
  1903. typedef iterator2 dual_iterator_type;
  1904. typedef reverse_iterator2 dual_reverse_iterator_type;
  1905. // Construction and destruction
  1906. BOOST_UBLAS_INLINE
  1907. iterator1 ():
  1908. container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  1909. BOOST_UBLAS_INLINE
  1910. iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
  1911. container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  1912. // Arithmetic
  1913. BOOST_UBLAS_INLINE
  1914. iterator1 &operator ++ () {
  1915. if (rank_ == 1 && layout_type::fast_i ())
  1916. ++ it_;
  1917. else {
  1918. self_type &m = (*this) ();
  1919. if (rank_ == 0) {
  1920. ++ itv_;
  1921. i_ = itv_->first;
  1922. } else {
  1923. i_ = index1 () + 1;
  1924. }
  1925. if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
  1926. *this = m.find1 (rank_, i_, j_, 1);
  1927. else if (rank_ == 1) {
  1928. it_ = (*itv_).second.begin ();
  1929. if (it_ == (*itv_).second.end () || index2 () != j_)
  1930. *this = m.find1 (rank_, i_, j_, 1);
  1931. }
  1932. }
  1933. return *this;
  1934. }
  1935. BOOST_UBLAS_INLINE
  1936. iterator1 &operator -- () {
  1937. if (rank_ == 1 && layout_type::fast_i ())
  1938. -- it_;
  1939. else {
  1940. self_type &m = (*this) ();
  1941. if (rank_ == 0) {
  1942. -- itv_;
  1943. i_ = itv_->first;
  1944. } else {
  1945. i_ = index1 () - 1;
  1946. }
  1947. // FIXME: this expression should never become true!
  1948. if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
  1949. *this = m.find1 (rank_, i_, j_, -1);
  1950. else if (rank_ == 1) {
  1951. it_ = (*itv_).second.begin ();
  1952. if (it_ == (*itv_).second.end () || index2 () != j_)
  1953. *this = m.find1 (rank_, i_, j_, -1);
  1954. }
  1955. }
  1956. return *this;
  1957. }
  1958. // Dereference
  1959. BOOST_UBLAS_INLINE
  1960. reference operator * () const {
  1961. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  1962. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  1963. if (rank_ == 1) {
  1964. return (*it_).second;
  1965. } else {
  1966. return (*this) ().at_element (i_, j_);
  1967. }
  1968. }
  1969. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1970. BOOST_UBLAS_INLINE
  1971. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1972. typename self_type::
  1973. #endif
  1974. iterator2 begin () const {
  1975. self_type &m = (*this) ();
  1976. return m.find2 (1, index1 (), 0);
  1977. }
  1978. BOOST_UBLAS_INLINE
  1979. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1980. typename self_type::
  1981. #endif
  1982. iterator2 end () const {
  1983. self_type &m = (*this) ();
  1984. return m.find2 (1, index1 (), m.size2 ());
  1985. }
  1986. BOOST_UBLAS_INLINE
  1987. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1988. typename self_type::
  1989. #endif
  1990. reverse_iterator2 rbegin () const {
  1991. return reverse_iterator2 (end ());
  1992. }
  1993. BOOST_UBLAS_INLINE
  1994. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1995. typename self_type::
  1996. #endif
  1997. reverse_iterator2 rend () const {
  1998. return reverse_iterator2 (begin ());
  1999. }
  2000. #endif
  2001. // Indices
  2002. BOOST_UBLAS_INLINE
  2003. size_type index1 () const {
  2004. BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
  2005. if (rank_ == 1) {
  2006. BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
  2007. return layout_type::index_M ((*itv_).first, (*it_).first);
  2008. } else {
  2009. return i_;
  2010. }
  2011. }
  2012. BOOST_UBLAS_INLINE
  2013. size_type index2 () const {
  2014. if (rank_ == 1) {
  2015. BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
  2016. return layout_type::index_m ((*itv_).first, (*it_).first);
  2017. } else {
  2018. return j_;
  2019. }
  2020. }
  2021. // Assignment
  2022. BOOST_UBLAS_INLINE
  2023. iterator1 &operator = (const iterator1 &it) {
  2024. container_reference<self_type>::assign (&it ());
  2025. rank_ = it.rank_;
  2026. i_ = it.i_;
  2027. j_ = it.j_;
  2028. itv_ = it.itv_;
  2029. it_ = it.it_;
  2030. return *this;
  2031. }
  2032. // Comparison
  2033. BOOST_UBLAS_INLINE
  2034. bool operator == (const iterator1 &it) const {
  2035. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2036. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  2037. if (rank_ == 1 || it.rank_ == 1) {
  2038. return it_ == it.it_;
  2039. } else {
  2040. return i_ == it.i_ && j_ == it.j_;
  2041. }
  2042. }
  2043. private:
  2044. int rank_;
  2045. size_type i_;
  2046. size_type j_;
  2047. vector_subiterator_type itv_;
  2048. subiterator_type it_;
  2049. friend class const_iterator1;
  2050. };
  2051. BOOST_UBLAS_INLINE
  2052. iterator1 begin1 () {
  2053. return find1 (0, 0, 0);
  2054. }
  2055. BOOST_UBLAS_INLINE
  2056. iterator1 end1 () {
  2057. return find1 (0, size1_, 0);
  2058. }
  2059. class const_iterator2:
  2060. public container_const_reference<mapped_vector_of_mapped_vector>,
  2061. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  2062. const_iterator2, value_type> {
  2063. public:
  2064. typedef typename mapped_vector_of_mapped_vector::value_type value_type;
  2065. typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
  2066. typedef typename mapped_vector_of_mapped_vector::const_reference reference;
  2067. typedef const typename mapped_vector_of_mapped_vector::pointer pointer;
  2068. typedef const_iterator1 dual_iterator_type;
  2069. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  2070. // Construction and destruction
  2071. BOOST_UBLAS_INLINE
  2072. const_iterator2 ():
  2073. container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  2074. BOOST_UBLAS_INLINE
  2075. const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
  2076. container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  2077. BOOST_UBLAS_INLINE
  2078. const_iterator2 (const iterator2 &it):
  2079. container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
  2080. // Arithmetic
  2081. BOOST_UBLAS_INLINE
  2082. const_iterator2 &operator ++ () {
  2083. if (rank_ == 1 && layout_type::fast_j ())
  2084. ++ it_;
  2085. else {
  2086. const self_type &m = (*this) ();
  2087. if (rank_ == 0) {
  2088. ++ itv_;
  2089. j_ = itv_->first;
  2090. } else {
  2091. j_ = index2 () + 1;
  2092. }
  2093. if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
  2094. *this = m.find2 (rank_, i_, j_, 1);
  2095. else if (rank_ == 1) {
  2096. it_ = (*itv_).second.begin ();
  2097. if (it_ == (*itv_).second.end () || index1 () != i_)
  2098. *this = m.find2 (rank_, i_, j_, 1);
  2099. }
  2100. }
  2101. return *this;
  2102. }
  2103. BOOST_UBLAS_INLINE
  2104. const_iterator2 &operator -- () {
  2105. if (rank_ == 1 && layout_type::fast_j ())
  2106. -- it_;
  2107. else {
  2108. const self_type &m = (*this) ();
  2109. if (rank_ == 0) {
  2110. -- itv_;
  2111. j_ = itv_->first;
  2112. } else {
  2113. j_ = index2 () - 1;
  2114. }
  2115. // FIXME: this expression should never become true!
  2116. if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
  2117. *this = m.find2 (rank_, i_, j_, -1);
  2118. else if (rank_ == 1) {
  2119. it_ = (*itv_).second.begin ();
  2120. if (it_ == (*itv_).second.end () || index1 () != i_)
  2121. *this = m.find2 (rank_, i_, j_, -1);
  2122. }
  2123. }
  2124. return *this;
  2125. }
  2126. // Dereference
  2127. BOOST_UBLAS_INLINE
  2128. const_reference operator * () const {
  2129. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  2130. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  2131. if (rank_ == 1) {
  2132. return (*it_).second;
  2133. } else {
  2134. return (*this) () (i_, j_);
  2135. }
  2136. }
  2137. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  2138. BOOST_UBLAS_INLINE
  2139. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2140. typename self_type::
  2141. #endif
  2142. const_iterator1 begin () const {
  2143. const self_type &m = (*this) ();
  2144. return m.find1 (1, 0, index2 ());
  2145. }
  2146. BOOST_UBLAS_INLINE
  2147. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2148. typename self_type::
  2149. #endif
  2150. const_iterator1 end () const {
  2151. const self_type &m = (*this) ();
  2152. return m.find1 (1, m.size1 (), index2 ());
  2153. }
  2154. BOOST_UBLAS_INLINE
  2155. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2156. typename self_type::
  2157. #endif
  2158. const_reverse_iterator1 rbegin () const {
  2159. return const_reverse_iterator1 (end ());
  2160. }
  2161. BOOST_UBLAS_INLINE
  2162. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2163. typename self_type::
  2164. #endif
  2165. const_reverse_iterator1 rend () const {
  2166. return const_reverse_iterator1 (begin ());
  2167. }
  2168. #endif
  2169. // Indices
  2170. BOOST_UBLAS_INLINE
  2171. size_type index1 () const {
  2172. if (rank_ == 1) {
  2173. BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
  2174. return layout_type::index_M ((*itv_).first, (*it_).first);
  2175. } else {
  2176. return i_;
  2177. }
  2178. }
  2179. BOOST_UBLAS_INLINE
  2180. size_type index2 () const {
  2181. BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
  2182. if (rank_ == 1) {
  2183. BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
  2184. return layout_type::index_m ((*itv_).first, (*it_).first);
  2185. } else {
  2186. return j_;
  2187. }
  2188. }
  2189. // Assignment
  2190. BOOST_UBLAS_INLINE
  2191. const_iterator2 &operator = (const const_iterator2 &it) {
  2192. container_const_reference<self_type>::assign (&it ());
  2193. rank_ = it.rank_;
  2194. i_ = it.i_;
  2195. j_ = it.j_;
  2196. itv_ = it.itv_;
  2197. it_ = it.it_;
  2198. return *this;
  2199. }
  2200. // Comparison
  2201. BOOST_UBLAS_INLINE
  2202. bool operator == (const const_iterator2 &it) const {
  2203. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2204. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  2205. if (rank_ == 1 || it.rank_ == 1) {
  2206. return it_ == it.it_;
  2207. } else {
  2208. return i_ == it.i_ && j_ == it.j_;
  2209. }
  2210. }
  2211. private:
  2212. int rank_;
  2213. size_type i_;
  2214. size_type j_;
  2215. vector_const_subiterator_type itv_;
  2216. const_subiterator_type it_;
  2217. };
  2218. BOOST_UBLAS_INLINE
  2219. const_iterator2 begin2 () const {
  2220. return find2 (0, 0, 0);
  2221. }
  2222. BOOST_UBLAS_INLINE
  2223. const_iterator2 end2 () const {
  2224. return find2 (0, 0, size2_);
  2225. }
  2226. class iterator2:
  2227. public container_reference<mapped_vector_of_mapped_vector>,
  2228. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  2229. iterator2, value_type> {
  2230. public:
  2231. typedef typename mapped_vector_of_mapped_vector::value_type value_type;
  2232. typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
  2233. typedef typename mapped_vector_of_mapped_vector::true_reference reference;
  2234. typedef typename mapped_vector_of_mapped_vector::pointer pointer;
  2235. typedef iterator1 dual_iterator_type;
  2236. typedef reverse_iterator1 dual_reverse_iterator_type;
  2237. // Construction and destruction
  2238. BOOST_UBLAS_INLINE
  2239. iterator2 ():
  2240. container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  2241. BOOST_UBLAS_INLINE
  2242. iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
  2243. container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  2244. // Arithmetic
  2245. BOOST_UBLAS_INLINE
  2246. iterator2 &operator ++ () {
  2247. if (rank_ == 1 && layout_type::fast_j ())
  2248. ++ it_;
  2249. else {
  2250. self_type &m = (*this) ();
  2251. if (rank_ == 0) {
  2252. ++ itv_;
  2253. j_ = itv_->first;
  2254. } else {
  2255. j_ = index2 () + 1;
  2256. }
  2257. if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
  2258. *this = m.find2 (rank_, i_, j_, 1);
  2259. else if (rank_ == 1) {
  2260. it_ = (*itv_).second.begin ();
  2261. if (it_ == (*itv_).second.end () || index1 () != i_)
  2262. *this = m.find2 (rank_, i_, j_, 1);
  2263. }
  2264. }
  2265. return *this;
  2266. }
  2267. BOOST_UBLAS_INLINE
  2268. iterator2 &operator -- () {
  2269. if (rank_ == 1 && layout_type::fast_j ())
  2270. -- it_;
  2271. else {
  2272. self_type &m = (*this) ();
  2273. if (rank_ == 0) {
  2274. -- itv_;
  2275. j_ = itv_->first;
  2276. } else {
  2277. j_ = index2 () - 1;
  2278. }
  2279. // FIXME: this expression should never become true!
  2280. if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
  2281. *this = m.find2 (rank_, i_, j_, -1);
  2282. else if (rank_ == 1) {
  2283. it_ = (*itv_).second.begin ();
  2284. if (it_ == (*itv_).second.end () || index1 () != i_)
  2285. *this = m.find2 (rank_, i_, j_, -1);
  2286. }
  2287. }
  2288. return *this;
  2289. }
  2290. // Dereference
  2291. BOOST_UBLAS_INLINE
  2292. reference operator * () const {
  2293. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  2294. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  2295. if (rank_ == 1) {
  2296. return (*it_).second;
  2297. } else {
  2298. return (*this) ().at_element (i_, j_);
  2299. }
  2300. }
  2301. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  2302. BOOST_UBLAS_INLINE
  2303. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2304. typename self_type::
  2305. #endif
  2306. iterator1 begin () const {
  2307. self_type &m = (*this) ();
  2308. return m.find1 (1, 0, index2 ());
  2309. }
  2310. BOOST_UBLAS_INLINE
  2311. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2312. typename self_type::
  2313. #endif
  2314. iterator1 end () const {
  2315. self_type &m = (*this) ();
  2316. return m.find1 (1, m.size1 (), index2 ());
  2317. }
  2318. BOOST_UBLAS_INLINE
  2319. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2320. typename self_type::
  2321. #endif
  2322. reverse_iterator1 rbegin () const {
  2323. return reverse_iterator1 (end ());
  2324. }
  2325. BOOST_UBLAS_INLINE
  2326. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2327. typename self_type::
  2328. #endif
  2329. reverse_iterator1 rend () const {
  2330. return reverse_iterator1 (begin ());
  2331. }
  2332. #endif
  2333. // Indices
  2334. BOOST_UBLAS_INLINE
  2335. size_type index1 () const {
  2336. if (rank_ == 1) {
  2337. BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
  2338. return layout_type::index_M ((*itv_).first, (*it_).first);
  2339. } else {
  2340. return i_;
  2341. }
  2342. }
  2343. BOOST_UBLAS_INLINE
  2344. size_type index2 () const {
  2345. BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
  2346. if (rank_ == 1) {
  2347. BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
  2348. return layout_type::index_m ((*itv_).first, (*it_).first);
  2349. } else {
  2350. return j_;
  2351. }
  2352. }
  2353. // Assignment
  2354. BOOST_UBLAS_INLINE
  2355. iterator2 &operator = (const iterator2 &it) {
  2356. container_reference<self_type>::assign (&it ());
  2357. rank_ = it.rank_;
  2358. i_ = it.i_;
  2359. j_ = it.j_;
  2360. itv_ = it.itv_;
  2361. it_ = it.it_;
  2362. return *this;
  2363. }
  2364. // Comparison
  2365. BOOST_UBLAS_INLINE
  2366. bool operator == (const iterator2 &it) const {
  2367. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2368. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  2369. if (rank_ == 1 || it.rank_ == 1) {
  2370. return it_ == it.it_;
  2371. } else {
  2372. return i_ == it.i_ && j_ == it.j_;
  2373. }
  2374. }
  2375. private:
  2376. int rank_;
  2377. size_type i_;
  2378. size_type j_;
  2379. vector_subiterator_type itv_;
  2380. subiterator_type it_;
  2381. friend class const_iterator2;
  2382. };
  2383. BOOST_UBLAS_INLINE
  2384. iterator2 begin2 () {
  2385. return find2 (0, 0, 0);
  2386. }
  2387. BOOST_UBLAS_INLINE
  2388. iterator2 end2 () {
  2389. return find2 (0, 0, size2_);
  2390. }
  2391. // Reverse iterators
  2392. BOOST_UBLAS_INLINE
  2393. const_reverse_iterator1 rbegin1 () const {
  2394. return const_reverse_iterator1 (end1 ());
  2395. }
  2396. BOOST_UBLAS_INLINE
  2397. const_reverse_iterator1 rend1 () const {
  2398. return const_reverse_iterator1 (begin1 ());
  2399. }
  2400. BOOST_UBLAS_INLINE
  2401. reverse_iterator1 rbegin1 () {
  2402. return reverse_iterator1 (end1 ());
  2403. }
  2404. BOOST_UBLAS_INLINE
  2405. reverse_iterator1 rend1 () {
  2406. return reverse_iterator1 (begin1 ());
  2407. }
  2408. BOOST_UBLAS_INLINE
  2409. const_reverse_iterator2 rbegin2 () const {
  2410. return const_reverse_iterator2 (end2 ());
  2411. }
  2412. BOOST_UBLAS_INLINE
  2413. const_reverse_iterator2 rend2 () const {
  2414. return const_reverse_iterator2 (begin2 ());
  2415. }
  2416. BOOST_UBLAS_INLINE
  2417. reverse_iterator2 rbegin2 () {
  2418. return reverse_iterator2 (end2 ());
  2419. }
  2420. BOOST_UBLAS_INLINE
  2421. reverse_iterator2 rend2 () {
  2422. return reverse_iterator2 (begin2 ());
  2423. }
  2424. // Serialization
  2425. template<class Archive>
  2426. void serialize(Archive & ar, const unsigned int /* file_version */){
  2427. serialization::collection_size_type s1 (size1_);
  2428. serialization::collection_size_type s2 (size2_);
  2429. ar & serialization::make_nvp("size1",s1);
  2430. ar & serialization::make_nvp("size2",s2);
  2431. if (Archive::is_loading::value) {
  2432. size1_ = s1;
  2433. size2_ = s2;
  2434. }
  2435. ar & serialization::make_nvp("data", data_);
  2436. }
  2437. private:
  2438. size_type size1_;
  2439. size_type size2_;
  2440. array_type data_;
  2441. static const value_type zero_;
  2442. };
  2443. template<class T, class L, class A>
  2444. const typename mapped_vector_of_mapped_vector<T, L, A>::value_type mapped_vector_of_mapped_vector<T, L, A>::zero_ = value_type/*zero*/();
  2445. // Comperssed array based sparse matrix class
  2446. // Thanks to Kresimir Fresl for extending this to cover different index bases.
  2447. template<class T, class L, std::size_t IB, class IA, class TA>
  2448. class compressed_matrix:
  2449. public matrix_container<compressed_matrix<T, L, IB, IA, TA> > {
  2450. typedef T &true_reference;
  2451. typedef T *pointer;
  2452. typedef const T *const_pointer;
  2453. typedef L layout_type;
  2454. typedef compressed_matrix<T, L, IB, IA, TA> self_type;
  2455. public:
  2456. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  2457. using matrix_container<self_type>::operator ();
  2458. #endif
  2459. // ISSUE require type consistency check
  2460. // is_convertable (IA::size_type, TA::size_type)
  2461. typedef typename IA::value_type size_type;
  2462. // size_type for the data arrays.
  2463. typedef typename IA::size_type array_size_type;
  2464. // FIXME difference type for sparse storage iterators should it be in the container?
  2465. typedef typename IA::difference_type difference_type;
  2466. typedef T value_type;
  2467. typedef const T &const_reference;
  2468. #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
  2469. typedef T &reference;
  2470. #else
  2471. typedef sparse_matrix_element<self_type> reference;
  2472. #endif
  2473. typedef IA index_array_type;
  2474. typedef TA value_array_type;
  2475. typedef const matrix_reference<const self_type> const_closure_type;
  2476. typedef matrix_reference<self_type> closure_type;
  2477. typedef compressed_vector<T, IB, IA, TA> vector_temporary_type;
  2478. typedef self_type matrix_temporary_type;
  2479. typedef sparse_tag storage_category;
  2480. typedef typename L::orientation_category orientation_category;
  2481. // Construction and destruction
  2482. BOOST_UBLAS_INLINE
  2483. compressed_matrix ():
  2484. matrix_container<self_type> (),
  2485. size1_ (0), size2_ (0), capacity_ (restrict_capacity (0)),
  2486. filled1_ (1), filled2_ (0),
  2487. index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) {
  2488. index1_data_ [filled1_ - 1] = k_based (filled2_);
  2489. storage_invariants ();
  2490. }
  2491. BOOST_UBLAS_INLINE
  2492. compressed_matrix (size_type size1, size_type size2, size_type non_zeros = 0):
  2493. matrix_container<self_type> (),
  2494. size1_ (size1), size2_ (size2), capacity_ (restrict_capacity (non_zeros)),
  2495. filled1_ (1), filled2_ (0),
  2496. index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) {
  2497. index1_data_ [filled1_ - 1] = k_based (filled2_);
  2498. storage_invariants ();
  2499. }
  2500. BOOST_UBLAS_INLINE
  2501. compressed_matrix (const compressed_matrix &m):
  2502. matrix_container<self_type> (),
  2503. size1_ (m.size1_), size2_ (m.size2_), capacity_ (m.capacity_),
  2504. filled1_ (m.filled1_), filled2_ (m.filled2_),
  2505. index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) {
  2506. storage_invariants ();
  2507. }
  2508. BOOST_UBLAS_INLINE
  2509. compressed_matrix (const coordinate_matrix<T, L, IB, IA, TA> &m):
  2510. matrix_container<self_type> (),
  2511. size1_ (m.size1()), size2_ (m.size2()),
  2512. index1_data_ (layout_type::size_M (size1_, size2_) + 1)
  2513. {
  2514. m.sort();
  2515. reserve(m.nnz(), false);
  2516. filled2_ = m.nnz();
  2517. const_subiterator_type i_start = m.index1_data().begin();
  2518. const_subiterator_type i_end = (i_start + filled2_);
  2519. const_subiterator_type i = i_start;
  2520. size_type r = 1;
  2521. for (; (r < layout_type::size_M (size1_, size2_)) && (i != i_end); ++r) {
  2522. i = std::lower_bound(i, i_end, r);
  2523. index1_data_[r] = k_based( i - i_start );
  2524. }
  2525. filled1_ = r + 1;
  2526. std::copy( m.index2_data().begin(), m.index2_data().begin() + filled2_, index2_data_.begin());
  2527. std::copy( m.value_data().begin(), m.value_data().begin() + filled2_, value_data_.begin());
  2528. index1_data_ [filled1_ - 1] = k_based(filled2_);
  2529. storage_invariants ();
  2530. }
  2531. template<class AE>
  2532. BOOST_UBLAS_INLINE
  2533. compressed_matrix (const matrix_expression<AE> &ae, size_type non_zeros = 0):
  2534. matrix_container<self_type> (),
  2535. size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), capacity_ (restrict_capacity (non_zeros)),
  2536. filled1_ (1), filled2_ (0),
  2537. index1_data_ (layout_type::size_M (ae ().size1 (), ae ().size2 ()) + 1),
  2538. index2_data_ (capacity_), value_data_ (capacity_) {
  2539. index1_data_ [filled1_ - 1] = k_based (filled2_);
  2540. storage_invariants ();
  2541. matrix_assign<scalar_assign> (*this, ae);
  2542. }
  2543. // Accessors
  2544. BOOST_UBLAS_INLINE
  2545. size_type size1 () const {
  2546. return size1_;
  2547. }
  2548. BOOST_UBLAS_INLINE
  2549. size_type size2 () const {
  2550. return size2_;
  2551. }
  2552. BOOST_UBLAS_INLINE
  2553. size_type nnz_capacity () const {
  2554. return capacity_;
  2555. }
  2556. BOOST_UBLAS_INLINE
  2557. size_type nnz () const {
  2558. return filled2_;
  2559. }
  2560. // Storage accessors
  2561. BOOST_UBLAS_INLINE
  2562. static size_type index_base () {
  2563. return IB;
  2564. }
  2565. BOOST_UBLAS_INLINE
  2566. array_size_type filled1 () const {
  2567. return filled1_;
  2568. }
  2569. BOOST_UBLAS_INLINE
  2570. array_size_type filled2 () const {
  2571. return filled2_;
  2572. }
  2573. BOOST_UBLAS_INLINE
  2574. const index_array_type &index1_data () const {
  2575. return index1_data_;
  2576. }
  2577. BOOST_UBLAS_INLINE
  2578. const index_array_type &index2_data () const {
  2579. return index2_data_;
  2580. }
  2581. BOOST_UBLAS_INLINE
  2582. const value_array_type &value_data () const {
  2583. return value_data_;
  2584. }
  2585. BOOST_UBLAS_INLINE
  2586. void set_filled (const array_size_type& filled1, const array_size_type& filled2) {
  2587. filled1_ = filled1;
  2588. filled2_ = filled2;
  2589. storage_invariants ();
  2590. }
  2591. BOOST_UBLAS_INLINE
  2592. index_array_type &index1_data () {
  2593. return index1_data_;
  2594. }
  2595. BOOST_UBLAS_INLINE
  2596. index_array_type &index2_data () {
  2597. return index2_data_;
  2598. }
  2599. BOOST_UBLAS_INLINE
  2600. value_array_type &value_data () {
  2601. return value_data_;
  2602. }
  2603. BOOST_UBLAS_INLINE
  2604. void complete_index1_data () {
  2605. while (filled1_ <= layout_type::size_M (size1_, size2_)) {
  2606. this->index1_data_ [filled1_] = k_based (filled2_);
  2607. ++ this->filled1_;
  2608. }
  2609. }
  2610. // Resizing
  2611. private:
  2612. BOOST_UBLAS_INLINE
  2613. size_type restrict_capacity (size_type non_zeros) const {
  2614. non_zeros = (std::max) (non_zeros, (std::min) (size1_, size2_));
  2615. // Guarding against overflow - Thanks to Alexei Novakov for the hint.
  2616. // non_zeros = (std::min) (non_zeros, size1_ * size2_);
  2617. if (size1_ > 0 && non_zeros / size1_ >= size2_)
  2618. non_zeros = size1_ * size2_;
  2619. return non_zeros;
  2620. }
  2621. public:
  2622. BOOST_UBLAS_INLINE
  2623. void resize (size_type size1, size_type size2, bool preserve = true) {
  2624. // FIXME preserve unimplemented
  2625. BOOST_UBLAS_CHECK (!preserve, internal_logic ());
  2626. size1_ = size1;
  2627. size2_ = size2;
  2628. capacity_ = restrict_capacity (capacity_);
  2629. filled1_ = 1;
  2630. filled2_ = 0;
  2631. index1_data_.resize (layout_type::size_M (size1_, size2_) + 1);
  2632. index2_data_.resize (capacity_);
  2633. value_data_.resize (capacity_);
  2634. index1_data_ [filled1_ - 1] = k_based (filled2_);
  2635. storage_invariants ();
  2636. }
  2637. // Reserving
  2638. BOOST_UBLAS_INLINE
  2639. void reserve (size_type non_zeros, bool preserve = true) {
  2640. capacity_ = restrict_capacity (non_zeros);
  2641. if (preserve) {
  2642. index2_data_.resize (capacity_, size_type ());
  2643. value_data_.resize (capacity_, value_type ());
  2644. filled2_ = (std::min) (capacity_, filled2_);
  2645. }
  2646. else {
  2647. index2_data_.resize (capacity_);
  2648. value_data_.resize (capacity_);
  2649. filled1_ = 1;
  2650. filled2_ = 0;
  2651. index1_data_ [filled1_ - 1] = k_based (filled2_);
  2652. }
  2653. storage_invariants ();
  2654. }
  2655. // Element support
  2656. BOOST_UBLAS_INLINE
  2657. pointer find_element (size_type i, size_type j) {
  2658. return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
  2659. }
  2660. BOOST_UBLAS_INLINE
  2661. const_pointer find_element (size_type i, size_type j) const {
  2662. size_type element1 (layout_type::index_M (i, j));
  2663. size_type element2 (layout_type::index_m (i, j));
  2664. if (filled1_ <= element1 + 1)
  2665. return 0;
  2666. vector_const_subiterator_type itv (index1_data_.begin () + element1);
  2667. const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
  2668. const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
  2669. const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
  2670. if (it == it_end || *it != k_based (element2))
  2671. return 0;
  2672. return &value_data_ [it - index2_data_.begin ()];
  2673. }
  2674. // Element access
  2675. BOOST_UBLAS_INLINE
  2676. const_reference operator () (size_type i, size_type j) const {
  2677. const_pointer p = find_element (i, j);
  2678. if (p)
  2679. return *p;
  2680. else
  2681. return zero_;
  2682. }
  2683. BOOST_UBLAS_INLINE
  2684. reference operator () (size_type i, size_type j) {
  2685. #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
  2686. size_type element1 (layout_type::index_M (i, j));
  2687. size_type element2 (layout_type::index_m (i, j));
  2688. if (filled1_ <= element1 + 1)
  2689. return insert_element (i, j, value_type/*zero*/());
  2690. pointer p = find_element (i, j);
  2691. if (p)
  2692. return *p;
  2693. else
  2694. return insert_element (i, j, value_type/*zero*/());
  2695. #else
  2696. return reference (*this, i, j);
  2697. #endif
  2698. }
  2699. // Element assignment
  2700. BOOST_UBLAS_INLINE
  2701. true_reference insert_element (size_type i, size_type j, const_reference t) {
  2702. BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
  2703. if (filled2_ >= capacity_)
  2704. reserve (2 * filled2_, true);
  2705. BOOST_UBLAS_CHECK (filled2_ < capacity_, internal_logic ());
  2706. size_type element1 = layout_type::index_M (i, j);
  2707. size_type element2 = layout_type::index_m (i, j);
  2708. while (filled1_ <= element1 + 1) {
  2709. index1_data_ [filled1_] = k_based (filled2_);
  2710. ++ filled1_;
  2711. }
  2712. vector_subiterator_type itv (index1_data_.begin () + element1);
  2713. subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
  2714. subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
  2715. subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
  2716. typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
  2717. BOOST_UBLAS_CHECK (it == it_end || *it != k_based (element2), internal_logic ()); // duplicate bound by lower_bound
  2718. ++ filled2_;
  2719. it = index2_data_.begin () + n;
  2720. std::copy_backward (it, index2_data_.begin () + filled2_ - 1, index2_data_.begin () + filled2_);
  2721. *it = k_based (element2);
  2722. typename value_array_type::iterator itt (value_data_.begin () + n);
  2723. std::copy_backward (itt, value_data_.begin () + filled2_ - 1, value_data_.begin () + filled2_);
  2724. *itt = t;
  2725. while (element1 + 1 < filled1_) {
  2726. ++ index1_data_ [element1 + 1];
  2727. ++ element1;
  2728. }
  2729. storage_invariants ();
  2730. return *itt;
  2731. }
  2732. BOOST_UBLAS_INLINE
  2733. void erase_element (size_type i, size_type j) {
  2734. size_type element1 = layout_type::index_M (i, j);
  2735. size_type element2 = layout_type::index_m (i, j);
  2736. if (element1 + 1 >= filled1_)
  2737. return;
  2738. vector_subiterator_type itv (index1_data_.begin () + element1);
  2739. subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
  2740. subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
  2741. subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
  2742. if (it != it_end && *it == k_based (element2)) {
  2743. typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
  2744. std::copy (it + 1, index2_data_.begin () + filled2_, it);
  2745. typename value_array_type::iterator itt (value_data_.begin () + n);
  2746. std::copy (itt + 1, value_data_.begin () + filled2_, itt);
  2747. -- filled2_;
  2748. while (index1_data_ [filled1_ - 2] > k_based (filled2_)) {
  2749. index1_data_ [filled1_ - 1] = 0;
  2750. -- filled1_;
  2751. }
  2752. while (element1 + 1 < filled1_) {
  2753. -- index1_data_ [element1 + 1];
  2754. ++ element1;
  2755. }
  2756. }
  2757. storage_invariants ();
  2758. }
  2759. // Zeroing
  2760. BOOST_UBLAS_INLINE
  2761. void clear () {
  2762. filled1_ = 1;
  2763. filled2_ = 0;
  2764. index1_data_ [filled1_ - 1] = k_based (filled2_);
  2765. storage_invariants ();
  2766. }
  2767. // Assignment
  2768. BOOST_UBLAS_INLINE
  2769. compressed_matrix &operator = (const compressed_matrix &m) {
  2770. if (this != &m) {
  2771. size1_ = m.size1_;
  2772. size2_ = m.size2_;
  2773. capacity_ = m.capacity_;
  2774. filled1_ = m.filled1_;
  2775. filled2_ = m.filled2_;
  2776. index1_data_ = m.index1_data_;
  2777. index2_data_ = m.index2_data_;
  2778. value_data_ = m.value_data_;
  2779. }
  2780. storage_invariants ();
  2781. return *this;
  2782. }
  2783. template<class C> // Container assignment without temporary
  2784. BOOST_UBLAS_INLINE
  2785. compressed_matrix &operator = (const matrix_container<C> &m) {
  2786. resize (m ().size1 (), m ().size2 (), false);
  2787. assign (m);
  2788. return *this;
  2789. }
  2790. BOOST_UBLAS_INLINE
  2791. compressed_matrix &assign_temporary (compressed_matrix &m) {
  2792. swap (m);
  2793. return *this;
  2794. }
  2795. template<class AE>
  2796. BOOST_UBLAS_INLINE
  2797. compressed_matrix &operator = (const matrix_expression<AE> &ae) {
  2798. self_type temporary (ae, capacity_);
  2799. return assign_temporary (temporary);
  2800. }
  2801. template<class AE>
  2802. BOOST_UBLAS_INLINE
  2803. compressed_matrix &assign (const matrix_expression<AE> &ae) {
  2804. matrix_assign<scalar_assign> (*this, ae);
  2805. return *this;
  2806. }
  2807. template<class AE>
  2808. BOOST_UBLAS_INLINE
  2809. compressed_matrix& operator += (const matrix_expression<AE> &ae) {
  2810. self_type temporary (*this + ae, capacity_);
  2811. return assign_temporary (temporary);
  2812. }
  2813. template<class C> // Container assignment without temporary
  2814. BOOST_UBLAS_INLINE
  2815. compressed_matrix &operator += (const matrix_container<C> &m) {
  2816. plus_assign (m);
  2817. return *this;
  2818. }
  2819. template<class AE>
  2820. BOOST_UBLAS_INLINE
  2821. compressed_matrix &plus_assign (const matrix_expression<AE> &ae) {
  2822. matrix_assign<scalar_plus_assign> (*this, ae);
  2823. return *this;
  2824. }
  2825. template<class AE>
  2826. BOOST_UBLAS_INLINE
  2827. compressed_matrix& operator -= (const matrix_expression<AE> &ae) {
  2828. self_type temporary (*this - ae, capacity_);
  2829. return assign_temporary (temporary);
  2830. }
  2831. template<class C> // Container assignment without temporary
  2832. BOOST_UBLAS_INLINE
  2833. compressed_matrix &operator -= (const matrix_container<C> &m) {
  2834. minus_assign (m);
  2835. return *this;
  2836. }
  2837. template<class AE>
  2838. BOOST_UBLAS_INLINE
  2839. compressed_matrix &minus_assign (const matrix_expression<AE> &ae) {
  2840. matrix_assign<scalar_minus_assign> (*this, ae);
  2841. return *this;
  2842. }
  2843. template<class AT>
  2844. BOOST_UBLAS_INLINE
  2845. compressed_matrix& operator *= (const AT &at) {
  2846. matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  2847. return *this;
  2848. }
  2849. template<class AT>
  2850. BOOST_UBLAS_INLINE
  2851. compressed_matrix& operator /= (const AT &at) {
  2852. matrix_assign_scalar<scalar_divides_assign> (*this, at);
  2853. return *this;
  2854. }
  2855. // Swapping
  2856. BOOST_UBLAS_INLINE
  2857. void swap (compressed_matrix &m) {
  2858. if (this != &m) {
  2859. std::swap (size1_, m.size1_);
  2860. std::swap (size2_, m.size2_);
  2861. std::swap (capacity_, m.capacity_);
  2862. std::swap (filled1_, m.filled1_);
  2863. std::swap (filled2_, m.filled2_);
  2864. index1_data_.swap (m.index1_data_);
  2865. index2_data_.swap (m.index2_data_);
  2866. value_data_.swap (m.value_data_);
  2867. }
  2868. storage_invariants ();
  2869. }
  2870. BOOST_UBLAS_INLINE
  2871. friend void swap (compressed_matrix &m1, compressed_matrix &m2) {
  2872. m1.swap (m2);
  2873. }
  2874. // Back element insertion and erasure
  2875. BOOST_UBLAS_INLINE
  2876. void push_back (size_type i, size_type j, const_reference t) {
  2877. if (filled2_ >= capacity_)
  2878. reserve (2 * filled2_, true);
  2879. BOOST_UBLAS_CHECK (filled2_ < capacity_, internal_logic ());
  2880. size_type element1 = layout_type::index_M (i, j);
  2881. size_type element2 = layout_type::index_m (i, j);
  2882. while (filled1_ < element1 + 2) {
  2883. index1_data_ [filled1_] = k_based (filled2_);
  2884. ++ filled1_;
  2885. }
  2886. // must maintain sort order
  2887. BOOST_UBLAS_CHECK ((filled1_ == element1 + 2 &&
  2888. (filled2_ == zero_based (index1_data_ [filled1_ - 2]) ||
  2889. index2_data_ [filled2_ - 1] < k_based (element2))), external_logic ());
  2890. ++ filled2_;
  2891. index1_data_ [filled1_ - 1] = k_based (filled2_);
  2892. index2_data_ [filled2_ - 1] = k_based (element2);
  2893. value_data_ [filled2_ - 1] = t;
  2894. storage_invariants ();
  2895. }
  2896. BOOST_UBLAS_INLINE
  2897. void pop_back () {
  2898. BOOST_UBLAS_CHECK (filled1_ > 0 && filled2_ > 0, external_logic ());
  2899. -- filled2_;
  2900. while (index1_data_ [filled1_ - 2] > k_based (filled2_)) {
  2901. index1_data_ [filled1_ - 1] = 0;
  2902. -- filled1_;
  2903. }
  2904. -- index1_data_ [filled1_ - 1];
  2905. storage_invariants ();
  2906. }
  2907. // Iterator types
  2908. private:
  2909. // Use index array iterator
  2910. typedef typename IA::const_iterator vector_const_subiterator_type;
  2911. typedef typename IA::iterator vector_subiterator_type;
  2912. typedef typename IA::const_iterator const_subiterator_type;
  2913. typedef typename IA::iterator subiterator_type;
  2914. BOOST_UBLAS_INLINE
  2915. true_reference at_element (size_type i, size_type j) {
  2916. pointer p = find_element (i, j);
  2917. BOOST_UBLAS_CHECK (p, bad_index ());
  2918. return *p;
  2919. }
  2920. public:
  2921. class const_iterator1;
  2922. class iterator1;
  2923. class const_iterator2;
  2924. class iterator2;
  2925. typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  2926. typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  2927. typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  2928. typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  2929. // Element lookup
  2930. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  2931. const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
  2932. for (;;) {
  2933. array_size_type address1 (layout_type::index_M (i, j));
  2934. array_size_type address2 (layout_type::index_m (i, j));
  2935. vector_const_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
  2936. if (filled1_ <= address1 + 1)
  2937. return const_iterator1 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
  2938. const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
  2939. const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
  2940. const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
  2941. if (rank == 0)
  2942. return const_iterator1 (*this, rank, i, j, itv, it);
  2943. if (it != it_end && zero_based (*it) == address2)
  2944. return const_iterator1 (*this, rank, i, j, itv, it);
  2945. if (direction > 0) {
  2946. if (layout_type::fast_i ()) {
  2947. if (it == it_end)
  2948. return const_iterator1 (*this, rank, i, j, itv, it);
  2949. i = zero_based (*it);
  2950. } else {
  2951. if (i >= size1_)
  2952. return const_iterator1 (*this, rank, i, j, itv, it);
  2953. ++ i;
  2954. }
  2955. } else /* if (direction < 0) */ {
  2956. if (layout_type::fast_i ()) {
  2957. if (it == index2_data_.begin () + zero_based (*itv))
  2958. return const_iterator1 (*this, rank, i, j, itv, it);
  2959. i = zero_based (*(it - 1));
  2960. } else {
  2961. if (i == 0)
  2962. return const_iterator1 (*this, rank, i, j, itv, it);
  2963. -- i;
  2964. }
  2965. }
  2966. }
  2967. }
  2968. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  2969. iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
  2970. for (;;) {
  2971. array_size_type address1 (layout_type::index_M (i, j));
  2972. array_size_type address2 (layout_type::index_m (i, j));
  2973. vector_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
  2974. if (filled1_ <= address1 + 1)
  2975. return iterator1 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
  2976. subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
  2977. subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
  2978. subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
  2979. if (rank == 0)
  2980. return iterator1 (*this, rank, i, j, itv, it);
  2981. if (it != it_end && zero_based (*it) == address2)
  2982. return iterator1 (*this, rank, i, j, itv, it);
  2983. if (direction > 0) {
  2984. if (layout_type::fast_i ()) {
  2985. if (it == it_end)
  2986. return iterator1 (*this, rank, i, j, itv, it);
  2987. i = zero_based (*it);
  2988. } else {
  2989. if (i >= size1_)
  2990. return iterator1 (*this, rank, i, j, itv, it);
  2991. ++ i;
  2992. }
  2993. } else /* if (direction < 0) */ {
  2994. if (layout_type::fast_i ()) {
  2995. if (it == index2_data_.begin () + zero_based (*itv))
  2996. return iterator1 (*this, rank, i, j, itv, it);
  2997. i = zero_based (*(it - 1));
  2998. } else {
  2999. if (i == 0)
  3000. return iterator1 (*this, rank, i, j, itv, it);
  3001. -- i;
  3002. }
  3003. }
  3004. }
  3005. }
  3006. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  3007. const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
  3008. for (;;) {
  3009. array_size_type address1 (layout_type::index_M (i, j));
  3010. array_size_type address2 (layout_type::index_m (i, j));
  3011. vector_const_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
  3012. if (filled1_ <= address1 + 1)
  3013. return const_iterator2 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
  3014. const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
  3015. const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
  3016. const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
  3017. if (rank == 0)
  3018. return const_iterator2 (*this, rank, i, j, itv, it);
  3019. if (it != it_end && zero_based (*it) == address2)
  3020. return const_iterator2 (*this, rank, i, j, itv, it);
  3021. if (direction > 0) {
  3022. if (layout_type::fast_j ()) {
  3023. if (it == it_end)
  3024. return const_iterator2 (*this, rank, i, j, itv, it);
  3025. j = zero_based (*it);
  3026. } else {
  3027. if (j >= size2_)
  3028. return const_iterator2 (*this, rank, i, j, itv, it);
  3029. ++ j;
  3030. }
  3031. } else /* if (direction < 0) */ {
  3032. if (layout_type::fast_j ()) {
  3033. if (it == index2_data_.begin () + zero_based (*itv))
  3034. return const_iterator2 (*this, rank, i, j, itv, it);
  3035. j = zero_based (*(it - 1));
  3036. } else {
  3037. if (j == 0)
  3038. return const_iterator2 (*this, rank, i, j, itv, it);
  3039. -- j;
  3040. }
  3041. }
  3042. }
  3043. }
  3044. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  3045. iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
  3046. for (;;) {
  3047. array_size_type address1 (layout_type::index_M (i, j));
  3048. array_size_type address2 (layout_type::index_m (i, j));
  3049. vector_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
  3050. if (filled1_ <= address1 + 1)
  3051. return iterator2 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
  3052. subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
  3053. subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
  3054. subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
  3055. if (rank == 0)
  3056. return iterator2 (*this, rank, i, j, itv, it);
  3057. if (it != it_end && zero_based (*it) == address2)
  3058. return iterator2 (*this, rank, i, j, itv, it);
  3059. if (direction > 0) {
  3060. if (layout_type::fast_j ()) {
  3061. if (it == it_end)
  3062. return iterator2 (*this, rank, i, j, itv, it);
  3063. j = zero_based (*it);
  3064. } else {
  3065. if (j >= size2_)
  3066. return iterator2 (*this, rank, i, j, itv, it);
  3067. ++ j;
  3068. }
  3069. } else /* if (direction < 0) */ {
  3070. if (layout_type::fast_j ()) {
  3071. if (it == index2_data_.begin () + zero_based (*itv))
  3072. return iterator2 (*this, rank, i, j, itv, it);
  3073. j = zero_based (*(it - 1));
  3074. } else {
  3075. if (j == 0)
  3076. return iterator2 (*this, rank, i, j, itv, it);
  3077. -- j;
  3078. }
  3079. }
  3080. }
  3081. }
  3082. class const_iterator1:
  3083. public container_const_reference<compressed_matrix>,
  3084. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  3085. const_iterator1, value_type> {
  3086. public:
  3087. typedef typename compressed_matrix::value_type value_type;
  3088. typedef typename compressed_matrix::difference_type difference_type;
  3089. typedef typename compressed_matrix::const_reference reference;
  3090. typedef const typename compressed_matrix::pointer pointer;
  3091. typedef const_iterator2 dual_iterator_type;
  3092. typedef const_reverse_iterator2 dual_reverse_iterator_type;
  3093. // Construction and destruction
  3094. BOOST_UBLAS_INLINE
  3095. const_iterator1 ():
  3096. container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  3097. BOOST_UBLAS_INLINE
  3098. const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
  3099. container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  3100. BOOST_UBLAS_INLINE
  3101. const_iterator1 (const iterator1 &it):
  3102. container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
  3103. // Arithmetic
  3104. BOOST_UBLAS_INLINE
  3105. const_iterator1 &operator ++ () {
  3106. if (rank_ == 1 && layout_type::fast_i ())
  3107. ++ it_;
  3108. else {
  3109. i_ = index1 () + 1;
  3110. if (rank_ == 1)
  3111. *this = (*this) ().find1 (rank_, i_, j_, 1);
  3112. }
  3113. return *this;
  3114. }
  3115. BOOST_UBLAS_INLINE
  3116. const_iterator1 &operator -- () {
  3117. if (rank_ == 1 && layout_type::fast_i ())
  3118. -- it_;
  3119. else {
  3120. --i_;
  3121. if (rank_ == 1)
  3122. *this = (*this) ().find1 (rank_, i_, j_, -1);
  3123. }
  3124. return *this;
  3125. }
  3126. // Dereference
  3127. BOOST_UBLAS_INLINE
  3128. const_reference operator * () const {
  3129. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  3130. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  3131. if (rank_ == 1) {
  3132. return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
  3133. } else {
  3134. return (*this) () (i_, j_);
  3135. }
  3136. }
  3137. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  3138. BOOST_UBLAS_INLINE
  3139. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3140. typename self_type::
  3141. #endif
  3142. const_iterator2 begin () const {
  3143. const self_type &m = (*this) ();
  3144. return m.find2 (1, index1 (), 0);
  3145. }
  3146. BOOST_UBLAS_INLINE
  3147. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3148. typename self_type::
  3149. #endif
  3150. const_iterator2 end () const {
  3151. const self_type &m = (*this) ();
  3152. return m.find2 (1, index1 (), m.size2 ());
  3153. }
  3154. BOOST_UBLAS_INLINE
  3155. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3156. typename self_type::
  3157. #endif
  3158. const_reverse_iterator2 rbegin () const {
  3159. return const_reverse_iterator2 (end ());
  3160. }
  3161. BOOST_UBLAS_INLINE
  3162. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3163. typename self_type::
  3164. #endif
  3165. const_reverse_iterator2 rend () const {
  3166. return const_reverse_iterator2 (begin ());
  3167. }
  3168. #endif
  3169. // Indices
  3170. BOOST_UBLAS_INLINE
  3171. size_type index1 () const {
  3172. BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
  3173. if (rank_ == 1) {
  3174. BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
  3175. return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
  3176. } else {
  3177. return i_;
  3178. }
  3179. }
  3180. BOOST_UBLAS_INLINE
  3181. size_type index2 () const {
  3182. if (rank_ == 1) {
  3183. BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
  3184. return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
  3185. } else {
  3186. return j_;
  3187. }
  3188. }
  3189. // Assignment
  3190. BOOST_UBLAS_INLINE
  3191. const_iterator1 &operator = (const const_iterator1 &it) {
  3192. container_const_reference<self_type>::assign (&it ());
  3193. rank_ = it.rank_;
  3194. i_ = it.i_;
  3195. j_ = it.j_;
  3196. itv_ = it.itv_;
  3197. it_ = it.it_;
  3198. return *this;
  3199. }
  3200. // Comparison
  3201. BOOST_UBLAS_INLINE
  3202. bool operator == (const const_iterator1 &it) const {
  3203. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3204. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  3205. if (rank_ == 1 || it.rank_ == 1) {
  3206. return it_ == it.it_;
  3207. } else {
  3208. return i_ == it.i_ && j_ == it.j_;
  3209. }
  3210. }
  3211. private:
  3212. int rank_;
  3213. size_type i_;
  3214. size_type j_;
  3215. vector_const_subiterator_type itv_;
  3216. const_subiterator_type it_;
  3217. };
  3218. BOOST_UBLAS_INLINE
  3219. const_iterator1 begin1 () const {
  3220. return find1 (0, 0, 0);
  3221. }
  3222. BOOST_UBLAS_INLINE
  3223. const_iterator1 end1 () const {
  3224. return find1 (0, size1_, 0);
  3225. }
  3226. class iterator1:
  3227. public container_reference<compressed_matrix>,
  3228. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  3229. iterator1, value_type> {
  3230. public:
  3231. typedef typename compressed_matrix::value_type value_type;
  3232. typedef typename compressed_matrix::difference_type difference_type;
  3233. typedef typename compressed_matrix::true_reference reference;
  3234. typedef typename compressed_matrix::pointer pointer;
  3235. typedef iterator2 dual_iterator_type;
  3236. typedef reverse_iterator2 dual_reverse_iterator_type;
  3237. // Construction and destruction
  3238. BOOST_UBLAS_INLINE
  3239. iterator1 ():
  3240. container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  3241. BOOST_UBLAS_INLINE
  3242. iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
  3243. container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  3244. // Arithmetic
  3245. BOOST_UBLAS_INLINE
  3246. iterator1 &operator ++ () {
  3247. if (rank_ == 1 && layout_type::fast_i ())
  3248. ++ it_;
  3249. else {
  3250. i_ = index1 () + 1;
  3251. if (rank_ == 1)
  3252. *this = (*this) ().find1 (rank_, i_, j_, 1);
  3253. }
  3254. return *this;
  3255. }
  3256. BOOST_UBLAS_INLINE
  3257. iterator1 &operator -- () {
  3258. if (rank_ == 1 && layout_type::fast_i ())
  3259. -- it_;
  3260. else {
  3261. --i_;
  3262. if (rank_ == 1)
  3263. *this = (*this) ().find1 (rank_, i_, j_, -1);
  3264. }
  3265. return *this;
  3266. }
  3267. // Dereference
  3268. BOOST_UBLAS_INLINE
  3269. reference operator * () const {
  3270. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  3271. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  3272. if (rank_ == 1) {
  3273. return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
  3274. } else {
  3275. return (*this) ().at_element (i_, j_);
  3276. }
  3277. }
  3278. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  3279. BOOST_UBLAS_INLINE
  3280. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3281. typename self_type::
  3282. #endif
  3283. iterator2 begin () const {
  3284. self_type &m = (*this) ();
  3285. return m.find2 (1, index1 (), 0);
  3286. }
  3287. BOOST_UBLAS_INLINE
  3288. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3289. typename self_type::
  3290. #endif
  3291. iterator2 end () const {
  3292. self_type &m = (*this) ();
  3293. return m.find2 (1, index1 (), m.size2 ());
  3294. }
  3295. BOOST_UBLAS_INLINE
  3296. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3297. typename self_type::
  3298. #endif
  3299. reverse_iterator2 rbegin () const {
  3300. return reverse_iterator2 (end ());
  3301. }
  3302. BOOST_UBLAS_INLINE
  3303. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3304. typename self_type::
  3305. #endif
  3306. reverse_iterator2 rend () const {
  3307. return reverse_iterator2 (begin ());
  3308. }
  3309. #endif
  3310. // Indices
  3311. BOOST_UBLAS_INLINE
  3312. size_type index1 () const {
  3313. BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
  3314. if (rank_ == 1) {
  3315. BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
  3316. return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
  3317. } else {
  3318. return i_;
  3319. }
  3320. }
  3321. BOOST_UBLAS_INLINE
  3322. size_type index2 () const {
  3323. if (rank_ == 1) {
  3324. BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
  3325. return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
  3326. } else {
  3327. return j_;
  3328. }
  3329. }
  3330. // Assignment
  3331. BOOST_UBLAS_INLINE
  3332. iterator1 &operator = (const iterator1 &it) {
  3333. container_reference<self_type>::assign (&it ());
  3334. rank_ = it.rank_;
  3335. i_ = it.i_;
  3336. j_ = it.j_;
  3337. itv_ = it.itv_;
  3338. it_ = it.it_;
  3339. return *this;
  3340. }
  3341. // Comparison
  3342. BOOST_UBLAS_INLINE
  3343. bool operator == (const iterator1 &it) const {
  3344. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3345. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  3346. if (rank_ == 1 || it.rank_ == 1) {
  3347. return it_ == it.it_;
  3348. } else {
  3349. return i_ == it.i_ && j_ == it.j_;
  3350. }
  3351. }
  3352. private:
  3353. int rank_;
  3354. size_type i_;
  3355. size_type j_;
  3356. vector_subiterator_type itv_;
  3357. subiterator_type it_;
  3358. friend class const_iterator1;
  3359. };
  3360. BOOST_UBLAS_INLINE
  3361. iterator1 begin1 () {
  3362. return find1 (0, 0, 0);
  3363. }
  3364. BOOST_UBLAS_INLINE
  3365. iterator1 end1 () {
  3366. return find1 (0, size1_, 0);
  3367. }
  3368. class const_iterator2:
  3369. public container_const_reference<compressed_matrix>,
  3370. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  3371. const_iterator2, value_type> {
  3372. public:
  3373. typedef typename compressed_matrix::value_type value_type;
  3374. typedef typename compressed_matrix::difference_type difference_type;
  3375. typedef typename compressed_matrix::const_reference reference;
  3376. typedef const typename compressed_matrix::pointer pointer;
  3377. typedef const_iterator1 dual_iterator_type;
  3378. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  3379. // Construction and destruction
  3380. BOOST_UBLAS_INLINE
  3381. const_iterator2 ():
  3382. container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  3383. BOOST_UBLAS_INLINE
  3384. const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type itv, const const_subiterator_type &it):
  3385. container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  3386. BOOST_UBLAS_INLINE
  3387. const_iterator2 (const iterator2 &it):
  3388. container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
  3389. // Arithmetic
  3390. BOOST_UBLAS_INLINE
  3391. const_iterator2 &operator ++ () {
  3392. if (rank_ == 1 && layout_type::fast_j ())
  3393. ++ it_;
  3394. else {
  3395. j_ = index2 () + 1;
  3396. if (rank_ == 1)
  3397. *this = (*this) ().find2 (rank_, i_, j_, 1);
  3398. }
  3399. return *this;
  3400. }
  3401. BOOST_UBLAS_INLINE
  3402. const_iterator2 &operator -- () {
  3403. if (rank_ == 1 && layout_type::fast_j ())
  3404. -- it_;
  3405. else {
  3406. --j_;
  3407. if (rank_ == 1)
  3408. *this = (*this) ().find2 (rank_, i_, j_, -1);
  3409. }
  3410. return *this;
  3411. }
  3412. // Dereference
  3413. BOOST_UBLAS_INLINE
  3414. const_reference operator * () const {
  3415. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  3416. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  3417. if (rank_ == 1) {
  3418. return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
  3419. } else {
  3420. return (*this) () (i_, j_);
  3421. }
  3422. }
  3423. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  3424. BOOST_UBLAS_INLINE
  3425. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3426. typename self_type::
  3427. #endif
  3428. const_iterator1 begin () const {
  3429. const self_type &m = (*this) ();
  3430. return m.find1 (1, 0, index2 ());
  3431. }
  3432. BOOST_UBLAS_INLINE
  3433. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3434. typename self_type::
  3435. #endif
  3436. const_iterator1 end () const {
  3437. const self_type &m = (*this) ();
  3438. return m.find1 (1, m.size1 (), index2 ());
  3439. }
  3440. BOOST_UBLAS_INLINE
  3441. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3442. typename self_type::
  3443. #endif
  3444. const_reverse_iterator1 rbegin () const {
  3445. return const_reverse_iterator1 (end ());
  3446. }
  3447. BOOST_UBLAS_INLINE
  3448. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3449. typename self_type::
  3450. #endif
  3451. const_reverse_iterator1 rend () const {
  3452. return const_reverse_iterator1 (begin ());
  3453. }
  3454. #endif
  3455. // Indices
  3456. BOOST_UBLAS_INLINE
  3457. size_type index1 () const {
  3458. if (rank_ == 1) {
  3459. BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
  3460. return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
  3461. } else {
  3462. return i_;
  3463. }
  3464. }
  3465. BOOST_UBLAS_INLINE
  3466. size_type index2 () const {
  3467. BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
  3468. if (rank_ == 1) {
  3469. BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
  3470. return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
  3471. } else {
  3472. return j_;
  3473. }
  3474. }
  3475. // Assignment
  3476. BOOST_UBLAS_INLINE
  3477. const_iterator2 &operator = (const const_iterator2 &it) {
  3478. container_const_reference<self_type>::assign (&it ());
  3479. rank_ = it.rank_;
  3480. i_ = it.i_;
  3481. j_ = it.j_;
  3482. itv_ = it.itv_;
  3483. it_ = it.it_;
  3484. return *this;
  3485. }
  3486. // Comparison
  3487. BOOST_UBLAS_INLINE
  3488. bool operator == (const const_iterator2 &it) const {
  3489. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3490. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  3491. if (rank_ == 1 || it.rank_ == 1) {
  3492. return it_ == it.it_;
  3493. } else {
  3494. return i_ == it.i_ && j_ == it.j_;
  3495. }
  3496. }
  3497. private:
  3498. int rank_;
  3499. size_type i_;
  3500. size_type j_;
  3501. vector_const_subiterator_type itv_;
  3502. const_subiterator_type it_;
  3503. };
  3504. BOOST_UBLAS_INLINE
  3505. const_iterator2 begin2 () const {
  3506. return find2 (0, 0, 0);
  3507. }
  3508. BOOST_UBLAS_INLINE
  3509. const_iterator2 end2 () const {
  3510. return find2 (0, 0, size2_);
  3511. }
  3512. class iterator2:
  3513. public container_reference<compressed_matrix>,
  3514. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  3515. iterator2, value_type> {
  3516. public:
  3517. typedef typename compressed_matrix::value_type value_type;
  3518. typedef typename compressed_matrix::difference_type difference_type;
  3519. typedef typename compressed_matrix::true_reference reference;
  3520. typedef typename compressed_matrix::pointer pointer;
  3521. typedef iterator1 dual_iterator_type;
  3522. typedef reverse_iterator1 dual_reverse_iterator_type;
  3523. // Construction and destruction
  3524. BOOST_UBLAS_INLINE
  3525. iterator2 ():
  3526. container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  3527. BOOST_UBLAS_INLINE
  3528. iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
  3529. container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  3530. // Arithmetic
  3531. BOOST_UBLAS_INLINE
  3532. iterator2 &operator ++ () {
  3533. if (rank_ == 1 && layout_type::fast_j ())
  3534. ++ it_;
  3535. else {
  3536. j_ = index2 () + 1;
  3537. if (rank_ == 1)
  3538. *this = (*this) ().find2 (rank_, i_, j_, 1);
  3539. }
  3540. return *this;
  3541. }
  3542. BOOST_UBLAS_INLINE
  3543. iterator2 &operator -- () {
  3544. if (rank_ == 1 && layout_type::fast_j ())
  3545. -- it_;
  3546. else {
  3547. --j_;
  3548. if (rank_ == 1)
  3549. *this = (*this) ().find2 (rank_, i_, j_, -1);
  3550. }
  3551. return *this;
  3552. }
  3553. // Dereference
  3554. BOOST_UBLAS_INLINE
  3555. reference operator * () const {
  3556. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  3557. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  3558. if (rank_ == 1) {
  3559. return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
  3560. } else {
  3561. return (*this) ().at_element (i_, j_);
  3562. }
  3563. }
  3564. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  3565. BOOST_UBLAS_INLINE
  3566. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3567. typename self_type::
  3568. #endif
  3569. iterator1 begin () const {
  3570. self_type &m = (*this) ();
  3571. return m.find1 (1, 0, index2 ());
  3572. }
  3573. BOOST_UBLAS_INLINE
  3574. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3575. typename self_type::
  3576. #endif
  3577. iterator1 end () const {
  3578. self_type &m = (*this) ();
  3579. return m.find1 (1, m.size1 (), index2 ());
  3580. }
  3581. BOOST_UBLAS_INLINE
  3582. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3583. typename self_type::
  3584. #endif
  3585. reverse_iterator1 rbegin () const {
  3586. return reverse_iterator1 (end ());
  3587. }
  3588. BOOST_UBLAS_INLINE
  3589. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3590. typename self_type::
  3591. #endif
  3592. reverse_iterator1 rend () const {
  3593. return reverse_iterator1 (begin ());
  3594. }
  3595. #endif
  3596. // Indices
  3597. BOOST_UBLAS_INLINE
  3598. size_type index1 () const {
  3599. if (rank_ == 1) {
  3600. BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
  3601. return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
  3602. } else {
  3603. return i_;
  3604. }
  3605. }
  3606. BOOST_UBLAS_INLINE
  3607. size_type index2 () const {
  3608. BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
  3609. if (rank_ == 1) {
  3610. BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
  3611. return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
  3612. } else {
  3613. return j_;
  3614. }
  3615. }
  3616. // Assignment
  3617. BOOST_UBLAS_INLINE
  3618. iterator2 &operator = (const iterator2 &it) {
  3619. container_reference<self_type>::assign (&it ());
  3620. rank_ = it.rank_;
  3621. i_ = it.i_;
  3622. j_ = it.j_;
  3623. itv_ = it.itv_;
  3624. it_ = it.it_;
  3625. return *this;
  3626. }
  3627. // Comparison
  3628. BOOST_UBLAS_INLINE
  3629. bool operator == (const iterator2 &it) const {
  3630. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3631. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  3632. if (rank_ == 1 || it.rank_ == 1) {
  3633. return it_ == it.it_;
  3634. } else {
  3635. return i_ == it.i_ && j_ == it.j_;
  3636. }
  3637. }
  3638. private:
  3639. int rank_;
  3640. size_type i_;
  3641. size_type j_;
  3642. vector_subiterator_type itv_;
  3643. subiterator_type it_;
  3644. friend class const_iterator2;
  3645. };
  3646. BOOST_UBLAS_INLINE
  3647. iterator2 begin2 () {
  3648. return find2 (0, 0, 0);
  3649. }
  3650. BOOST_UBLAS_INLINE
  3651. iterator2 end2 () {
  3652. return find2 (0, 0, size2_);
  3653. }
  3654. // Reverse iterators
  3655. BOOST_UBLAS_INLINE
  3656. const_reverse_iterator1 rbegin1 () const {
  3657. return const_reverse_iterator1 (end1 ());
  3658. }
  3659. BOOST_UBLAS_INLINE
  3660. const_reverse_iterator1 rend1 () const {
  3661. return const_reverse_iterator1 (begin1 ());
  3662. }
  3663. BOOST_UBLAS_INLINE
  3664. reverse_iterator1 rbegin1 () {
  3665. return reverse_iterator1 (end1 ());
  3666. }
  3667. BOOST_UBLAS_INLINE
  3668. reverse_iterator1 rend1 () {
  3669. return reverse_iterator1 (begin1 ());
  3670. }
  3671. BOOST_UBLAS_INLINE
  3672. const_reverse_iterator2 rbegin2 () const {
  3673. return const_reverse_iterator2 (end2 ());
  3674. }
  3675. BOOST_UBLAS_INLINE
  3676. const_reverse_iterator2 rend2 () const {
  3677. return const_reverse_iterator2 (begin2 ());
  3678. }
  3679. BOOST_UBLAS_INLINE
  3680. reverse_iterator2 rbegin2 () {
  3681. return reverse_iterator2 (end2 ());
  3682. }
  3683. BOOST_UBLAS_INLINE
  3684. reverse_iterator2 rend2 () {
  3685. return reverse_iterator2 (begin2 ());
  3686. }
  3687. // Serialization
  3688. template<class Archive>
  3689. void serialize(Archive & ar, const unsigned int /* file_version */){
  3690. serialization::collection_size_type s1 (size1_);
  3691. serialization::collection_size_type s2 (size2_);
  3692. ar & serialization::make_nvp("size1",s1);
  3693. ar & serialization::make_nvp("size2",s2);
  3694. if (Archive::is_loading::value) {
  3695. size1_ = s1;
  3696. size2_ = s2;
  3697. }
  3698. ar & serialization::make_nvp("capacity", capacity_);
  3699. ar & serialization::make_nvp("filled1", filled1_);
  3700. ar & serialization::make_nvp("filled2", filled2_);
  3701. ar & serialization::make_nvp("index1_data", index1_data_);
  3702. ar & serialization::make_nvp("index2_data", index2_data_);
  3703. ar & serialization::make_nvp("value_data", value_data_);
  3704. storage_invariants();
  3705. }
  3706. private:
  3707. void storage_invariants () const {
  3708. BOOST_UBLAS_CHECK (layout_type::size_M (size1_, size2_) + 1 == index1_data_.size (), internal_logic ());
  3709. BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
  3710. BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
  3711. BOOST_UBLAS_CHECK (filled1_ > 0 && filled1_ <= layout_type::size_M (size1_, size2_) + 1, internal_logic ());
  3712. BOOST_UBLAS_CHECK (filled2_ <= capacity_, internal_logic ());
  3713. BOOST_UBLAS_CHECK (index1_data_ [filled1_ - 1] == k_based (filled2_), internal_logic ());
  3714. }
  3715. size_type size1_;
  3716. size_type size2_;
  3717. array_size_type capacity_;
  3718. array_size_type filled1_;
  3719. array_size_type filled2_;
  3720. index_array_type index1_data_;
  3721. index_array_type index2_data_;
  3722. value_array_type value_data_;
  3723. static const value_type zero_;
  3724. BOOST_UBLAS_INLINE
  3725. static size_type zero_based (size_type k_based_index) {
  3726. return k_based_index - IB;
  3727. }
  3728. BOOST_UBLAS_INLINE
  3729. static size_type k_based (size_type zero_based_index) {
  3730. return zero_based_index + IB;
  3731. }
  3732. friend class iterator1;
  3733. friend class iterator2;
  3734. friend class const_iterator1;
  3735. friend class const_iterator2;
  3736. };
  3737. template<class T, class L, std::size_t IB, class IA, class TA>
  3738. const typename compressed_matrix<T, L, IB, IA, TA>::value_type compressed_matrix<T, L, IB, IA, TA>::zero_ = value_type/*zero*/();
  3739. // Coordinate array based sparse matrix class
  3740. // Thanks to Kresimir Fresl for extending this to cover different index bases.
  3741. template<class T, class L, std::size_t IB, class IA, class TA>
  3742. class coordinate_matrix:
  3743. public matrix_container<coordinate_matrix<T, L, IB, IA, TA> > {
  3744. typedef T &true_reference;
  3745. typedef T *pointer;
  3746. typedef const T *const_pointer;
  3747. typedef L layout_type;
  3748. typedef coordinate_matrix<T, L, IB, IA, TA> self_type;
  3749. public:
  3750. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  3751. using matrix_container<self_type>::operator ();
  3752. #endif
  3753. // ISSUE require type consistency check, is_convertable (IA::size_type, TA::size_type)
  3754. typedef typename IA::value_type size_type;
  3755. // ISSUE difference_type cannot be deduced for sparse indices, we only know the value_type
  3756. typedef std::ptrdiff_t difference_type;
  3757. // size_type for the data arrays.
  3758. typedef typename IA::size_type array_size_type;
  3759. typedef T value_type;
  3760. typedef const T &const_reference;
  3761. #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
  3762. typedef T &reference;
  3763. #else
  3764. typedef sparse_matrix_element<self_type> reference;
  3765. #endif
  3766. typedef IA index_array_type;
  3767. typedef TA value_array_type;
  3768. typedef const matrix_reference<const self_type> const_closure_type;
  3769. typedef matrix_reference<self_type> closure_type;
  3770. typedef coordinate_vector<T, IB, IA, TA> vector_temporary_type;
  3771. typedef self_type matrix_temporary_type;
  3772. typedef sparse_tag storage_category;
  3773. typedef typename L::orientation_category orientation_category;
  3774. // Construction and destruction
  3775. BOOST_UBLAS_INLINE
  3776. coordinate_matrix ():
  3777. matrix_container<self_type> (),
  3778. size1_ (0), size2_ (0), capacity_ (restrict_capacity (0)),
  3779. filled_ (0), sorted_filled_ (filled_), sorted_ (true),
  3780. index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
  3781. storage_invariants ();
  3782. }
  3783. BOOST_UBLAS_INLINE
  3784. coordinate_matrix (size_type size1, size_type size2, array_size_type non_zeros = 0):
  3785. matrix_container<self_type> (),
  3786. size1_ (size1), size2_ (size2), capacity_ (restrict_capacity (non_zeros)),
  3787. filled_ (0), sorted_filled_ (filled_), sorted_ (true),
  3788. index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
  3789. storage_invariants ();
  3790. }
  3791. BOOST_UBLAS_INLINE
  3792. coordinate_matrix (const coordinate_matrix &m):
  3793. matrix_container<self_type> (),
  3794. size1_ (m.size1_), size2_ (m.size2_), capacity_ (m.capacity_),
  3795. filled_ (m.filled_), sorted_filled_ (m.sorted_filled_), sorted_ (m.sorted_),
  3796. index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) {
  3797. storage_invariants ();
  3798. }
  3799. template<class AE>
  3800. BOOST_UBLAS_INLINE
  3801. coordinate_matrix (const matrix_expression<AE> &ae, array_size_type non_zeros = 0):
  3802. matrix_container<self_type> (),
  3803. size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), capacity_ (restrict_capacity (non_zeros)),
  3804. filled_ (0), sorted_filled_ (filled_), sorted_ (true),
  3805. index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
  3806. storage_invariants ();
  3807. matrix_assign<scalar_assign> (*this, ae);
  3808. }
  3809. // Accessors
  3810. BOOST_UBLAS_INLINE
  3811. size_type size1 () const {
  3812. return size1_;
  3813. }
  3814. BOOST_UBLAS_INLINE
  3815. size_type size2 () const {
  3816. return size2_;
  3817. }
  3818. BOOST_UBLAS_INLINE
  3819. size_type nnz_capacity () const {
  3820. return capacity_;
  3821. }
  3822. BOOST_UBLAS_INLINE
  3823. size_type nnz () const {
  3824. return filled_;
  3825. }
  3826. // Storage accessors
  3827. BOOST_UBLAS_INLINE
  3828. static size_type index_base () {
  3829. return IB;
  3830. }
  3831. BOOST_UBLAS_INLINE
  3832. array_size_type filled () const {
  3833. return filled_;
  3834. }
  3835. BOOST_UBLAS_INLINE
  3836. const index_array_type &index1_data () const {
  3837. return index1_data_;
  3838. }
  3839. BOOST_UBLAS_INLINE
  3840. const index_array_type &index2_data () const {
  3841. return index2_data_;
  3842. }
  3843. BOOST_UBLAS_INLINE
  3844. const value_array_type &value_data () const {
  3845. return value_data_;
  3846. }
  3847. BOOST_UBLAS_INLINE
  3848. void set_filled (const array_size_type &filled) {
  3849. // Make sure that storage_invariants() succeeds
  3850. if (sorted_ && filled < filled_)
  3851. sorted_filled_ = filled;
  3852. else
  3853. sorted_ = (sorted_filled_ == filled);
  3854. filled_ = filled;
  3855. storage_invariants ();
  3856. }
  3857. BOOST_UBLAS_INLINE
  3858. index_array_type &index1_data () {
  3859. return index1_data_;
  3860. }
  3861. BOOST_UBLAS_INLINE
  3862. index_array_type &index2_data () {
  3863. return index2_data_;
  3864. }
  3865. BOOST_UBLAS_INLINE
  3866. value_array_type &value_data () {
  3867. return value_data_;
  3868. }
  3869. // Resizing
  3870. private:
  3871. BOOST_UBLAS_INLINE
  3872. array_size_type restrict_capacity (array_size_type non_zeros) const {
  3873. // minimum non_zeros
  3874. non_zeros = (std::max) (non_zeros, array_size_type((std::min) (size1_, size2_)));
  3875. // ISSUE no maximum as coordinate may contain inserted duplicates
  3876. return non_zeros;
  3877. }
  3878. public:
  3879. BOOST_UBLAS_INLINE
  3880. void resize (size_type size1, size_type size2, bool preserve = true) {
  3881. // FIXME preserve unimplemented
  3882. BOOST_UBLAS_CHECK (!preserve, internal_logic ());
  3883. size1_ = size1;
  3884. size2_ = size2;
  3885. capacity_ = restrict_capacity (capacity_);
  3886. index1_data_.resize (capacity_);
  3887. index2_data_.resize (capacity_);
  3888. value_data_.resize (capacity_);
  3889. filled_ = 0;
  3890. sorted_filled_ = filled_;
  3891. sorted_ = true;
  3892. storage_invariants ();
  3893. }
  3894. // Reserving
  3895. BOOST_UBLAS_INLINE
  3896. void reserve (array_size_type non_zeros, bool preserve = true) {
  3897. sort (); // remove duplicate elements
  3898. capacity_ = restrict_capacity (non_zeros);
  3899. if (preserve) {
  3900. index1_data_.resize (capacity_, size_type ());
  3901. index2_data_.resize (capacity_, size_type ());
  3902. value_data_.resize (capacity_, value_type ());
  3903. filled_ = (std::min) (capacity_, filled_);
  3904. }
  3905. else {
  3906. index1_data_.resize (capacity_);
  3907. index2_data_.resize (capacity_);
  3908. value_data_.resize (capacity_);
  3909. filled_ = 0;
  3910. }
  3911. sorted_filled_ = filled_;
  3912. storage_invariants ();
  3913. }
  3914. // Element support
  3915. BOOST_UBLAS_INLINE
  3916. pointer find_element (size_type i, size_type j) {
  3917. return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
  3918. }
  3919. BOOST_UBLAS_INLINE
  3920. const_pointer find_element (size_type i, size_type j) const {
  3921. sort ();
  3922. size_type element1 (layout_type::index_M (i, j));
  3923. size_type element2 (layout_type::index_m (i, j));
  3924. vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
  3925. vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
  3926. if (itv_begin == itv_end)
  3927. return 0;
  3928. const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
  3929. const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
  3930. const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
  3931. if (it == it_end || *it != k_based (element2))
  3932. return 0;
  3933. return &value_data_ [it - index2_data_.begin ()];
  3934. }
  3935. // Element access
  3936. BOOST_UBLAS_INLINE
  3937. const_reference operator () (size_type i, size_type j) const {
  3938. const_pointer p = find_element (i, j);
  3939. if (p)
  3940. return *p;
  3941. else
  3942. return zero_;
  3943. }
  3944. BOOST_UBLAS_INLINE
  3945. reference operator () (size_type i, size_type j) {
  3946. #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
  3947. pointer p = find_element (i, j);
  3948. if (p)
  3949. return *p;
  3950. else
  3951. return insert_element (i, j, value_type/*zero*/());
  3952. #else
  3953. return reference (*this, i, j);
  3954. #endif
  3955. }
  3956. // Element assignment
  3957. BOOST_UBLAS_INLINE
  3958. void append_element (size_type i, size_type j, const_reference t) {
  3959. if (filled_ >= capacity_)
  3960. reserve (2 * filled_, true);
  3961. BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
  3962. size_type element1 = layout_type::index_M (i, j);
  3963. size_type element2 = layout_type::index_m (i, j);
  3964. index1_data_ [filled_] = k_based (element1);
  3965. index2_data_ [filled_] = k_based (element2);
  3966. value_data_ [filled_] = t;
  3967. ++ filled_;
  3968. sorted_ = false;
  3969. storage_invariants ();
  3970. }
  3971. BOOST_UBLAS_INLINE
  3972. true_reference insert_element (size_type i, size_type j, const_reference t) {
  3973. BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
  3974. append_element (i, j, t);
  3975. return value_data_ [filled_ - 1];
  3976. }
  3977. BOOST_UBLAS_INLINE
  3978. void erase_element (size_type i, size_type j) {
  3979. size_type element1 = layout_type::index_M (i, j);
  3980. size_type element2 = layout_type::index_m (i, j);
  3981. sort ();
  3982. vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
  3983. vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
  3984. subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
  3985. subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
  3986. subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
  3987. if (it != it_end && *it == k_based (element2)) {
  3988. typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
  3989. vector_subiterator_type itv (index1_data_.begin () + n);
  3990. std::copy (itv + 1, index1_data_.begin () + filled_, itv);
  3991. std::copy (it + 1, index2_data_.begin () + filled_, it);
  3992. typename value_array_type::iterator itt (value_data_.begin () + n);
  3993. std::copy (itt + 1, value_data_.begin () + filled_, itt);
  3994. -- filled_;
  3995. sorted_filled_ = filled_;
  3996. }
  3997. storage_invariants ();
  3998. }
  3999. // Zeroing
  4000. BOOST_UBLAS_INLINE
  4001. void clear () {
  4002. filled_ = 0;
  4003. sorted_filled_ = filled_;
  4004. sorted_ = true;
  4005. storage_invariants ();
  4006. }
  4007. // Assignment
  4008. BOOST_UBLAS_INLINE
  4009. coordinate_matrix &operator = (const coordinate_matrix &m) {
  4010. if (this != &m) {
  4011. size1_ = m.size1_;
  4012. size2_ = m.size2_;
  4013. capacity_ = m.capacity_;
  4014. filled_ = m.filled_;
  4015. sorted_filled_ = m.sorted_filled_;
  4016. sorted_ = m.sorted_;
  4017. index1_data_ = m.index1_data_;
  4018. index2_data_ = m.index2_data_;
  4019. value_data_ = m.value_data_;
  4020. BOOST_UBLAS_CHECK (capacity_ == index1_data_.size (), internal_logic ());
  4021. BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
  4022. BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
  4023. }
  4024. storage_invariants ();
  4025. return *this;
  4026. }
  4027. template<class C> // Container assignment without temporary
  4028. BOOST_UBLAS_INLINE
  4029. coordinate_matrix &operator = (const matrix_container<C> &m) {
  4030. resize (m ().size1 (), m ().size2 (), false);
  4031. assign (m);
  4032. return *this;
  4033. }
  4034. BOOST_UBLAS_INLINE
  4035. coordinate_matrix &assign_temporary (coordinate_matrix &m) {
  4036. swap (m);
  4037. return *this;
  4038. }
  4039. template<class AE>
  4040. BOOST_UBLAS_INLINE
  4041. coordinate_matrix &operator = (const matrix_expression<AE> &ae) {
  4042. self_type temporary (ae, capacity_);
  4043. return assign_temporary (temporary);
  4044. }
  4045. template<class AE>
  4046. BOOST_UBLAS_INLINE
  4047. coordinate_matrix &assign (const matrix_expression<AE> &ae) {
  4048. matrix_assign<scalar_assign> (*this, ae);
  4049. return *this;
  4050. }
  4051. template<class AE>
  4052. BOOST_UBLAS_INLINE
  4053. coordinate_matrix& operator += (const matrix_expression<AE> &ae) {
  4054. self_type temporary (*this + ae, capacity_);
  4055. return assign_temporary (temporary);
  4056. }
  4057. template<class C> // Container assignment without temporary
  4058. BOOST_UBLAS_INLINE
  4059. coordinate_matrix &operator += (const matrix_container<C> &m) {
  4060. plus_assign (m);
  4061. return *this;
  4062. }
  4063. template<class AE>
  4064. BOOST_UBLAS_INLINE
  4065. coordinate_matrix &plus_assign (const matrix_expression<AE> &ae) {
  4066. matrix_assign<scalar_plus_assign> (*this, ae);
  4067. return *this;
  4068. }
  4069. template<class AE>
  4070. BOOST_UBLAS_INLINE
  4071. coordinate_matrix& operator -= (const matrix_expression<AE> &ae) {
  4072. self_type temporary (*this - ae, capacity_);
  4073. return assign_temporary (temporary);
  4074. }
  4075. template<class C> // Container assignment without temporary
  4076. BOOST_UBLAS_INLINE
  4077. coordinate_matrix &operator -= (const matrix_container<C> &m) {
  4078. minus_assign (m);
  4079. return *this;
  4080. }
  4081. template<class AE>
  4082. BOOST_UBLAS_INLINE
  4083. coordinate_matrix &minus_assign (const matrix_expression<AE> &ae) {
  4084. matrix_assign<scalar_minus_assign> (*this, ae);
  4085. return *this;
  4086. }
  4087. template<class AT>
  4088. BOOST_UBLAS_INLINE
  4089. coordinate_matrix& operator *= (const AT &at) {
  4090. matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  4091. return *this;
  4092. }
  4093. template<class AT>
  4094. BOOST_UBLAS_INLINE
  4095. coordinate_matrix& operator /= (const AT &at) {
  4096. matrix_assign_scalar<scalar_divides_assign> (*this, at);
  4097. return *this;
  4098. }
  4099. // Swapping
  4100. BOOST_UBLAS_INLINE
  4101. void swap (coordinate_matrix &m) {
  4102. if (this != &m) {
  4103. std::swap (size1_, m.size1_);
  4104. std::swap (size2_, m.size2_);
  4105. std::swap (capacity_, m.capacity_);
  4106. std::swap (filled_, m.filled_);
  4107. std::swap (sorted_filled_, m.sorted_filled_);
  4108. std::swap (sorted_, m.sorted_);
  4109. index1_data_.swap (m.index1_data_);
  4110. index2_data_.swap (m.index2_data_);
  4111. value_data_.swap (m.value_data_);
  4112. }
  4113. storage_invariants ();
  4114. }
  4115. BOOST_UBLAS_INLINE
  4116. friend void swap (coordinate_matrix &m1, coordinate_matrix &m2) {
  4117. m1.swap (m2);
  4118. }
  4119. // replacement if STL lower bound algorithm for use of inplace_merge
  4120. array_size_type lower_bound (array_size_type beg, array_size_type end, array_size_type target) const {
  4121. while (end > beg) {
  4122. array_size_type mid = (beg + end) / 2;
  4123. if (((index1_data_[mid] < index1_data_[target]) ||
  4124. ((index1_data_[mid] == index1_data_[target]) &&
  4125. (index2_data_[mid] < index2_data_[target])))) {
  4126. beg = mid + 1;
  4127. } else {
  4128. end = mid;
  4129. }
  4130. }
  4131. return beg;
  4132. }
  4133. // specialized replacement of STL inplace_merge to avoid compilation
  4134. // problems with respect to the array_triple iterator
  4135. void inplace_merge (array_size_type beg, array_size_type mid, array_size_type end) const {
  4136. array_size_type len_lef = mid - beg;
  4137. array_size_type len_rig = end - mid;
  4138. if (len_lef == 1 && len_rig == 1) {
  4139. if ((index1_data_[mid] < index1_data_[beg]) ||
  4140. ((index1_data_[mid] == index1_data_[beg]) && (index2_data_[mid] < index2_data_[beg])))
  4141. {
  4142. std::swap(index1_data_[beg], index1_data_[mid]);
  4143. std::swap(index2_data_[beg], index2_data_[mid]);
  4144. std::swap(value_data_[beg], value_data_[mid]);
  4145. }
  4146. } else if (len_lef > 0 && len_rig > 0) {
  4147. array_size_type lef_mid, rig_mid;
  4148. if (len_lef >= len_rig) {
  4149. lef_mid = (beg + mid) / 2;
  4150. rig_mid = lower_bound(mid, end, lef_mid);
  4151. } else {
  4152. rig_mid = (mid + end) / 2;
  4153. lef_mid = lower_bound(beg, mid, rig_mid);
  4154. }
  4155. std::rotate(&index1_data_[0] + lef_mid, &index1_data_[0] + mid, &index1_data_[0] + rig_mid);
  4156. std::rotate(&index2_data_[0] + lef_mid, &index2_data_[0] + mid, &index2_data_[0] + rig_mid);
  4157. std::rotate(&value_data_[0] + lef_mid, &value_data_[0] + mid, &value_data_[0] + rig_mid);
  4158. array_size_type new_mid = lef_mid + rig_mid - mid;
  4159. inplace_merge(beg, lef_mid, new_mid);
  4160. inplace_merge(new_mid, rig_mid, end);
  4161. }
  4162. }
  4163. // Sorting and summation of duplicates
  4164. BOOST_UBLAS_INLINE
  4165. void sort () const {
  4166. if (! sorted_ && filled_ > 0) {
  4167. typedef index_triple_array<index_array_type, index_array_type, value_array_type> array_triple;
  4168. array_triple ita (filled_, index1_data_, index2_data_, value_data_);
  4169. #ifndef BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT
  4170. const typename array_triple::iterator iunsorted = ita.begin () + sorted_filled_;
  4171. // sort new elements and merge
  4172. std::sort (iunsorted, ita.end ());
  4173. inplace_merge(0, sorted_filled_, filled_);
  4174. #else
  4175. const typename array_triple::iterator iunsorted = ita.begin ();
  4176. std::sort (iunsorted, ita.end ());
  4177. #endif
  4178. // sum duplicates with += and remove
  4179. array_size_type filled = 0;
  4180. for (array_size_type i = 1; i < filled_; ++ i) {
  4181. if (index1_data_ [filled] != index1_data_ [i] ||
  4182. index2_data_ [filled] != index2_data_ [i]) {
  4183. ++ filled;
  4184. if (filled != i) {
  4185. index1_data_ [filled] = index1_data_ [i];
  4186. index2_data_ [filled] = index2_data_ [i];
  4187. value_data_ [filled] = value_data_ [i];
  4188. }
  4189. } else {
  4190. value_data_ [filled] += value_data_ [i];
  4191. }
  4192. }
  4193. filled_ = filled + 1;
  4194. sorted_filled_ = filled_;
  4195. sorted_ = true;
  4196. storage_invariants ();
  4197. }
  4198. }
  4199. // Back element insertion and erasure
  4200. BOOST_UBLAS_INLINE
  4201. void push_back (size_type i, size_type j, const_reference t) {
  4202. size_type element1 = layout_type::index_M (i, j);
  4203. size_type element2 = layout_type::index_m (i, j);
  4204. // must maintain sort order
  4205. BOOST_UBLAS_CHECK (sorted_ &&
  4206. (filled_ == 0 ||
  4207. index1_data_ [filled_ - 1] < k_based (element1) ||
  4208. (index1_data_ [filled_ - 1] == k_based (element1) && index2_data_ [filled_ - 1] < k_based (element2)))
  4209. , external_logic ());
  4210. if (filled_ >= capacity_)
  4211. reserve (2 * filled_, true);
  4212. BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
  4213. index1_data_ [filled_] = k_based (element1);
  4214. index2_data_ [filled_] = k_based (element2);
  4215. value_data_ [filled_] = t;
  4216. ++ filled_;
  4217. sorted_filled_ = filled_;
  4218. storage_invariants ();
  4219. }
  4220. BOOST_UBLAS_INLINE
  4221. void pop_back () {
  4222. // ISSUE invariants could be simpilfied if sorted required as precondition
  4223. BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
  4224. -- filled_;
  4225. sorted_filled_ = (std::min) (sorted_filled_, filled_);
  4226. sorted_ = sorted_filled_ = filled_;
  4227. storage_invariants ();
  4228. }
  4229. // Iterator types
  4230. private:
  4231. // Use index array iterator
  4232. typedef typename IA::const_iterator vector_const_subiterator_type;
  4233. typedef typename IA::iterator vector_subiterator_type;
  4234. typedef typename IA::const_iterator const_subiterator_type;
  4235. typedef typename IA::iterator subiterator_type;
  4236. BOOST_UBLAS_INLINE
  4237. true_reference at_element (size_type i, size_type j) {
  4238. pointer p = find_element (i, j);
  4239. BOOST_UBLAS_CHECK (p, bad_index ());
  4240. return *p;
  4241. }
  4242. public:
  4243. class const_iterator1;
  4244. class iterator1;
  4245. class const_iterator2;
  4246. class iterator2;
  4247. typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  4248. typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  4249. typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  4250. typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  4251. // Element lookup
  4252. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  4253. const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
  4254. sort ();
  4255. for (;;) {
  4256. size_type address1 (layout_type::index_M (i, j));
  4257. size_type address2 (layout_type::index_m (i, j));
  4258. vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
  4259. vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
  4260. const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
  4261. const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
  4262. const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
  4263. vector_const_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
  4264. if (rank == 0)
  4265. return const_iterator1 (*this, rank, i, j, itv, it);
  4266. if (it != it_end && zero_based (*it) == address2)
  4267. return const_iterator1 (*this, rank, i, j, itv, it);
  4268. if (direction > 0) {
  4269. if (layout_type::fast_i ()) {
  4270. if (it == it_end)
  4271. return const_iterator1 (*this, rank, i, j, itv, it);
  4272. i = zero_based (*it);
  4273. } else {
  4274. if (i >= size1_)
  4275. return const_iterator1 (*this, rank, i, j, itv, it);
  4276. ++ i;
  4277. }
  4278. } else /* if (direction < 0) */ {
  4279. if (layout_type::fast_i ()) {
  4280. if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
  4281. return const_iterator1 (*this, rank, i, j, itv, it);
  4282. i = zero_based (*(it - 1));
  4283. } else {
  4284. if (i == 0)
  4285. return const_iterator1 (*this, rank, i, j, itv, it);
  4286. -- i;
  4287. }
  4288. }
  4289. }
  4290. }
  4291. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  4292. iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
  4293. sort ();
  4294. for (;;) {
  4295. size_type address1 (layout_type::index_M (i, j));
  4296. size_type address2 (layout_type::index_m (i, j));
  4297. vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
  4298. vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
  4299. subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
  4300. subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
  4301. subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
  4302. vector_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
  4303. if (rank == 0)
  4304. return iterator1 (*this, rank, i, j, itv, it);
  4305. if (it != it_end && zero_based (*it) == address2)
  4306. return iterator1 (*this, rank, i, j, itv, it);
  4307. if (direction > 0) {
  4308. if (layout_type::fast_i ()) {
  4309. if (it == it_end)
  4310. return iterator1 (*this, rank, i, j, itv, it);
  4311. i = zero_based (*it);
  4312. } else {
  4313. if (i >= size1_)
  4314. return iterator1 (*this, rank, i, j, itv, it);
  4315. ++ i;
  4316. }
  4317. } else /* if (direction < 0) */ {
  4318. if (layout_type::fast_i ()) {
  4319. if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
  4320. return iterator1 (*this, rank, i, j, itv, it);
  4321. i = zero_based (*(it - 1));
  4322. } else {
  4323. if (i == 0)
  4324. return iterator1 (*this, rank, i, j, itv, it);
  4325. -- i;
  4326. }
  4327. }
  4328. }
  4329. }
  4330. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  4331. const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
  4332. sort ();
  4333. for (;;) {
  4334. size_type address1 (layout_type::index_M (i, j));
  4335. size_type address2 (layout_type::index_m (i, j));
  4336. vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
  4337. vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
  4338. const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
  4339. const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
  4340. const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
  4341. vector_const_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
  4342. if (rank == 0)
  4343. return const_iterator2 (*this, rank, i, j, itv, it);
  4344. if (it != it_end && zero_based (*it) == address2)
  4345. return const_iterator2 (*this, rank, i, j, itv, it);
  4346. if (direction > 0) {
  4347. if (layout_type::fast_j ()) {
  4348. if (it == it_end)
  4349. return const_iterator2 (*this, rank, i, j, itv, it);
  4350. j = zero_based (*it);
  4351. } else {
  4352. if (j >= size2_)
  4353. return const_iterator2 (*this, rank, i, j, itv, it);
  4354. ++ j;
  4355. }
  4356. } else /* if (direction < 0) */ {
  4357. if (layout_type::fast_j ()) {
  4358. if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
  4359. return const_iterator2 (*this, rank, i, j, itv, it);
  4360. j = zero_based (*(it - 1));
  4361. } else {
  4362. if (j == 0)
  4363. return const_iterator2 (*this, rank, i, j, itv, it);
  4364. -- j;
  4365. }
  4366. }
  4367. }
  4368. }
  4369. // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
  4370. iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
  4371. sort ();
  4372. for (;;) {
  4373. size_type address1 (layout_type::index_M (i, j));
  4374. size_type address2 (layout_type::index_m (i, j));
  4375. vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
  4376. vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
  4377. subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
  4378. subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
  4379. subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
  4380. vector_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
  4381. if (rank == 0)
  4382. return iterator2 (*this, rank, i, j, itv, it);
  4383. if (it != it_end && zero_based (*it) == address2)
  4384. return iterator2 (*this, rank, i, j, itv, it);
  4385. if (direction > 0) {
  4386. if (layout_type::fast_j ()) {
  4387. if (it == it_end)
  4388. return iterator2 (*this, rank, i, j, itv, it);
  4389. j = zero_based (*it);
  4390. } else {
  4391. if (j >= size2_)
  4392. return iterator2 (*this, rank, i, j, itv, it);
  4393. ++ j;
  4394. }
  4395. } else /* if (direction < 0) */ {
  4396. if (layout_type::fast_j ()) {
  4397. if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
  4398. return iterator2 (*this, rank, i, j, itv, it);
  4399. j = zero_based (*(it - 1));
  4400. } else {
  4401. if (j == 0)
  4402. return iterator2 (*this, rank, i, j, itv, it);
  4403. -- j;
  4404. }
  4405. }
  4406. }
  4407. }
  4408. class const_iterator1:
  4409. public container_const_reference<coordinate_matrix>,
  4410. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  4411. const_iterator1, value_type> {
  4412. public:
  4413. typedef typename coordinate_matrix::value_type value_type;
  4414. typedef typename coordinate_matrix::difference_type difference_type;
  4415. typedef typename coordinate_matrix::const_reference reference;
  4416. typedef const typename coordinate_matrix::pointer pointer;
  4417. typedef const_iterator2 dual_iterator_type;
  4418. typedef const_reverse_iterator2 dual_reverse_iterator_type;
  4419. // Construction and destruction
  4420. BOOST_UBLAS_INLINE
  4421. const_iterator1 ():
  4422. container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  4423. BOOST_UBLAS_INLINE
  4424. const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
  4425. container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  4426. BOOST_UBLAS_INLINE
  4427. const_iterator1 (const iterator1 &it):
  4428. container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
  4429. // Arithmetic
  4430. BOOST_UBLAS_INLINE
  4431. const_iterator1 &operator ++ () {
  4432. if (rank_ == 1 && layout_type::fast_i ())
  4433. ++ it_;
  4434. else {
  4435. i_ = index1 () + 1;
  4436. if (rank_ == 1)
  4437. *this = (*this) ().find1 (rank_, i_, j_, 1);
  4438. }
  4439. return *this;
  4440. }
  4441. BOOST_UBLAS_INLINE
  4442. const_iterator1 &operator -- () {
  4443. if (rank_ == 1 && layout_type::fast_i ())
  4444. -- it_;
  4445. else {
  4446. i_ = index1 () - 1;
  4447. if (rank_ == 1)
  4448. *this = (*this) ().find1 (rank_, i_, j_, -1);
  4449. }
  4450. return *this;
  4451. }
  4452. // Dereference
  4453. BOOST_UBLAS_INLINE
  4454. const_reference operator * () const {
  4455. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  4456. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  4457. if (rank_ == 1) {
  4458. return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
  4459. } else {
  4460. return (*this) () (i_, j_);
  4461. }
  4462. }
  4463. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  4464. BOOST_UBLAS_INLINE
  4465. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4466. typename self_type::
  4467. #endif
  4468. const_iterator2 begin () const {
  4469. const self_type &m = (*this) ();
  4470. return m.find2 (1, index1 (), 0);
  4471. }
  4472. BOOST_UBLAS_INLINE
  4473. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4474. typename self_type::
  4475. #endif
  4476. const_iterator2 end () const {
  4477. const self_type &m = (*this) ();
  4478. return m.find2 (1, index1 (), m.size2 ());
  4479. }
  4480. BOOST_UBLAS_INLINE
  4481. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4482. typename self_type::
  4483. #endif
  4484. const_reverse_iterator2 rbegin () const {
  4485. return const_reverse_iterator2 (end ());
  4486. }
  4487. BOOST_UBLAS_INLINE
  4488. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4489. typename self_type::
  4490. #endif
  4491. const_reverse_iterator2 rend () const {
  4492. return const_reverse_iterator2 (begin ());
  4493. }
  4494. #endif
  4495. // Indices
  4496. BOOST_UBLAS_INLINE
  4497. size_type index1 () const {
  4498. BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
  4499. if (rank_ == 1) {
  4500. BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
  4501. return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
  4502. } else {
  4503. return i_;
  4504. }
  4505. }
  4506. BOOST_UBLAS_INLINE
  4507. size_type index2 () const {
  4508. if (rank_ == 1) {
  4509. BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
  4510. return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
  4511. } else {
  4512. return j_;
  4513. }
  4514. }
  4515. // Assignment
  4516. BOOST_UBLAS_INLINE
  4517. const_iterator1 &operator = (const const_iterator1 &it) {
  4518. container_const_reference<self_type>::assign (&it ());
  4519. rank_ = it.rank_;
  4520. i_ = it.i_;
  4521. j_ = it.j_;
  4522. itv_ = it.itv_;
  4523. it_ = it.it_;
  4524. return *this;
  4525. }
  4526. // Comparison
  4527. BOOST_UBLAS_INLINE
  4528. bool operator == (const const_iterator1 &it) const {
  4529. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  4530. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  4531. if (rank_ == 1 || it.rank_ == 1) {
  4532. return it_ == it.it_;
  4533. } else {
  4534. return i_ == it.i_ && j_ == it.j_;
  4535. }
  4536. }
  4537. private:
  4538. int rank_;
  4539. size_type i_;
  4540. size_type j_;
  4541. vector_const_subiterator_type itv_;
  4542. const_subiterator_type it_;
  4543. };
  4544. BOOST_UBLAS_INLINE
  4545. const_iterator1 begin1 () const {
  4546. return find1 (0, 0, 0);
  4547. }
  4548. BOOST_UBLAS_INLINE
  4549. const_iterator1 end1 () const {
  4550. return find1 (0, size1_, 0);
  4551. }
  4552. class iterator1:
  4553. public container_reference<coordinate_matrix>,
  4554. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  4555. iterator1, value_type> {
  4556. public:
  4557. typedef typename coordinate_matrix::value_type value_type;
  4558. typedef typename coordinate_matrix::difference_type difference_type;
  4559. typedef typename coordinate_matrix::true_reference reference;
  4560. typedef typename coordinate_matrix::pointer pointer;
  4561. typedef iterator2 dual_iterator_type;
  4562. typedef reverse_iterator2 dual_reverse_iterator_type;
  4563. // Construction and destruction
  4564. BOOST_UBLAS_INLINE
  4565. iterator1 ():
  4566. container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  4567. BOOST_UBLAS_INLINE
  4568. iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
  4569. container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  4570. // Arithmetic
  4571. BOOST_UBLAS_INLINE
  4572. iterator1 &operator ++ () {
  4573. if (rank_ == 1 && layout_type::fast_i ())
  4574. ++ it_;
  4575. else {
  4576. i_ = index1 () + 1;
  4577. if (rank_ == 1)
  4578. *this = (*this) ().find1 (rank_, i_, j_, 1);
  4579. }
  4580. return *this;
  4581. }
  4582. BOOST_UBLAS_INLINE
  4583. iterator1 &operator -- () {
  4584. if (rank_ == 1 && layout_type::fast_i ())
  4585. -- it_;
  4586. else {
  4587. i_ = index1 () - 1;
  4588. if (rank_ == 1)
  4589. *this = (*this) ().find1 (rank_, i_, j_, -1);
  4590. }
  4591. return *this;
  4592. }
  4593. // Dereference
  4594. BOOST_UBLAS_INLINE
  4595. reference operator * () const {
  4596. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  4597. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  4598. if (rank_ == 1) {
  4599. return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
  4600. } else {
  4601. return (*this) ().at_element (i_, j_);
  4602. }
  4603. }
  4604. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  4605. BOOST_UBLAS_INLINE
  4606. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4607. typename self_type::
  4608. #endif
  4609. iterator2 begin () const {
  4610. self_type &m = (*this) ();
  4611. return m.find2 (1, index1 (), 0);
  4612. }
  4613. BOOST_UBLAS_INLINE
  4614. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4615. typename self_type::
  4616. #endif
  4617. iterator2 end () const {
  4618. self_type &m = (*this) ();
  4619. return m.find2 (1, index1 (), m.size2 ());
  4620. }
  4621. BOOST_UBLAS_INLINE
  4622. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4623. typename self_type::
  4624. #endif
  4625. reverse_iterator2 rbegin () const {
  4626. return reverse_iterator2 (end ());
  4627. }
  4628. BOOST_UBLAS_INLINE
  4629. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4630. typename self_type::
  4631. #endif
  4632. reverse_iterator2 rend () const {
  4633. return reverse_iterator2 (begin ());
  4634. }
  4635. #endif
  4636. // Indices
  4637. BOOST_UBLAS_INLINE
  4638. size_type index1 () const {
  4639. BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
  4640. if (rank_ == 1) {
  4641. BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
  4642. return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
  4643. } else {
  4644. return i_;
  4645. }
  4646. }
  4647. BOOST_UBLAS_INLINE
  4648. size_type index2 () const {
  4649. if (rank_ == 1) {
  4650. BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
  4651. return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
  4652. } else {
  4653. return j_;
  4654. }
  4655. }
  4656. // Assignment
  4657. BOOST_UBLAS_INLINE
  4658. iterator1 &operator = (const iterator1 &it) {
  4659. container_reference<self_type>::assign (&it ());
  4660. rank_ = it.rank_;
  4661. i_ = it.i_;
  4662. j_ = it.j_;
  4663. itv_ = it.itv_;
  4664. it_ = it.it_;
  4665. return *this;
  4666. }
  4667. // Comparison
  4668. BOOST_UBLAS_INLINE
  4669. bool operator == (const iterator1 &it) const {
  4670. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  4671. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  4672. if (rank_ == 1 || it.rank_ == 1) {
  4673. return it_ == it.it_;
  4674. } else {
  4675. return i_ == it.i_ && j_ == it.j_;
  4676. }
  4677. }
  4678. private:
  4679. int rank_;
  4680. size_type i_;
  4681. size_type j_;
  4682. vector_subiterator_type itv_;
  4683. subiterator_type it_;
  4684. friend class const_iterator1;
  4685. };
  4686. BOOST_UBLAS_INLINE
  4687. iterator1 begin1 () {
  4688. return find1 (0, 0, 0);
  4689. }
  4690. BOOST_UBLAS_INLINE
  4691. iterator1 end1 () {
  4692. return find1 (0, size1_, 0);
  4693. }
  4694. class const_iterator2:
  4695. public container_const_reference<coordinate_matrix>,
  4696. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  4697. const_iterator2, value_type> {
  4698. public:
  4699. typedef typename coordinate_matrix::value_type value_type;
  4700. typedef typename coordinate_matrix::difference_type difference_type;
  4701. typedef typename coordinate_matrix::const_reference reference;
  4702. typedef const typename coordinate_matrix::pointer pointer;
  4703. typedef const_iterator1 dual_iterator_type;
  4704. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  4705. // Construction and destruction
  4706. BOOST_UBLAS_INLINE
  4707. const_iterator2 ():
  4708. container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  4709. BOOST_UBLAS_INLINE
  4710. const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type itv, const const_subiterator_type &it):
  4711. container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  4712. BOOST_UBLAS_INLINE
  4713. const_iterator2 (const iterator2 &it):
  4714. container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
  4715. // Arithmetic
  4716. BOOST_UBLAS_INLINE
  4717. const_iterator2 &operator ++ () {
  4718. if (rank_ == 1 && layout_type::fast_j ())
  4719. ++ it_;
  4720. else {
  4721. j_ = index2 () + 1;
  4722. if (rank_ == 1)
  4723. *this = (*this) ().find2 (rank_, i_, j_, 1);
  4724. }
  4725. return *this;
  4726. }
  4727. BOOST_UBLAS_INLINE
  4728. const_iterator2 &operator -- () {
  4729. if (rank_ == 1 && layout_type::fast_j ())
  4730. -- it_;
  4731. else {
  4732. j_ = index2 () - 1;
  4733. if (rank_ == 1)
  4734. *this = (*this) ().find2 (rank_, i_, j_, -1);
  4735. }
  4736. return *this;
  4737. }
  4738. // Dereference
  4739. BOOST_UBLAS_INLINE
  4740. const_reference operator * () const {
  4741. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  4742. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  4743. if (rank_ == 1) {
  4744. return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
  4745. } else {
  4746. return (*this) () (i_, j_);
  4747. }
  4748. }
  4749. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  4750. BOOST_UBLAS_INLINE
  4751. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4752. typename self_type::
  4753. #endif
  4754. const_iterator1 begin () const {
  4755. const self_type &m = (*this) ();
  4756. return m.find1 (1, 0, index2 ());
  4757. }
  4758. BOOST_UBLAS_INLINE
  4759. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4760. typename self_type::
  4761. #endif
  4762. const_iterator1 end () const {
  4763. const self_type &m = (*this) ();
  4764. return m.find1 (1, m.size1 (), index2 ());
  4765. }
  4766. BOOST_UBLAS_INLINE
  4767. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4768. typename self_type::
  4769. #endif
  4770. const_reverse_iterator1 rbegin () const {
  4771. return const_reverse_iterator1 (end ());
  4772. }
  4773. BOOST_UBLAS_INLINE
  4774. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4775. typename self_type::
  4776. #endif
  4777. const_reverse_iterator1 rend () const {
  4778. return const_reverse_iterator1 (begin ());
  4779. }
  4780. #endif
  4781. // Indices
  4782. BOOST_UBLAS_INLINE
  4783. size_type index1 () const {
  4784. if (rank_ == 1) {
  4785. BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
  4786. return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
  4787. } else {
  4788. return i_;
  4789. }
  4790. }
  4791. BOOST_UBLAS_INLINE
  4792. size_type index2 () const {
  4793. BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
  4794. if (rank_ == 1) {
  4795. BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
  4796. return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
  4797. } else {
  4798. return j_;
  4799. }
  4800. }
  4801. // Assignment
  4802. BOOST_UBLAS_INLINE
  4803. const_iterator2 &operator = (const const_iterator2 &it) {
  4804. container_const_reference<self_type>::assign (&it ());
  4805. rank_ = it.rank_;
  4806. i_ = it.i_;
  4807. j_ = it.j_;
  4808. itv_ = it.itv_;
  4809. it_ = it.it_;
  4810. return *this;
  4811. }
  4812. // Comparison
  4813. BOOST_UBLAS_INLINE
  4814. bool operator == (const const_iterator2 &it) const {
  4815. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  4816. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  4817. if (rank_ == 1 || it.rank_ == 1) {
  4818. return it_ == it.it_;
  4819. } else {
  4820. return i_ == it.i_ && j_ == it.j_;
  4821. }
  4822. }
  4823. private:
  4824. int rank_;
  4825. size_type i_;
  4826. size_type j_;
  4827. vector_const_subiterator_type itv_;
  4828. const_subiterator_type it_;
  4829. };
  4830. BOOST_UBLAS_INLINE
  4831. const_iterator2 begin2 () const {
  4832. return find2 (0, 0, 0);
  4833. }
  4834. BOOST_UBLAS_INLINE
  4835. const_iterator2 end2 () const {
  4836. return find2 (0, 0, size2_);
  4837. }
  4838. class iterator2:
  4839. public container_reference<coordinate_matrix>,
  4840. public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  4841. iterator2, value_type> {
  4842. public:
  4843. typedef typename coordinate_matrix::value_type value_type;
  4844. typedef typename coordinate_matrix::difference_type difference_type;
  4845. typedef typename coordinate_matrix::true_reference reference;
  4846. typedef typename coordinate_matrix::pointer pointer;
  4847. typedef iterator1 dual_iterator_type;
  4848. typedef reverse_iterator1 dual_reverse_iterator_type;
  4849. // Construction and destruction
  4850. BOOST_UBLAS_INLINE
  4851. iterator2 ():
  4852. container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
  4853. BOOST_UBLAS_INLINE
  4854. iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
  4855. container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
  4856. // Arithmetic
  4857. BOOST_UBLAS_INLINE
  4858. iterator2 &operator ++ () {
  4859. if (rank_ == 1 && layout_type::fast_j ())
  4860. ++ it_;
  4861. else {
  4862. j_ = index2 () + 1;
  4863. if (rank_ == 1)
  4864. *this = (*this) ().find2 (rank_, i_, j_, 1);
  4865. }
  4866. return *this;
  4867. }
  4868. BOOST_UBLAS_INLINE
  4869. iterator2 &operator -- () {
  4870. if (rank_ == 1 && layout_type::fast_j ())
  4871. -- it_;
  4872. else {
  4873. j_ = index2 ();
  4874. if (rank_ == 1)
  4875. *this = (*this) ().find2 (rank_, i_, j_, -1);
  4876. }
  4877. return *this;
  4878. }
  4879. // Dereference
  4880. BOOST_UBLAS_INLINE
  4881. reference operator * () const {
  4882. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  4883. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  4884. if (rank_ == 1) {
  4885. return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
  4886. } else {
  4887. return (*this) ().at_element (i_, j_);
  4888. }
  4889. }
  4890. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  4891. BOOST_UBLAS_INLINE
  4892. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4893. typename self_type::
  4894. #endif
  4895. iterator1 begin () const {
  4896. self_type &m = (*this) ();
  4897. return m.find1 (1, 0, index2 ());
  4898. }
  4899. BOOST_UBLAS_INLINE
  4900. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4901. typename self_type::
  4902. #endif
  4903. iterator1 end () const {
  4904. self_type &m = (*this) ();
  4905. return m.find1 (1, m.size1 (), index2 ());
  4906. }
  4907. BOOST_UBLAS_INLINE
  4908. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4909. typename self_type::
  4910. #endif
  4911. reverse_iterator1 rbegin () const {
  4912. return reverse_iterator1 (end ());
  4913. }
  4914. BOOST_UBLAS_INLINE
  4915. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  4916. typename self_type::
  4917. #endif
  4918. reverse_iterator1 rend () const {
  4919. return reverse_iterator1 (begin ());
  4920. }
  4921. #endif
  4922. // Indices
  4923. BOOST_UBLAS_INLINE
  4924. size_type index1 () const {
  4925. if (rank_ == 1) {
  4926. BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
  4927. return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
  4928. } else {
  4929. return i_;
  4930. }
  4931. }
  4932. BOOST_UBLAS_INLINE
  4933. size_type index2 () const {
  4934. BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
  4935. if (rank_ == 1) {
  4936. BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
  4937. return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
  4938. } else {
  4939. return j_;
  4940. }
  4941. }
  4942. // Assignment
  4943. BOOST_UBLAS_INLINE
  4944. iterator2 &operator = (const iterator2 &it) {
  4945. container_reference<self_type>::assign (&it ());
  4946. rank_ = it.rank_;
  4947. i_ = it.i_;
  4948. j_ = it.j_;
  4949. itv_ = it.itv_;
  4950. it_ = it.it_;
  4951. return *this;
  4952. }
  4953. // Comparison
  4954. BOOST_UBLAS_INLINE
  4955. bool operator == (const iterator2 &it) const {
  4956. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  4957. // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
  4958. if (rank_ == 1 || it.rank_ == 1) {
  4959. return it_ == it.it_;
  4960. } else {
  4961. return i_ == it.i_ && j_ == it.j_;
  4962. }
  4963. }
  4964. private:
  4965. int rank_;
  4966. size_type i_;
  4967. size_type j_;
  4968. vector_subiterator_type itv_;
  4969. subiterator_type it_;
  4970. friend class const_iterator2;
  4971. };
  4972. BOOST_UBLAS_INLINE
  4973. iterator2 begin2 () {
  4974. return find2 (0, 0, 0);
  4975. }
  4976. BOOST_UBLAS_INLINE
  4977. iterator2 end2 () {
  4978. return find2 (0, 0, size2_);
  4979. }
  4980. // Reverse iterators
  4981. BOOST_UBLAS_INLINE
  4982. const_reverse_iterator1 rbegin1 () const {
  4983. return const_reverse_iterator1 (end1 ());
  4984. }
  4985. BOOST_UBLAS_INLINE
  4986. const_reverse_iterator1 rend1 () const {
  4987. return const_reverse_iterator1 (begin1 ());
  4988. }
  4989. BOOST_UBLAS_INLINE
  4990. reverse_iterator1 rbegin1 () {
  4991. return reverse_iterator1 (end1 ());
  4992. }
  4993. BOOST_UBLAS_INLINE
  4994. reverse_iterator1 rend1 () {
  4995. return reverse_iterator1 (begin1 ());
  4996. }
  4997. BOOST_UBLAS_INLINE
  4998. const_reverse_iterator2 rbegin2 () const {
  4999. return const_reverse_iterator2 (end2 ());
  5000. }
  5001. BOOST_UBLAS_INLINE
  5002. const_reverse_iterator2 rend2 () const {
  5003. return const_reverse_iterator2 (begin2 ());
  5004. }
  5005. BOOST_UBLAS_INLINE
  5006. reverse_iterator2 rbegin2 () {
  5007. return reverse_iterator2 (end2 ());
  5008. }
  5009. BOOST_UBLAS_INLINE
  5010. reverse_iterator2 rend2 () {
  5011. return reverse_iterator2 (begin2 ());
  5012. }
  5013. // Serialization
  5014. template<class Archive>
  5015. void serialize(Archive & ar, const unsigned int /* file_version */){
  5016. serialization::collection_size_type s1 (size1_);
  5017. serialization::collection_size_type s2 (size2_);
  5018. ar & serialization::make_nvp("size1",s1);
  5019. ar & serialization::make_nvp("size2",s2);
  5020. if (Archive::is_loading::value) {
  5021. size1_ = s1;
  5022. size2_ = s2;
  5023. }
  5024. ar & serialization::make_nvp("capacity", capacity_);
  5025. ar & serialization::make_nvp("filled", filled_);
  5026. ar & serialization::make_nvp("sorted_filled", sorted_filled_);
  5027. ar & serialization::make_nvp("sorted", sorted_);
  5028. ar & serialization::make_nvp("index1_data", index1_data_);
  5029. ar & serialization::make_nvp("index2_data", index2_data_);
  5030. ar & serialization::make_nvp("value_data", value_data_);
  5031. storage_invariants();
  5032. }
  5033. private:
  5034. void storage_invariants () const
  5035. {
  5036. BOOST_UBLAS_CHECK (capacity_ == index1_data_.size (), internal_logic ());
  5037. BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
  5038. BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
  5039. BOOST_UBLAS_CHECK (filled_ <= capacity_, internal_logic ());
  5040. BOOST_UBLAS_CHECK (sorted_filled_ <= filled_, internal_logic ());
  5041. BOOST_UBLAS_CHECK (sorted_ == (sorted_filled_ == filled_), internal_logic ());
  5042. }
  5043. size_type size1_;
  5044. size_type size2_;
  5045. array_size_type capacity_;
  5046. mutable array_size_type filled_;
  5047. mutable array_size_type sorted_filled_;
  5048. mutable bool sorted_;
  5049. mutable index_array_type index1_data_;
  5050. mutable index_array_type index2_data_;
  5051. mutable value_array_type value_data_;
  5052. static const value_type zero_;
  5053. BOOST_UBLAS_INLINE
  5054. static size_type zero_based (size_type k_based_index) {
  5055. return k_based_index - IB;
  5056. }
  5057. BOOST_UBLAS_INLINE
  5058. static size_type k_based (size_type zero_based_index) {
  5059. return zero_based_index + IB;
  5060. }
  5061. friend class iterator1;
  5062. friend class iterator2;
  5063. friend class const_iterator1;
  5064. friend class const_iterator2;
  5065. };
  5066. template<class T, class L, std::size_t IB, class IA, class TA>
  5067. const typename coordinate_matrix<T, L, IB, IA, TA>::value_type coordinate_matrix<T, L, IB, IA, TA>::zero_ = value_type/*zero*/();
  5068. }}}
  5069. #endif