matrix_expression.hpp 208 KB

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