12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992 |
- // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
- // Copyright 2008-2016 National ICT Australia (NICTA)
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- // ------------------------------------------------------------------------
- //! \addtogroup SpMat
- //! @{
- /**
- * Initialize a sparse matrix with size 0x0 (empty).
- */
- template<typename eT>
- inline
- SpMat<eT>::SpMat()
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- init_cold(0,0);
- }
- /**
- * Clean up the memory of a sparse matrix and destruct it.
- */
- template<typename eT>
- inline
- SpMat<eT>::~SpMat()
- {
- arma_extra_debug_sigprint_this(this);
-
- if(values ) { memory::release(access::rw(values)); }
- if(row_indices) { memory::release(access::rw(row_indices)); }
- if(col_ptrs ) { memory::release(access::rw(col_ptrs)); }
- }
- /**
- * Constructor with size given.
- */
- template<typename eT>
- inline
- SpMat<eT>::SpMat(const uword in_rows, const uword in_cols)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- init_cold(in_rows, in_cols);
- }
- template<typename eT>
- inline
- SpMat<eT>::SpMat(const SizeMat& s)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- init_cold(s.n_rows, s.n_cols);
- }
- template<typename eT>
- inline
- SpMat<eT>::SpMat(const arma_reserve_indicator&, const uword in_rows, const uword in_cols, const uword new_n_nonzero)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- init_cold(in_rows, in_cols, new_n_nonzero);
- }
- template<typename eT>
- template<typename eT2>
- inline
- SpMat<eT>::SpMat(const arma_layout_indicator&, const SpMat<eT2>& x)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- init_cold(x.n_rows, x.n_cols, x.n_nonzero);
-
- if(x.n_nonzero == 0) { return; }
-
- if(x.row_indices) { arrayops::copy(access::rwp(row_indices), x.row_indices, x.n_nonzero + 1); }
- if(x.col_ptrs ) { arrayops::copy(access::rwp(col_ptrs), x.col_ptrs, x.n_cols + 1); }
-
- // NOTE: 'values' array is not initialised
- }
- /**
- * Assemble from text.
- */
- template<typename eT>
- inline
- SpMat<eT>::SpMat(const char* text)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- init(std::string(text));
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const char* text)
- {
- arma_extra_debug_sigprint();
-
- init(std::string(text));
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>::SpMat(const std::string& text)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint();
-
- init(text);
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const std::string& text)
- {
- arma_extra_debug_sigprint();
-
- init(text);
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>::SpMat(const SpMat<eT>& x)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- init(x);
- }
- #if defined(ARMA_USE_CXX11)
-
- template<typename eT>
- inline
- SpMat<eT>::SpMat(SpMat<eT>&& in_mat)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
- arma_extra_debug_sigprint(arma_str::format("this = %x in_mat = %x") % this % &in_mat);
-
- (*this).steal_mem(in_mat);
- }
-
-
-
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(SpMat<eT>&& in_mat)
- {
- arma_extra_debug_sigprint(arma_str::format("this = %x in_mat = %x") % this % &in_mat);
-
- (*this).steal_mem(in_mat);
-
- return *this;
- }
-
- #endif
- template<typename eT>
- inline
- SpMat<eT>::SpMat(const MapMat<eT>& x)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- init(x);
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const MapMat<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- init(x);
-
- return *this;
- }
- //! Insert a large number of values at once.
- //! locations.row[0] should be row indices, locations.row[1] should be column indices,
- //! and values should be the corresponding values.
- //! If sort_locations is false, then it is assumed that the locations and values
- //! are already sorted in column-major ordering.
- template<typename eT>
- template<typename T1, typename T2>
- inline
- SpMat<eT>::SpMat(const Base<uword,T1>& locations_expr, const Base<eT,T2>& vals_expr, const bool sort_locations)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- const unwrap<T1> locs_tmp( locations_expr.get_ref() );
- const unwrap<T2> vals_tmp( vals_expr.get_ref() );
-
- const Mat<uword>& locs = locs_tmp.M;
- const Mat<eT>& vals = vals_tmp.M;
-
- arma_debug_check( (vals.is_vec() == false), "SpMat::SpMat(): given 'values' object is not a vector" );
- arma_debug_check( (locs.n_rows != 2), "SpMat::SpMat(): locations matrix must have two rows" );
- arma_debug_check( (locs.n_cols != vals.n_elem), "SpMat::SpMat(): number of locations is different than number of values" );
- // If there are no elements in the list, max() will fail.
- if(locs.n_cols == 0) { init_cold(0, 0); return; }
-
- // Automatically determine size before pruning zeros.
- uvec bounds = arma::max(locs, 1);
- init_cold(bounds[0] + 1, bounds[1] + 1);
-
- // Ensure that there are no zeros
- const uword N_old = vals.n_elem;
- uword N_new = 0;
-
- for(uword i = 0; i < N_old; ++i)
- {
- if(vals[i] != eT(0)) { ++N_new; }
- }
-
- if(N_new != N_old)
- {
- Col<eT> filtered_vals(N_new);
- Mat<uword> filtered_locs(2, N_new);
-
- uword index = 0;
- for(uword i = 0; i < N_old; ++i)
- {
- if(vals[i] != eT(0))
- {
- filtered_vals[index] = vals[i];
-
- filtered_locs.at(0, index) = locs.at(0, i);
- filtered_locs.at(1, index) = locs.at(1, i);
-
- ++index;
- }
- }
-
- init_batch_std(filtered_locs, filtered_vals, sort_locations);
- }
- else
- {
- init_batch_std(locs, vals, sort_locations);
- }
- }
- //! Insert a large number of values at once.
- //! locations.row[0] should be row indices, locations.row[1] should be column indices,
- //! and values should be the corresponding values.
- //! If sort_locations is false, then it is assumed that the locations and values
- //! are already sorted in column-major ordering.
- //! In this constructor the size is explicitly given.
- template<typename eT>
- template<typename T1, typename T2>
- inline
- SpMat<eT>::SpMat(const Base<uword,T1>& locations_expr, const Base<eT,T2>& vals_expr, const uword in_n_rows, const uword in_n_cols, const bool sort_locations, const bool check_for_zeros)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- const unwrap<T1> locs_tmp( locations_expr.get_ref() );
- const unwrap<T2> vals_tmp( vals_expr.get_ref() );
-
- const Mat<uword>& locs = locs_tmp.M;
- const Mat<eT>& vals = vals_tmp.M;
-
- arma_debug_check( (vals.is_vec() == false), "SpMat::SpMat(): given 'values' object is not a vector" );
- arma_debug_check( (locs.n_rows != 2), "SpMat::SpMat(): locations matrix must have two rows" );
- arma_debug_check( (locs.n_cols != vals.n_elem), "SpMat::SpMat(): number of locations is different than number of values" );
-
- init_cold(in_n_rows, in_n_cols);
-
- // Ensure that there are no zeros, unless the user asked not to.
- if(check_for_zeros)
- {
- const uword N_old = vals.n_elem;
- uword N_new = 0;
-
- for(uword i = 0; i < N_old; ++i)
- {
- if(vals[i] != eT(0)) { ++N_new; }
- }
-
- if(N_new != N_old)
- {
- Col<eT> filtered_vals(N_new);
- Mat<uword> filtered_locs(2, N_new);
-
- uword index = 0;
- for(uword i = 0; i < N_old; ++i)
- {
- if(vals[i] != eT(0))
- {
- filtered_vals[index] = vals[i];
-
- filtered_locs.at(0, index) = locs.at(0, i);
- filtered_locs.at(1, index) = locs.at(1, i);
-
- ++index;
- }
- }
-
- init_batch_std(filtered_locs, filtered_vals, sort_locations);
- }
- else
- {
- init_batch_std(locs, vals, sort_locations);
- }
- }
- else
- {
- init_batch_std(locs, vals, sort_locations);
- }
- }
- template<typename eT>
- template<typename T1, typename T2>
- inline
- SpMat<eT>::SpMat(const bool add_values, const Base<uword,T1>& locations_expr, const Base<eT,T2>& vals_expr, const uword in_n_rows, const uword in_n_cols, const bool sort_locations, const bool check_for_zeros)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- const unwrap<T1> locs_tmp( locations_expr.get_ref() );
- const unwrap<T2> vals_tmp( vals_expr.get_ref() );
-
- const Mat<uword>& locs = locs_tmp.M;
- const Mat<eT>& vals = vals_tmp.M;
-
- arma_debug_check( (vals.is_vec() == false), "SpMat::SpMat(): given 'values' object is not a vector" );
- arma_debug_check( (locs.n_rows != 2), "SpMat::SpMat(): locations matrix must have two rows" );
- arma_debug_check( (locs.n_cols != vals.n_elem), "SpMat::SpMat(): number of locations is different than number of values" );
-
- init_cold(in_n_rows, in_n_cols);
-
- // Ensure that there are no zeros, unless the user asked not to.
- if(check_for_zeros)
- {
- const uword N_old = vals.n_elem;
- uword N_new = 0;
-
- for(uword i = 0; i < N_old; ++i)
- {
- if(vals[i] != eT(0)) { ++N_new; }
- }
-
- if(N_new != N_old)
- {
- Col<eT> filtered_vals(N_new);
- Mat<uword> filtered_locs(2, N_new);
-
- uword index = 0;
- for(uword i = 0; i < N_old; ++i)
- {
- if(vals[i] != eT(0))
- {
- filtered_vals[index] = vals[i];
-
- filtered_locs.at(0, index) = locs.at(0, i);
- filtered_locs.at(1, index) = locs.at(1, i);
-
- ++index;
- }
- }
-
- add_values ? init_batch_add(filtered_locs, filtered_vals, sort_locations) : init_batch_std(filtered_locs, filtered_vals, sort_locations);
- }
- else
- {
- add_values ? init_batch_add(locs, vals, sort_locations) : init_batch_std(locs, vals, sort_locations);
- }
- }
- else
- {
- add_values ? init_batch_add(locs, vals, sort_locations) : init_batch_std(locs, vals, sort_locations);
- }
- }
- //! Insert a large number of values at once.
- //! Per CSC format, rowind_expr should be row indices,
- //! colptr_expr should column ptr indices locations,
- //! and values should be the corresponding values.
- //! In this constructor the size is explicitly given.
- //! Values are assumed to be sorted, and the size
- //! information is trusted
- template<typename eT>
- template<typename T1, typename T2, typename T3>
- inline
- SpMat<eT>::SpMat
- (
- const Base<uword,T1>& rowind_expr,
- const Base<uword,T2>& colptr_expr,
- const Base<eT, T3>& values_expr,
- const uword in_n_rows,
- const uword in_n_cols
- )
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- const unwrap<T1> rowind_tmp( rowind_expr.get_ref() );
- const unwrap<T2> colptr_tmp( colptr_expr.get_ref() );
- const unwrap<T3> vals_tmp( values_expr.get_ref() );
-
- const Mat<uword>& rowind = rowind_tmp.M;
- const Mat<uword>& colptr = colptr_tmp.M;
- const Mat<eT>& vals = vals_tmp.M;
-
- arma_debug_check( (rowind.is_vec() == false), "SpMat::SpMat(): given 'rowind' object is not a vector" );
- arma_debug_check( (colptr.is_vec() == false), "SpMat::SpMat(): given 'colptr' object is not a vector" );
- arma_debug_check( (vals.is_vec() == false), "SpMat::SpMat(): given 'values' object is not a vector" );
-
- // Resize to correct number of elements (this also sets n_nonzero)
- init_cold(in_n_rows, in_n_cols, vals.n_elem);
-
- arma_debug_check( (rowind.n_elem != vals.n_elem), "SpMat::SpMat(): number of row indices is not equal to number of values" );
- arma_debug_check( (colptr.n_elem != (n_cols+1) ), "SpMat::SpMat(): number of column pointers is not equal to n_cols+1" );
-
- // copy supplied values into sparse matrix -- not checked for consistency
- arrayops::copy(access::rwp(row_indices), rowind.memptr(), rowind.n_elem );
- arrayops::copy(access::rwp(col_ptrs), colptr.memptr(), colptr.n_elem );
- arrayops::copy(access::rwp(values), vals.memptr(), vals.n_elem );
-
- // important: set the sentinel as well
- access::rw(col_ptrs[n_cols + 1]) = std::numeric_limits<uword>::max();
-
- // make sure no zeros are stored
- remove_zeros();
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const eT val)
- {
- arma_extra_debug_sigprint();
-
- if(val != eT(0))
- {
- // Resize to 1x1 then set that to the right value.
- init(1, 1, 1); // Sets col_ptrs to 0.
-
- // Manually set element.
- access::rw(values[0]) = val;
- access::rw(row_indices[0]) = 0;
- access::rw(col_ptrs[1]) = 1;
- }
- else
- {
- init(0, 0);
- }
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator*=(const eT val)
- {
- arma_extra_debug_sigprint();
-
- if(val != eT(0))
- {
- sync_csc();
- invalidate_cache();
-
- const uword n_nz = n_nonzero;
-
- eT* vals = access::rwp(values);
-
- bool has_zero = false;
-
- for(uword i=0; i<n_nz; ++i)
- {
- eT& vals_i = vals[i];
-
- vals_i *= val;
-
- if(vals_i == eT(0)) { has_zero = true; }
- }
-
- if(has_zero) { remove_zeros(); }
- }
- else
- {
- (*this).zeros();
- }
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator/=(const eT val)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( (val == eT(0)), "element-wise division: division by zero" );
-
- sync_csc();
- invalidate_cache();
-
- const uword n_nz = n_nonzero;
-
- eT* vals = access::rwp(values);
-
- bool has_zero = false;
-
- for(uword i=0; i<n_nz; ++i)
- {
- eT& vals_i = vals[i];
-
- vals_i /= val;
-
- if(vals_i == eT(0)) { has_zero = true; }
- }
-
- if(has_zero) { remove_zeros(); }
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const SpMat<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- init(x);
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator+=(const SpMat<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- SpMat<eT> out = (*this) + x;
-
- steal_mem(out);
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator-=(const SpMat<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- SpMat<eT> out = (*this) - x;
-
- steal_mem(out);
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator*=(const SpMat<eT>& y)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- SpMat<eT> z = (*this) * y;
-
- steal_mem(z);
-
- return *this;
- }
- // This is in-place element-wise matrix multiplication.
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator%=(const SpMat<eT>& y)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- SpMat<eT> z = (*this) % y;
-
- steal_mem(z);
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator/=(const SpMat<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- // NOTE: use of this function is not advised; it is implemented only for completeness
-
- arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element-wise division");
-
- for(uword c = 0; c < n_cols; ++c)
- for(uword r = 0; r < n_rows; ++r)
- {
- at(r, c) /= x.at(r, c);
- }
-
- return *this;
- }
- template<typename eT>
- template<typename T1, typename op_type>
- inline
- SpMat<eT>::SpMat(const SpToDOp<T1, op_type>& expr)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- typedef typename T1::elem_type T;
-
- // Make sure the type is compatible.
- arma_type_check(( is_same_type< eT, T >::no ));
-
- op_type::apply(*this, expr);
- }
- // Construct a complex matrix out of two non-complex matrices
- template<typename eT>
- template<typename T1, typename T2>
- inline
- SpMat<eT>::SpMat
- (
- const SpBase<typename SpMat<eT>::pod_type, T1>& A,
- const SpBase<typename SpMat<eT>::pod_type, T2>& B
- )
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint();
-
- typedef typename T1::elem_type T;
-
- // Make sure eT is complex and T is not (compile-time check).
- arma_type_check(( is_cx<eT>::no ));
- arma_type_check(( is_cx< T>::yes ));
-
- // Compile-time abort if types are not compatible.
- arma_type_check(( is_same_type< std::complex<T>, eT >::no ));
-
- const unwrap_spmat<T1> tmp1(A.get_ref());
- const unwrap_spmat<T2> tmp2(B.get_ref());
-
- const SpMat<T>& X = tmp1.M;
- const SpMat<T>& Y = tmp2.M;
-
- arma_debug_assert_same_size(X.n_rows, X.n_cols, Y.n_rows, Y.n_cols, "SpMat()");
-
- const uword l_n_rows = X.n_rows;
- const uword l_n_cols = X.n_cols;
-
- // Set size of matrix correctly.
- init_cold(l_n_rows, l_n_cols, n_unique(X, Y, op_n_unique_count()));
-
- // Now on a second iteration, fill it.
- typename SpMat<T>::const_iterator x_it = X.begin();
- typename SpMat<T>::const_iterator x_end = X.end();
-
- typename SpMat<T>::const_iterator y_it = Y.begin();
- typename SpMat<T>::const_iterator y_end = Y.end();
-
- uword cur_pos = 0;
-
- while((x_it != x_end) || (y_it != y_end))
- {
- if(x_it == y_it) // if we are at the same place
- {
- access::rw(values[cur_pos]) = std::complex<T>((T) *x_it, (T) *y_it);
- access::rw(row_indices[cur_pos]) = x_it.row();
- ++access::rw(col_ptrs[x_it.col() + 1]);
-
- ++x_it;
- ++y_it;
- }
- else
- {
- if((x_it.col() < y_it.col()) || ((x_it.col() == y_it.col()) && (x_it.row() < y_it.row()))) // if y is closer to the end
- {
- access::rw(values[cur_pos]) = std::complex<T>((T) *x_it, T(0));
- access::rw(row_indices[cur_pos]) = x_it.row();
- ++access::rw(col_ptrs[x_it.col() + 1]);
-
- ++x_it;
- }
- else // x is closer to the end
- {
- access::rw(values[cur_pos]) = std::complex<T>(T(0), (T) *y_it);
- access::rw(row_indices[cur_pos]) = y_it.row();
- ++access::rw(col_ptrs[y_it.col() + 1]);
-
- ++y_it;
- }
- }
-
- ++cur_pos;
- }
-
- // Now fix the column pointers; they are supposed to be a sum.
- for(uword c = 1; c <= n_cols; ++c)
- {
- access::rw(col_ptrs[c]) += col_ptrs[c - 1];
- }
-
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>::SpMat(const Base<eT, T1>& x)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- (*this).operator=(x);
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const Base<eT, T1>& expr)
- {
- arma_extra_debug_sigprint();
-
- if(is_same_type< T1, Gen<Mat<eT>, gen_zeros> >::yes)
- {
- const Proxy<T1> P(expr.get_ref());
-
- (*this).zeros( P.get_n_rows(), P.get_n_cols() );
-
- return *this;
- }
-
- if(is_same_type< T1, Gen<Mat<eT>, gen_eye> >::yes)
- {
- const Proxy<T1> P(expr.get_ref());
-
- (*this).eye( P.get_n_rows(), P.get_n_cols() );
-
- return *this;
- }
-
- const quasi_unwrap<T1> tmp(expr.get_ref());
- const Mat<eT>& x = tmp.M;
-
- const uword x_n_rows = x.n_rows;
- const uword x_n_cols = x.n_cols;
- const uword x_n_elem = x.n_elem;
-
- // Count number of nonzero elements in base object.
- uword n = 0;
-
- const eT* x_mem = x.memptr();
-
- for(uword i = 0; i < x_n_elem; ++i)
- {
- n += (x_mem[i] != eT(0)) ? uword(1) : uword(0);
- }
-
- init(x_n_rows, x_n_cols, n);
-
- if(n == 0) { return *this; }
-
- // Now the memory is resized correctly; set nonzero elements.
- n = 0;
- for(uword j = 0; j < x_n_cols; ++j)
- for(uword i = 0; i < x_n_rows; ++i)
- {
- const eT val = (*x_mem); x_mem++;
-
- if(val != eT(0))
- {
- access::rw(values[n]) = val;
- access::rw(row_indices[n]) = i;
- access::rw(col_ptrs[j + 1])++;
- ++n;
- }
- }
-
- // Sum column counts to be column pointers.
- for(uword c = 1; c <= n_cols; ++c)
- {
- access::rw(col_ptrs[c]) += col_ptrs[c - 1];
- }
-
- return *this;
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator+=(const Base<eT, T1>& x)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- return (*this).operator=( (*this) + x.get_ref() );
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator-=(const Base<eT, T1>& x)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- return (*this).operator=( (*this) - x.get_ref() );
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator*=(const Base<eT, T1>& y)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const Proxy<T1> p(y.get_ref());
-
- arma_debug_assert_mul_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "matrix multiplication");
-
- // We assume the matrix structure is such that we will end up with a sparse
- // matrix. Assuming that every entry in the dense matrix is nonzero (which is
- // a fairly valid assumption), each row with any nonzero elements in it (in this
- // matrix) implies an entire nonzero column. Therefore, we iterate over all
- // the row_indices and count the number of rows with any elements in them
- // (using the quasi-linked-list idea from SYMBMM -- see spglue_times_meat.hpp).
- podarray<uword> index(n_rows);
- index.fill(n_rows); // Fill with invalid links.
-
- uword last_index = n_rows + 1;
- for(uword i = 0; i < n_nonzero; ++i)
- {
- if(index[row_indices[i]] == n_rows)
- {
- index[row_indices[i]] = last_index;
- last_index = row_indices[i];
- }
- }
-
- // Now count the number of rows which have nonzero elements.
- uword nonzero_rows = 0;
- while(last_index != n_rows + 1)
- {
- ++nonzero_rows;
- last_index = index[last_index];
- }
-
- SpMat<eT> z(arma_reserve_indicator(), n_rows, p.get_n_cols(), (nonzero_rows * p.get_n_cols())); // upper bound on size
-
- // Now we have to fill all the elements using a modification of the NUMBMM algorithm.
- uword cur_pos = 0;
-
- podarray<eT> partial_sums(n_rows);
- partial_sums.zeros();
-
- for(uword lcol = 0; lcol < n_cols; ++lcol)
- {
- const_iterator it = begin();
- const_iterator it_end = end();
-
- while(it != it_end)
- {
- const eT value = (*it);
-
- partial_sums[it.row()] += (value * p.at(it.col(), lcol));
-
- ++it;
- }
-
- // Now add all partial sums to the matrix.
- for(uword i = 0; i < n_rows; ++i)
- {
- if(partial_sums[i] != eT(0))
- {
- access::rw(z.values[cur_pos]) = partial_sums[i];
- access::rw(z.row_indices[cur_pos]) = i;
- ++access::rw(z.col_ptrs[lcol + 1]);
- //printf("colptr %d now %d\n", lcol + 1, z.col_ptrs[lcol + 1]);
- ++cur_pos;
- partial_sums[i] = 0; // Would it be faster to do this in batch later?
- }
- }
- }
-
- // Now fix the column pointers.
- for(uword c = 1; c <= z.n_cols; ++c)
- {
- access::rw(z.col_ptrs[c]) += z.col_ptrs[c - 1];
- }
-
- // Resize to final correct size.
- z.mem_resize(z.col_ptrs[z.n_cols]);
-
- // Now take the memory of the temporary matrix.
- steal_mem(z);
-
- return *this;
- }
- /**
- * Don't use this function. It's not mathematically well-defined and wastes
- * cycles to trash all your data. This is dumb.
- */
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator/=(const Base<eT, T1>& x)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- SpMat<eT> tmp = (*this) / x.get_ref();
-
- steal_mem(tmp);
-
- return *this;
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator%=(const Base<eT, T1>& x)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const Proxy<T1> p(x.get_ref());
-
- arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(), "element-wise multiplication");
-
- // Count the number of elements we will need.
- const_iterator it = begin();
- const_iterator it_end = end();
-
- uword new_n_nonzero = 0;
-
- while(it != it_end)
- {
- // use_at == false can't save us any work here
- if(((*it) * p.at(it.row(), it.col())) != eT(0))
- {
- ++new_n_nonzero;
- }
- ++it;
- }
-
- SpMat<eT> tmp(arma_reserve_indicator(), n_rows, n_cols, new_n_nonzero);
-
- const_iterator c_it = begin();
- const_iterator c_it_end = end();
-
- uword cur_pos = 0;
-
- while(c_it != c_it_end)
- {
- // use_at == false can't save us any work here
- const eT val = (*c_it) * p.at(c_it.row(), c_it.col());
- if(val != eT(0))
- {
- access::rw(tmp.values[cur_pos]) = val;
- access::rw(tmp.row_indices[cur_pos]) = c_it.row();
- ++access::rw(tmp.col_ptrs[c_it.col() + 1]);
- ++cur_pos;
- }
- ++c_it;
- }
-
- // Fix column pointers.
- for(uword c = 1; c <= n_cols; ++c)
- {
- access::rw(tmp.col_ptrs[c]) += tmp.col_ptrs[c - 1];
- }
-
- steal_mem(tmp);
-
- return *this;
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>::SpMat(const Op<T1, op_diagmat>& expr)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
- (*this).operator=(expr);
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const Op<T1, op_diagmat>& expr)
- {
- arma_extra_debug_sigprint();
-
- const diagmat_proxy<T1> P(expr.m);
-
- const uword max_n_nonzero = (std::min)(P.n_rows, P.n_cols);
-
- // resize memory to upper bound
- init(P.n_rows, P.n_cols, max_n_nonzero);
-
- uword count = 0;
-
- for(uword i=0; i < max_n_nonzero; ++i)
- {
- const eT val = P[i];
-
- if(val != eT(0))
- {
- access::rw(values[count]) = val;
- access::rw(row_indices[count]) = i;
- access::rw(col_ptrs[i + 1])++;
- ++count;
- }
- }
-
- // fix column pointers to be cumulative
- for(uword i = 1; i < n_cols + 1; ++i)
- {
- access::rw(col_ptrs[i]) += col_ptrs[i - 1];
- }
-
- // quick resize without reallocating memory and copying data
- access::rw( n_nonzero) = count;
- access::rw( values[count]) = eT(0);
- access::rw(row_indices[count]) = uword(0);
-
- return *this;
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator+=(const Op<T1, op_diagmat>& expr)
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT> tmp(expr);
-
- return (*this).operator+=(tmp);
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator-=(const Op<T1, op_diagmat>& expr)
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT> tmp(expr);
-
- return (*this).operator-=(tmp);
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator*=(const Op<T1, op_diagmat>& expr)
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT> tmp(expr);
-
- return (*this).operator*=(tmp);
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator/=(const Op<T1, op_diagmat>& expr)
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT> tmp(expr);
-
- return (*this).operator/=(tmp);
- }
- template<typename eT>
- template<typename T1>
- inline
- SpMat<eT>&
- SpMat<eT>::operator%=(const Op<T1, op_diagmat>& expr)
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT> tmp(expr);
-
- return (*this).operator%=(tmp);
- }
- /**
- * Functions on subviews.
- */
- template<typename eT>
- inline
- SpMat<eT>::SpMat(const SpSubview<eT>& X)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- (*this).operator=(X);
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const SpSubview<eT>& X)
- {
- arma_extra_debug_sigprint();
-
- if(X.n_nonzero == 0) { zeros(X.n_rows, X.n_cols); return *this; }
-
- X.m.sync_csc();
-
- const bool alias = (this == &(X.m));
-
- if(alias)
- {
- SpMat<eT> tmp(X);
-
- steal_mem(tmp);
- }
- else
- {
- init(X.n_rows, X.n_cols, X.n_nonzero);
-
- if(X.n_rows == X.m.n_rows)
- {
- const uword sv_col_start = X.aux_col1;
- const uword sv_col_end = X.aux_col1 + X.n_cols - 1;
-
- typename SpMat<eT>::const_col_iterator m_it = X.m.begin_col(sv_col_start);
- typename SpMat<eT>::const_col_iterator m_it_end = X.m.end_col(sv_col_end);
-
- uword count = 0;
-
- while(m_it != m_it_end)
- {
- const uword m_it_col_adjusted = m_it.col() - sv_col_start;
-
- access::rw(row_indices[count]) = m_it.row();
- access::rw(values[count]) = (*m_it);
- ++access::rw(col_ptrs[m_it_col_adjusted + 1]);
-
- count++;
-
- ++m_it;
- }
- }
- else
- {
- typename SpSubview<eT>::const_iterator it = X.begin();
- typename SpSubview<eT>::const_iterator it_end = X.end();
-
- while(it != it_end)
- {
- const uword it_pos = it.pos();
-
- access::rw(row_indices[it_pos]) = it.row();
- access::rw(values[it_pos]) = (*it);
- ++access::rw(col_ptrs[it.col() + 1]);
- ++it;
- }
- }
-
- // Now sum column pointers.
- for(uword c = 1; c <= n_cols; ++c)
- {
- access::rw(col_ptrs[c]) += col_ptrs[c - 1];
- }
- }
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator+=(const SpSubview<eT>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- SpMat<eT> tmp = (*this) + X;
-
- steal_mem(tmp);
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator-=(const SpSubview<eT>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- SpMat<eT> tmp = (*this) - X;
-
- steal_mem(tmp);
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator*=(const SpSubview<eT>& y)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- SpMat<eT> z = (*this) * y;
-
- steal_mem(z);
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator%=(const SpSubview<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- SpMat<eT> tmp = (*this) % x;
-
- steal_mem(tmp);
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator/=(const SpSubview<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element-wise division");
-
- // There is no pretty way to do this.
- for(uword elem = 0; elem < n_elem; elem++)
- {
- at(elem) /= x(elem);
- }
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>::SpMat(const spdiagview<eT>& X)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- spdiagview<eT>::extract(*this, X);
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const spdiagview<eT>& X)
- {
- arma_extra_debug_sigprint();
-
- spdiagview<eT>::extract(*this, X);
-
- return *this;
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator+=(const spdiagview<eT>& X)
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT> tmp(X);
-
- return (*this).operator+=(tmp);
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator-=(const spdiagview<eT>& X)
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT> tmp(X);
-
- return (*this).operator-=(tmp);
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator*=(const spdiagview<eT>& X)
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT> tmp(X);
-
- return (*this).operator*=(tmp);
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator%=(const spdiagview<eT>& X)
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT> tmp(X);
-
- return (*this).operator%=(tmp);
- }
- template<typename eT>
- inline
- SpMat<eT>&
- SpMat<eT>::operator/=(const spdiagview<eT>& X)
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT> tmp(X);
-
- return (*this).operator/=(tmp);
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>::SpMat(const SpOp<T1, spop_type>& X)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL) // set in application of sparse operation
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- spop_type::apply(*this, X);
-
- sync_csc(); // in case apply() used element accessors
- invalidate_cache(); // in case apply() modified the CSC representation
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const SpOp<T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- spop_type::apply(*this, X);
-
- sync_csc(); // in case apply() used element accessors
- invalidate_cache(); // in case apply() modified the CSC representation
-
- return *this;
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator+=(const SpOp<T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator+=(m);
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator-=(const SpOp<T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator-=(m);
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator*=(const SpOp<T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator*=(m);
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator%=(const SpOp<T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator%=(m);
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator/=(const SpOp<T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator/=(m);
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>::SpMat(const SpGlue<T1, T2, spglue_type>& X)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- spglue_type::apply(*this, X);
-
- sync_csc(); // in case apply() used element accessors
- invalidate_cache(); // in case apply() modified the CSC representation
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const SpGlue<T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- spglue_type::apply(*this, X);
-
- sync_csc(); // in case apply() used element accessors
- invalidate_cache(); // in case apply() modified the CSC representation
-
- return *this;
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator+=(const SpGlue<T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator+=(m);
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator-=(const SpGlue<T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator-=(m);
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator*=(const SpGlue<T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator*=(m);
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator%=(const SpGlue<T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator%=(m);
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator/=(const SpGlue<T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator/=(m);
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>::SpMat(const mtSpOp<eT, T1, spop_type>& X)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- spop_type::apply(*this, X);
-
- sync_csc(); // in case apply() used element accessors
- invalidate_cache(); // in case apply() modified the CSC representation
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const mtSpOp<eT, T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- spop_type::apply(*this, X);
-
- sync_csc(); // in case apply() used element accessors
- invalidate_cache(); // in case apply() modified the CSC representation
-
- return *this;
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator+=(const mtSpOp<eT, T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator+=(m);
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator-=(const mtSpOp<eT, T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator-=(m);
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator*=(const mtSpOp<eT, T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator*=(m);
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator%=(const mtSpOp<eT, T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator%=(m);
- }
- template<typename eT>
- template<typename T1, typename spop_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator/=(const mtSpOp<eT, T1, spop_type>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator/=(m);
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>::SpMat(const mtSpGlue<eT, T1, T2, spglue_type>& X)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(0)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- spglue_type::apply(*this, X);
-
- sync_csc(); // in case apply() used element accessors
- invalidate_cache(); // in case apply() modified the CSC representation
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator=(const mtSpGlue<eT, T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- spglue_type::apply(*this, X);
-
- sync_csc(); // in case apply() used element accessors
- invalidate_cache(); // in case apply() modified the CSC representation
-
- return *this;
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator+=(const mtSpGlue<eT, T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator+=(m);
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator-=(const mtSpGlue<eT, T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator-=(m);
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator*=(const mtSpGlue<eT, T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator*=(m);
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator%=(const mtSpGlue<eT, T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator%=(m);
- }
- template<typename eT>
- template<typename T1, typename T2, typename spglue_type>
- inline
- SpMat<eT>&
- SpMat<eT>::operator/=(const mtSpGlue<eT, T1, T2, spglue_type>& X)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const SpMat<eT> m(X);
-
- return (*this).operator/=(m);
- }
- template<typename eT>
- arma_inline
- SpSubview_row<eT>
- SpMat<eT>::row(const uword row_num)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check(row_num >= n_rows, "SpMat::row(): out of bounds");
-
- return SpSubview_row<eT>(*this, row_num);
- }
- template<typename eT>
- arma_inline
- const SpSubview_row<eT>
- SpMat<eT>::row(const uword row_num) const
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check(row_num >= n_rows, "SpMat::row(): out of bounds");
-
- return SpSubview_row<eT>(*this, row_num);
- }
- template<typename eT>
- inline
- SpSubview_row<eT>
- SpMat<eT>::operator()(const uword row_num, const span& col_span)
- {
- arma_extra_debug_sigprint();
-
- const bool col_all = col_span.whole;
-
- const uword local_n_cols = n_cols;
-
- const uword in_col1 = col_all ? 0 : col_span.a;
- const uword in_col2 = col_span.b;
- const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
-
- arma_debug_check
- (
- (row_num >= n_rows)
- ||
- ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
- ,
- "SpMat::operator(): indices out of bounds or incorrectly used"
- );
-
- return SpSubview_row<eT>(*this, row_num, in_col1, submat_n_cols);
- }
- template<typename eT>
- inline
- const SpSubview_row<eT>
- SpMat<eT>::operator()(const uword row_num, const span& col_span) const
- {
- arma_extra_debug_sigprint();
-
- const bool col_all = col_span.whole;
-
- const uword local_n_cols = n_cols;
-
- const uword in_col1 = col_all ? 0 : col_span.a;
- const uword in_col2 = col_span.b;
- const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
-
- arma_debug_check
- (
- (row_num >= n_rows)
- ||
- ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
- ,
- "SpMat::operator(): indices out of bounds or incorrectly used"
- );
-
- return SpSubview_row<eT>(*this, row_num, in_col1, submat_n_cols);
- }
- template<typename eT>
- arma_inline
- SpSubview_col<eT>
- SpMat<eT>::col(const uword col_num)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check(col_num >= n_cols, "SpMat::col(): out of bounds");
-
- return SpSubview_col<eT>(*this, col_num);
- }
- template<typename eT>
- arma_inline
- const SpSubview_col<eT>
- SpMat<eT>::col(const uword col_num) const
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check(col_num >= n_cols, "SpMat::col(): out of bounds");
-
- return SpSubview_col<eT>(*this, col_num);
- }
- template<typename eT>
- inline
- SpSubview_col<eT>
- SpMat<eT>::operator()(const span& row_span, const uword col_num)
- {
- arma_extra_debug_sigprint();
-
- const bool row_all = row_span.whole;
-
- const uword local_n_rows = n_rows;
-
- const uword in_row1 = row_all ? 0 : row_span.a;
- const uword in_row2 = row_span.b;
- const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
-
- arma_debug_check
- (
- (col_num >= n_cols)
- ||
- ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
- ,
- "SpMat::operator(): indices out of bounds or incorrectly used"
- );
-
- return SpSubview_col<eT>(*this, col_num, in_row1, submat_n_rows);
- }
- template<typename eT>
- inline
- const SpSubview_col<eT>
- SpMat<eT>::operator()(const span& row_span, const uword col_num) const
- {
- arma_extra_debug_sigprint();
-
- const bool row_all = row_span.whole;
-
- const uword local_n_rows = n_rows;
-
- const uword in_row1 = row_all ? 0 : row_span.a;
- const uword in_row2 = row_span.b;
- const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
-
- arma_debug_check
- (
- (col_num >= n_cols)
- ||
- ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
- ,
- "SpMat::operator(): indices out of bounds or incorrectly used"
- );
-
- return SpSubview_col<eT>(*this, col_num, in_row1, submat_n_rows);
- }
- template<typename eT>
- arma_inline
- SpSubview<eT>
- SpMat<eT>::rows(const uword in_row1, const uword in_row2)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check
- (
- (in_row1 > in_row2) || (in_row2 >= n_rows),
- "SpMat::rows(): indices out of bounds or incorrectly used"
- );
-
- const uword subview_n_rows = in_row2 - in_row1 + 1;
-
- return SpSubview<eT>(*this, in_row1, 0, subview_n_rows, n_cols);
- }
- template<typename eT>
- arma_inline
- const SpSubview<eT>
- SpMat<eT>::rows(const uword in_row1, const uword in_row2) const
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check
- (
- (in_row1 > in_row2) || (in_row2 >= n_rows),
- "SpMat::rows(): indices out of bounds or incorrectly used"
- );
-
- const uword subview_n_rows = in_row2 - in_row1 + 1;
-
- return SpSubview<eT>(*this, in_row1, 0, subview_n_rows, n_cols);
- }
- template<typename eT>
- arma_inline
- SpSubview<eT>
- SpMat<eT>::cols(const uword in_col1, const uword in_col2)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check
- (
- (in_col1 > in_col2) || (in_col2 >= n_cols),
- "SpMat::cols(): indices out of bounds or incorrectly used"
- );
-
- const uword subview_n_cols = in_col2 - in_col1 + 1;
-
- return SpSubview<eT>(*this, 0, in_col1, n_rows, subview_n_cols);
- }
- template<typename eT>
- arma_inline
- const SpSubview<eT>
- SpMat<eT>::cols(const uword in_col1, const uword in_col2) const
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check
- (
- (in_col1 > in_col2) || (in_col2 >= n_cols),
- "SpMat::cols(): indices out of bounds or incorrectly used"
- );
-
- const uword subview_n_cols = in_col2 - in_col1 + 1;
-
- return SpSubview<eT>(*this, 0, in_col1, n_rows, subview_n_cols);
- }
- template<typename eT>
- arma_inline
- SpSubview<eT>
- SpMat<eT>::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check
- (
- (in_row1 > in_row2) || (in_col1 > in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols),
- "SpMat::submat(): indices out of bounds or incorrectly used"
- );
-
- const uword subview_n_rows = in_row2 - in_row1 + 1;
- const uword subview_n_cols = in_col2 - in_col1 + 1;
-
- return SpSubview<eT>(*this, in_row1, in_col1, subview_n_rows, subview_n_cols);
- }
- template<typename eT>
- arma_inline
- const SpSubview<eT>
- SpMat<eT>::submat(const uword in_row1, const uword in_col1, const uword in_row2, const uword in_col2) const
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check
- (
- (in_row1 > in_row2) || (in_col1 > in_col2) || (in_row2 >= n_rows) || (in_col2 >= n_cols),
- "SpMat::submat(): indices out of bounds or incorrectly used"
- );
-
- const uword subview_n_rows = in_row2 - in_row1 + 1;
- const uword subview_n_cols = in_col2 - in_col1 + 1;
-
- return SpSubview<eT>(*this, in_row1, in_col1, subview_n_rows, subview_n_cols);
- }
- template<typename eT>
- arma_inline
- SpSubview<eT>
- SpMat<eT>::submat(const uword in_row1, const uword in_col1, const SizeMat& s)
- {
- arma_extra_debug_sigprint();
-
- const uword l_n_rows = n_rows;
- const uword l_n_cols = n_cols;
-
- const uword s_n_rows = s.n_rows;
- const uword s_n_cols = s.n_cols;
-
- arma_debug_check
- (
- ((in_row1 >= l_n_rows) || (in_col1 >= l_n_cols) || ((in_row1 + s_n_rows) > l_n_rows) || ((in_col1 + s_n_cols) > l_n_cols)),
- "SpMat::submat(): indices or size out of bounds"
- );
-
- return SpSubview<eT>(*this, in_row1, in_col1, s_n_rows, s_n_cols);
- }
- template<typename eT>
- arma_inline
- const SpSubview<eT>
- SpMat<eT>::submat(const uword in_row1, const uword in_col1, const SizeMat& s) const
- {
- arma_extra_debug_sigprint();
-
- const uword l_n_rows = n_rows;
- const uword l_n_cols = n_cols;
-
- const uword s_n_rows = s.n_rows;
- const uword s_n_cols = s.n_cols;
-
- arma_debug_check
- (
- ((in_row1 >= l_n_rows) || (in_col1 >= l_n_cols) || ((in_row1 + s_n_rows) > l_n_rows) || ((in_col1 + s_n_cols) > l_n_cols)),
- "SpMat::submat(): indices or size out of bounds"
- );
-
- return SpSubview<eT>(*this, in_row1, in_col1, s_n_rows, s_n_cols);
- }
- template<typename eT>
- inline
- SpSubview<eT>
- SpMat<eT>::submat(const span& row_span, const span& col_span)
- {
- arma_extra_debug_sigprint();
-
- const bool row_all = row_span.whole;
- const bool col_all = col_span.whole;
-
- const uword local_n_rows = n_rows;
- const uword local_n_cols = n_cols;
-
- const uword in_row1 = row_all ? 0 : row_span.a;
- const uword in_row2 = row_span.b;
- const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
-
- const uword in_col1 = col_all ? 0 : col_span.a;
- const uword in_col2 = col_span.b;
- const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
-
- arma_debug_check
- (
- ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
- ||
- ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
- ,
- "SpMat::submat(): indices out of bounds or incorrectly used"
- );
-
- return SpSubview<eT>(*this, in_row1, in_col1, submat_n_rows, submat_n_cols);
- }
- template<typename eT>
- inline
- const SpSubview<eT>
- SpMat<eT>::submat(const span& row_span, const span& col_span) const
- {
- arma_extra_debug_sigprint();
-
- const bool row_all = row_span.whole;
- const bool col_all = col_span.whole;
-
- const uword local_n_rows = n_rows;
- const uword local_n_cols = n_cols;
-
- const uword in_row1 = row_all ? 0 : row_span.a;
- const uword in_row2 = row_span.b;
- const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 + 1;
-
- const uword in_col1 = col_all ? 0 : col_span.a;
- const uword in_col2 = col_span.b;
- const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 + 1;
-
- arma_debug_check
- (
- ( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows)) )
- ||
- ( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols)) )
- ,
- "SpMat::submat(): indices out of bounds or incorrectly used"
- );
-
- return SpSubview<eT>(*this, in_row1, in_col1, submat_n_rows, submat_n_cols);
- }
- template<typename eT>
- inline
- SpSubview<eT>
- SpMat<eT>::operator()(const span& row_span, const span& col_span)
- {
- arma_extra_debug_sigprint();
-
- return submat(row_span, col_span);
- }
- template<typename eT>
- inline
- const SpSubview<eT>
- SpMat<eT>::operator()(const span& row_span, const span& col_span) const
- {
- arma_extra_debug_sigprint();
-
- return submat(row_span, col_span);
- }
- template<typename eT>
- arma_inline
- SpSubview<eT>
- SpMat<eT>::operator()(const uword in_row1, const uword in_col1, const SizeMat& s)
- {
- arma_extra_debug_sigprint();
-
- return (*this).submat(in_row1, in_col1, s);
- }
- template<typename eT>
- arma_inline
- const SpSubview<eT>
- SpMat<eT>::operator()(const uword in_row1, const uword in_col1, const SizeMat& s) const
- {
- arma_extra_debug_sigprint();
-
- return (*this).submat(in_row1, in_col1, s);
- }
- template<typename eT>
- inline
- SpSubview<eT>
- SpMat<eT>::head_rows(const uword N)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( (N > n_rows), "SpMat::head_rows(): size out of bounds");
-
- return SpSubview<eT>(*this, 0, 0, N, n_cols);
- }
- template<typename eT>
- inline
- const SpSubview<eT>
- SpMat<eT>::head_rows(const uword N) const
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( (N > n_rows), "SpMat::head_rows(): size out of bounds");
-
- return SpSubview<eT>(*this, 0, 0, N, n_cols);
- }
- template<typename eT>
- inline
- SpSubview<eT>
- SpMat<eT>::tail_rows(const uword N)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( (N > n_rows), "SpMat::tail_rows(): size out of bounds");
-
- const uword start_row = n_rows - N;
-
- return SpSubview<eT>(*this, start_row, 0, N, n_cols);
- }
- template<typename eT>
- inline
- const SpSubview<eT>
- SpMat<eT>::tail_rows(const uword N) const
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( (N > n_rows), "SpMat::tail_rows(): size out of bounds");
-
- const uword start_row = n_rows - N;
-
- return SpSubview<eT>(*this, start_row, 0, N, n_cols);
- }
- template<typename eT>
- inline
- SpSubview<eT>
- SpMat<eT>::head_cols(const uword N)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( (N > n_cols), "SpMat::head_cols(): size out of bounds");
-
- return SpSubview<eT>(*this, 0, 0, n_rows, N);
- }
- template<typename eT>
- inline
- const SpSubview<eT>
- SpMat<eT>::head_cols(const uword N) const
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( (N > n_cols), "SpMat::head_cols(): size out of bounds");
-
- return SpSubview<eT>(*this, 0, 0, n_rows, N);
- }
- template<typename eT>
- inline
- SpSubview<eT>
- SpMat<eT>::tail_cols(const uword N)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( (N > n_cols), "SpMat::tail_cols(): size out of bounds");
-
- const uword start_col = n_cols - N;
-
- return SpSubview<eT>(*this, 0, start_col, n_rows, N);
- }
- template<typename eT>
- inline
- const SpSubview<eT>
- SpMat<eT>::tail_cols(const uword N) const
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( (N > n_cols), "SpMat::tail_cols(): size out of bounds");
-
- const uword start_col = n_cols - N;
-
- return SpSubview<eT>(*this, 0, start_col, n_rows, N);
- }
- //! creation of spdiagview (diagonal)
- template<typename eT>
- inline
- spdiagview<eT>
- SpMat<eT>::diag(const sword in_id)
- {
- arma_extra_debug_sigprint();
-
- const uword row_offset = (in_id < 0) ? uword(-in_id) : 0;
- const uword col_offset = (in_id > 0) ? uword( in_id) : 0;
-
- arma_debug_check
- (
- ((row_offset > 0) && (row_offset >= n_rows)) || ((col_offset > 0) && (col_offset >= n_cols)),
- "SpMat::diag(): requested diagonal out of bounds"
- );
-
- const uword len = (std::min)(n_rows - row_offset, n_cols - col_offset);
-
- return spdiagview<eT>(*this, row_offset, col_offset, len);
- }
- //! creation of spdiagview (diagonal)
- template<typename eT>
- inline
- const spdiagview<eT>
- SpMat<eT>::diag(const sword in_id) const
- {
- arma_extra_debug_sigprint();
-
- const uword row_offset = uword( (in_id < 0) ? -in_id : 0 );
- const uword col_offset = uword( (in_id > 0) ? in_id : 0 );
-
- arma_debug_check
- (
- ((row_offset > 0) && (row_offset >= n_rows)) || ((col_offset > 0) && (col_offset >= n_cols)),
- "SpMat::diag(): requested diagonal out of bounds"
- );
-
- const uword len = (std::min)(n_rows - row_offset, n_cols - col_offset);
-
- return spdiagview<eT>(*this, row_offset, col_offset, len);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::swap_rows(const uword in_row1, const uword in_row2)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( ((in_row1 >= n_rows) || (in_row2 >= n_rows)), "SpMat::swap_rows(): out of bounds" );
-
- if(in_row1 == in_row2) { return; }
-
- sync_csc();
- invalidate_cache();
-
- // The easier way to do this, instead of collecting all the elements in one row and then swapping with the other, will be
- // to iterate over each column of the matrix (since we store in column-major format) and then swap the two elements in the two rows at that time.
- // We will try to avoid using the at() call since it is expensive, instead preferring to use an iterator to track our position.
- uword col1 = (in_row1 < in_row2) ? in_row1 : in_row2;
- uword col2 = (in_row1 < in_row2) ? in_row2 : in_row1;
-
- for(uword lcol = 0; lcol < n_cols; lcol++)
- {
- // If there is nothing in this column we can ignore it.
- if(col_ptrs[lcol] == col_ptrs[lcol + 1])
- {
- continue;
- }
-
- // These will represent the positions of the items themselves.
- uword loc1 = n_nonzero + 1;
- uword loc2 = n_nonzero + 1;
-
- for(uword search_pos = col_ptrs[lcol]; search_pos < col_ptrs[lcol + 1]; search_pos++)
- {
- if(row_indices[search_pos] == col1)
- {
- loc1 = search_pos;
- }
-
- if(row_indices[search_pos] == col2)
- {
- loc2 = search_pos;
- break; // No need to look any further.
- }
- }
-
- // There are four cases: we found both elements; we found one element (loc1); we found one element (loc2); we found zero elements.
- // If we found zero elements no work needs to be done and we can continue to the next column.
- if((loc1 != (n_nonzero + 1)) && (loc2 != (n_nonzero + 1)))
- {
- // This is an easy case: just swap the values. No index modifying necessary.
- eT tmp = values[loc1];
- access::rw(values[loc1]) = values[loc2];
- access::rw(values[loc2]) = tmp;
- }
- else if(loc1 != (n_nonzero + 1)) // We only found loc1 and not loc2.
- {
- // We need to find the correct place to move our value to. It will be forward (not backwards) because in_row2 > in_row1.
- // Each iteration of the loop swaps the current value (loc1) with (loc1 + 1); in this manner we move our value down to where it should be.
- while(((loc1 + 1) < col_ptrs[lcol + 1]) && (row_indices[loc1 + 1] < in_row2))
- {
- // Swap both the values and the indices. The column should not change.
- eT tmp = values[loc1];
- access::rw(values[loc1]) = values[loc1 + 1];
- access::rw(values[loc1 + 1]) = tmp;
-
- uword tmp_index = row_indices[loc1];
- access::rw(row_indices[loc1]) = row_indices[loc1 + 1];
- access::rw(row_indices[loc1 + 1]) = tmp_index;
-
- loc1++; // And increment the counter.
- }
-
- // Now set the row index correctly.
- access::rw(row_indices[loc1]) = in_row2;
-
- }
- else if(loc2 != (n_nonzero + 1))
- {
- // We need to find the correct place to move our value to. It will be backwards (not forwards) because in_row1 < in_row2.
- // Each iteration of the loop swaps the current value (loc2) with (loc2 - 1); in this manner we move our value up to where it should be.
- while(((loc2 - 1) >= col_ptrs[lcol]) && (row_indices[loc2 - 1] > in_row1))
- {
- // Swap both the values and the indices. The column should not change.
- eT tmp = values[loc2];
- access::rw(values[loc2]) = values[loc2 - 1];
- access::rw(values[loc2 - 1]) = tmp;
-
- uword tmp_index = row_indices[loc2];
- access::rw(row_indices[loc2]) = row_indices[loc2 - 1];
- access::rw(row_indices[loc2 - 1]) = tmp_index;
-
- loc2--; // And decrement the counter.
- }
-
- // Now set the row index correctly.
- access::rw(row_indices[loc2]) = in_row1;
-
- }
- /* else: no need to swap anything; both values are zero */
- }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::swap_cols(const uword in_col1, const uword in_col2)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( ((in_col1 >= n_cols) || (in_col2 >= n_cols)), "SpMat::swap_cols(): out of bounds" );
-
- if(in_col1 == in_col2) { return; }
-
- // TODO: this is a rudimentary implementation
-
- SpMat<eT> tmp = (*this);
-
- tmp.col(in_col1) = (*this).col(in_col2);
- tmp.col(in_col2) = (*this).col(in_col1);
-
- steal_mem(tmp);
-
- // for(uword lrow = 0; lrow < n_rows; ++lrow)
- // {
- // const eT tmp = at(lrow, in_col1);
- // at(lrow, in_col1) = eT( at(lrow, in_col2) );
- // at(lrow, in_col2) = tmp;
- // }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::shed_row(const uword row_num)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check (row_num >= n_rows, "SpMat::shed_row(): out of bounds");
-
- shed_rows (row_num, row_num);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::shed_col(const uword col_num)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check (col_num >= n_cols, "SpMat::shed_col(): out of bounds");
-
- shed_cols(col_num, col_num);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::shed_rows(const uword in_row1, const uword in_row2)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check
- (
- (in_row1 > in_row2) || (in_row2 >= n_rows),
- "SpMat::shed_rows(): indices out of bounds or incorectly used"
- );
-
- sync_csc();
-
- SpMat<eT> newmat(n_rows - (in_row2 - in_row1 + 1), n_cols);
-
- // First, count the number of elements we will be removing.
- uword removing = 0;
- for(uword i = 0; i < n_nonzero; ++i)
- {
- const uword lrow = row_indices[i];
- if(lrow >= in_row1 && lrow <= in_row2)
- {
- ++removing;
- }
- }
-
- // Obtain counts of the number of points in each column and store them as the
- // (invalid) column pointers of the new matrix.
- for(uword i = 1; i < n_cols + 1; ++i)
- {
- access::rw(newmat.col_ptrs[i]) = col_ptrs[i] - col_ptrs[i - 1];
- }
-
- // Now initialize memory for the new matrix.
- newmat.mem_resize(n_nonzero - removing);
-
- // Now, copy over the elements.
- // i is the index in the old matrix; j is the index in the new matrix.
- const_iterator it = begin();
- const_iterator it_end = end();
-
- uword j = 0; // The index in the new matrix.
- while(it != it_end)
- {
- const uword lrow = it.row();
- const uword lcol = it.col();
-
- if(lrow >= in_row1 && lrow <= in_row2)
- {
- // This element is being removed. Subtract it from the column counts.
- --access::rw(newmat.col_ptrs[lcol + 1]);
- }
- else
- {
- // This element is being kept. We may need to map the row index,
- // if it is past the section of rows we are removing.
- if(lrow > in_row2)
- {
- access::rw(newmat.row_indices[j]) = lrow - (in_row2 - in_row1 + 1);
- }
- else
- {
- access::rw(newmat.row_indices[j]) = lrow;
- }
- access::rw(newmat.values[j]) = (*it);
- ++j; // Increment index in new matrix.
- }
-
- ++it;
- }
-
- // Finally, sum the column counts so they are correct column pointers.
- for(uword i = 1; i < n_cols + 1; ++i)
- {
- access::rw(newmat.col_ptrs[i]) += newmat.col_ptrs[i - 1];
- }
-
- // Now steal the memory of the new matrix.
- steal_mem(newmat);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::shed_cols(const uword in_col1, const uword in_col2)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check
- (
- (in_col1 > in_col2) || (in_col2 >= n_cols),
- "SpMat::shed_cols(): indices out of bounds or incorrectly used"
- );
-
- sync_csc();
- invalidate_cache();
-
- // First we find the locations in values and row_indices for the column entries.
- uword col_beg = col_ptrs[in_col1];
- uword col_end = col_ptrs[in_col2 + 1];
-
- // Then we find the number of entries in the column.
- uword diff = col_end - col_beg;
-
- if(diff > 0)
- {
- eT* new_values = memory::acquire<eT> (n_nonzero - diff);
- uword* new_row_indices = memory::acquire<uword>(n_nonzero - diff);
-
- // Copy first part.
- if(col_beg != 0)
- {
- arrayops::copy(new_values, values, col_beg);
- arrayops::copy(new_row_indices, row_indices, col_beg);
- }
-
- // Copy second part.
- if(col_end != n_nonzero)
- {
- arrayops::copy(new_values + col_beg, values + col_end, n_nonzero - col_end);
- arrayops::copy(new_row_indices + col_beg, row_indices + col_end, n_nonzero - col_end);
- }
-
- if(values) { memory::release(access::rw(values)); }
- if(row_indices) { memory::release(access::rw(row_indices)); }
-
- access::rw(values) = new_values;
- access::rw(row_indices) = new_row_indices;
-
- // Update counts and such.
- access::rw(n_nonzero) -= diff;
- }
-
- // Update column pointers.
- const uword new_n_cols = n_cols - ((in_col2 - in_col1) + 1);
-
- uword* new_col_ptrs = memory::acquire<uword>(new_n_cols + 2);
- new_col_ptrs[new_n_cols + 1] = std::numeric_limits<uword>::max();
-
- // Copy first set of columns (no manipulation required).
- if(in_col1 != 0)
- {
- arrayops::copy(new_col_ptrs, col_ptrs, in_col1);
- }
-
- // Copy second set of columns (manipulation required).
- uword cur_col = in_col1;
- for(uword i = in_col2 + 1; i <= n_cols; ++i, ++cur_col)
- {
- new_col_ptrs[cur_col] = col_ptrs[i] - diff;
- }
-
- if(col_ptrs) { memory::release(access::rw(col_ptrs)); }
- access::rw(col_ptrs) = new_col_ptrs;
-
- // We update the element and column counts, and we're done.
- access::rw(n_cols) = new_n_cols;
- access::rw(n_elem) = n_cols * n_rows;
- }
- /**
- * Element access; acces the i'th element (works identically to the Mat accessors).
- * If there is nothing at element i, 0 is returned.
- */
- template<typename eT>
- arma_inline
- arma_warn_unused
- SpMat_MapMat_val<eT>
- SpMat<eT>::operator[](const uword i)
- {
- const uword in_col = i / n_rows;
- const uword in_row = i % n_rows;
-
- return SpMat_MapMat_val<eT>((*this), cache, in_row, in_col);
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- eT
- SpMat<eT>::operator[](const uword i) const
- {
- return get_value(i);
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- SpMat_MapMat_val<eT>
- SpMat<eT>::at(const uword i)
- {
- const uword in_col = i / n_rows;
- const uword in_row = i % n_rows;
-
- return SpMat_MapMat_val<eT>((*this), cache, in_row, in_col);
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- eT
- SpMat<eT>::at(const uword i) const
- {
- return get_value(i);
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- SpMat_MapMat_val<eT>
- SpMat<eT>::operator()(const uword i)
- {
- arma_debug_check( (i >= n_elem), "SpMat::operator(): out of bounds");
-
- const uword in_col = i / n_rows;
- const uword in_row = i % n_rows;
-
- return SpMat_MapMat_val<eT>((*this), cache, in_row, in_col);
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- eT
- SpMat<eT>::operator()(const uword i) const
- {
- arma_debug_check( (i >= n_elem), "SpMat::operator(): out of bounds");
-
- return get_value(i);
- }
- /**
- * Element access; access the element at row in_rows and column in_col.
- * If there is nothing at that position, 0 is returned.
- */
- template<typename eT>
- arma_inline
- arma_warn_unused
- SpMat_MapMat_val<eT>
- SpMat<eT>::at(const uword in_row, const uword in_col)
- {
- return SpMat_MapMat_val<eT>((*this), cache, in_row, in_col);
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- eT
- SpMat<eT>::at(const uword in_row, const uword in_col) const
- {
- return get_value(in_row, in_col);
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- SpMat_MapMat_val<eT>
- SpMat<eT>::operator()(const uword in_row, const uword in_col)
- {
- arma_debug_check( ((in_row >= n_rows) || (in_col >= n_cols)), "SpMat::operator(): out of bounds");
-
- return SpMat_MapMat_val<eT>((*this), cache, in_row, in_col);
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- eT
- SpMat<eT>::operator()(const uword in_row, const uword in_col) const
- {
- arma_debug_check( ((in_row >= n_rows) || (in_col >= n_cols)), "SpMat::operator(): out of bounds");
-
- return get_value(in_row, in_col);
- }
- /**
- * Check if matrix is empty (no size, no values).
- */
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::is_empty() const
- {
- return (n_elem == 0);
- }
- //! returns true if the object can be interpreted as a column or row vector
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::is_vec() const
- {
- return ( (n_rows == 1) || (n_cols == 1) );
- }
- //! returns true if the object can be interpreted as a row vector
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::is_rowvec() const
- {
- return (n_rows == 1);
- }
- //! returns true if the object can be interpreted as a column vector
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::is_colvec() const
- {
- return (n_cols == 1);
- }
- //! returns true if the object has the same number of non-zero rows and columnns
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::is_square() const
- {
- return (n_rows == n_cols);
- }
- //! returns true if all of the elements are finite
- template<typename eT>
- inline
- arma_warn_unused
- bool
- SpMat<eT>::is_finite() const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- return arrayops::is_finite(values, n_nonzero);
- }
- template<typename eT>
- inline
- arma_warn_unused
- bool
- SpMat<eT>::is_symmetric() const
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT>& A = (*this);
-
- if(A.n_rows != A.n_cols) { return false; }
-
- const SpMat<eT> tmp = A - A.st();
-
- return (tmp.n_nonzero == uword(0));
- }
- template<typename eT>
- inline
- arma_warn_unused
- bool
- SpMat<eT>::is_symmetric(const typename get_pod_type<elem_type>::result tol) const
- {
- arma_extra_debug_sigprint();
-
- typedef typename get_pod_type<eT>::result T;
-
- if(tol == T(0)) { return (*this).is_symmetric(); }
-
- arma_debug_check( (tol < T(0)), "is_symmetric(): parameter 'tol' must be >= 0" );
-
- const SpMat<eT>& A = (*this);
-
- if(A.n_rows != A.n_cols) { return false; }
-
- const T norm_A = as_scalar( arma::max(sum(abs(A), 1), 0) );
-
- if(norm_A == T(0)) { return true; }
-
- const T norm_A_Ast = as_scalar( arma::max(sum(abs(A - A.st()), 1), 0) );
-
- return ( (norm_A_Ast / norm_A) <= tol );
- }
- template<typename eT>
- inline
- arma_warn_unused
- bool
- SpMat<eT>::is_hermitian() const
- {
- arma_extra_debug_sigprint();
-
- const SpMat<eT>& A = (*this);
-
- if(A.n_rows != A.n_cols) { return false; }
-
- const SpMat<eT> tmp = A - A.t();
-
- return (tmp.n_nonzero == uword(0));
- }
- template<typename eT>
- inline
- arma_warn_unused
- bool
- SpMat<eT>::is_hermitian(const typename get_pod_type<elem_type>::result tol) const
- {
- arma_extra_debug_sigprint();
-
- typedef typename get_pod_type<eT>::result T;
-
- if(tol == T(0)) { return (*this).is_hermitian(); }
-
- arma_debug_check( (tol < T(0)), "is_hermitian(): parameter 'tol' must be >= 0" );
-
- const SpMat<eT>& A = (*this);
-
- if(A.n_rows != A.n_cols) { return false; }
-
- const T norm_A = as_scalar( arma::max(sum(abs(A), 1), 0) );
-
- if(norm_A == T(0)) { return true; }
-
- const T norm_A_At = as_scalar( arma::max(sum(abs(A - A.t()), 1), 0) );
-
- return ( (norm_A_At / norm_A) <= tol );
- }
- template<typename eT>
- inline
- arma_warn_unused
- bool
- SpMat<eT>::has_inf() const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- return arrayops::has_inf(values, n_nonzero);
- }
- template<typename eT>
- inline
- arma_warn_unused
- bool
- SpMat<eT>::has_nan() const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- return arrayops::has_nan(values, n_nonzero);
- }
- //! returns true if the given index is currently in range
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::in_range(const uword i) const
- {
- return (i < n_elem);
- }
- //! returns true if the given start and end indices are currently in range
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::in_range(const span& x) const
- {
- arma_extra_debug_sigprint();
-
- if(x.whole == true)
- {
- return true;
- }
- else
- {
- const uword a = x.a;
- const uword b = x.b;
-
- return ( (a <= b) && (b < n_elem) );
- }
- }
- //! returns true if the given location is currently in range
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::in_range(const uword in_row, const uword in_col) const
- {
- return ( (in_row < n_rows) && (in_col < n_cols) );
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::in_range(const span& row_span, const uword in_col) const
- {
- arma_extra_debug_sigprint();
-
- if(row_span.whole == true)
- {
- return (in_col < n_cols);
- }
- else
- {
- const uword in_row1 = row_span.a;
- const uword in_row2 = row_span.b;
-
- return ( (in_row1 <= in_row2) && (in_row2 < n_rows) && (in_col < n_cols) );
- }
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::in_range(const uword in_row, const span& col_span) const
- {
- arma_extra_debug_sigprint();
-
- if(col_span.whole == true)
- {
- return (in_row < n_rows);
- }
- else
- {
- const uword in_col1 = col_span.a;
- const uword in_col2 = col_span.b;
-
- return ( (in_row < n_rows) && (in_col1 <= in_col2) && (in_col2 < n_cols) );
- }
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::in_range(const span& row_span, const span& col_span) const
- {
- arma_extra_debug_sigprint();
-
- const uword in_row1 = row_span.a;
- const uword in_row2 = row_span.b;
-
- const uword in_col1 = col_span.a;
- const uword in_col2 = col_span.b;
-
- const bool rows_ok = row_span.whole ? true : ( (in_row1 <= in_row2) && (in_row2 < n_rows) );
- const bool cols_ok = col_span.whole ? true : ( (in_col1 <= in_col2) && (in_col2 < n_cols) );
-
- return ( (rows_ok == true) && (cols_ok == true) );
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- bool
- SpMat<eT>::in_range(const uword in_row, const uword in_col, const SizeMat& s) const
- {
- const uword l_n_rows = n_rows;
- const uword l_n_cols = n_cols;
-
- if( (in_row >= l_n_rows) || (in_col >= l_n_cols) || ((in_row + s.n_rows) > l_n_rows) || ((in_col + s.n_cols) > l_n_cols) )
- {
- return false;
- }
- else
- {
- return true;
- }
- }
- template<typename eT>
- arma_cold
- inline
- void
- SpMat<eT>::impl_print(const std::string& extra_text) const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- if(extra_text.length() != 0)
- {
- const std::streamsize orig_width = get_cout_stream().width();
-
- get_cout_stream() << extra_text << '\n';
-
- get_cout_stream().width(orig_width);
- }
-
- arma_ostream::print(get_cout_stream(), *this, true);
- }
- template<typename eT>
- arma_cold
- inline
- void
- SpMat<eT>::impl_print(std::ostream& user_stream, const std::string& extra_text) const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- if(extra_text.length() != 0)
- {
- const std::streamsize orig_width = user_stream.width();
-
- user_stream << extra_text << '\n';
-
- user_stream.width(orig_width);
- }
-
- arma_ostream::print(user_stream, *this, true);
- }
- template<typename eT>
- arma_cold
- inline
- void
- SpMat<eT>::impl_raw_print(const std::string& extra_text) const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- if(extra_text.length() != 0)
- {
- const std::streamsize orig_width = get_cout_stream().width();
-
- get_cout_stream() << extra_text << '\n';
-
- get_cout_stream().width(orig_width);
- }
-
- arma_ostream::print(get_cout_stream(), *this, false);
- }
- template<typename eT>
- arma_cold
- inline
- void
- SpMat<eT>::impl_raw_print(std::ostream& user_stream, const std::string& extra_text) const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- if(extra_text.length() != 0)
- {
- const std::streamsize orig_width = user_stream.width();
-
- user_stream << extra_text << '\n';
-
- user_stream.width(orig_width);
- }
-
- arma_ostream::print(user_stream, *this, false);
- }
- /**
- * Matrix printing, prepends supplied text.
- * Prints 0 wherever no element exists.
- */
- template<typename eT>
- arma_cold
- inline
- void
- SpMat<eT>::impl_print_dense(const std::string& extra_text) const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- if(extra_text.length() != 0)
- {
- const std::streamsize orig_width = get_cout_stream().width();
-
- get_cout_stream() << extra_text << '\n';
-
- get_cout_stream().width(orig_width);
- }
-
- arma_ostream::print_dense(get_cout_stream(), *this, true);
- }
- template<typename eT>
- arma_cold
- inline
- void
- SpMat<eT>::impl_print_dense(std::ostream& user_stream, const std::string& extra_text) const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- if(extra_text.length() != 0)
- {
- const std::streamsize orig_width = user_stream.width();
-
- user_stream << extra_text << '\n';
-
- user_stream.width(orig_width);
- }
-
- arma_ostream::print_dense(user_stream, *this, true);
- }
- template<typename eT>
- arma_cold
- inline
- void
- SpMat<eT>::impl_raw_print_dense(const std::string& extra_text) const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- if(extra_text.length() != 0)
- {
- const std::streamsize orig_width = get_cout_stream().width();
-
- get_cout_stream() << extra_text << '\n';
-
- get_cout_stream().width(orig_width);
- }
-
- arma_ostream::print_dense(get_cout_stream(), *this, false);
- }
- template<typename eT>
- arma_cold
- inline
- void
- SpMat<eT>::impl_raw_print_dense(std::ostream& user_stream, const std::string& extra_text) const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- if(extra_text.length() != 0)
- {
- const std::streamsize orig_width = user_stream.width();
-
- user_stream << extra_text << '\n';
-
- user_stream.width(orig_width);
- }
-
- arma_ostream::print_dense(user_stream, *this, false);
- }
- //! Set the size to the size of another matrix.
- template<typename eT>
- template<typename eT2>
- inline
- void
- SpMat<eT>::copy_size(const SpMat<eT2>& m)
- {
- arma_extra_debug_sigprint();
-
- set_size(m.n_rows, m.n_cols);
- }
- template<typename eT>
- template<typename eT2>
- inline
- void
- SpMat<eT>::copy_size(const Mat<eT2>& m)
- {
- arma_extra_debug_sigprint();
-
- set_size(m.n_rows, m.n_cols);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::set_size(const uword in_elem)
- {
- arma_extra_debug_sigprint();
-
- // If this is a row vector, we resize to a row vector.
- if(vec_state == 2)
- {
- set_size(1, in_elem);
- }
- else
- {
- set_size(in_elem, 1);
- }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::set_size(const uword in_rows, const uword in_cols)
- {
- arma_extra_debug_sigprint();
-
- invalidate_cache(); // placed here, as set_size() is used during matrix modification
-
- if( (n_rows == in_rows) && (n_cols == in_cols) )
- {
- return;
- }
- else
- {
- init(in_rows, in_cols);
- }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::set_size(const SizeMat& s)
- {
- arma_extra_debug_sigprint();
-
- (*this).set_size(s.n_rows, s.n_cols);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::resize(const uword in_rows, const uword in_cols)
- {
- arma_extra_debug_sigprint();
-
- if( (n_rows == in_rows) && (n_cols == in_cols) )
- {
- return;
- }
-
- if( (n_elem == 0) || (n_nonzero == 0) )
- {
- set_size(in_rows, in_cols);
- return;
- }
-
- SpMat<eT> tmp(in_rows, in_cols);
-
- if(tmp.n_elem > 0)
- {
- sync_csc();
-
- const uword last_row = (std::min)(in_rows, n_rows) - 1;
- const uword last_col = (std::min)(in_cols, n_cols) - 1;
-
- tmp.submat(0, 0, last_row, last_col) = (*this).submat(0, 0, last_row, last_col);
- }
-
- steal_mem(tmp);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::resize(const SizeMat& s)
- {
- arma_extra_debug_sigprint();
-
- (*this).resize(s.n_rows, s.n_cols);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::reshape(const uword in_rows, const uword in_cols)
- {
- arma_extra_debug_sigprint();
-
- arma_check( ((in_rows*in_cols) != n_elem), "SpMat::reshape(): changing the number of elements in a sparse matrix is currently not supported" );
-
- if( (n_rows == in_rows) && (n_cols == in_cols) ) { return; }
-
- if(vec_state == 1) { arma_debug_check( (in_cols != 1), "SpMat::reshape(): object is a column vector; requested size is not compatible" ); }
- if(vec_state == 2) { arma_debug_check( (in_rows != 1), "SpMat::reshape(): object is a row vector; requested size is not compatible" ); }
-
- if(n_nonzero == 0)
- {
- (*this).zeros(in_rows, in_cols);
- return;
- }
-
- if(in_cols == 1)
- {
- (*this).reshape_helper_intovec();
- }
- else
- {
- (*this).reshape_helper_generic(in_rows, in_cols);
- }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::reshape(const SizeMat& s)
- {
- arma_extra_debug_sigprint();
-
- (*this).reshape(s.n_rows, s.n_cols);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::reshape_helper_generic(const uword in_rows, const uword in_cols)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
- invalidate_cache();
-
- // We have to modify all of the relevant row indices and the relevant column pointers.
- // Iterate over all the points to do this. We won't be deleting any points, but we will be modifying
- // columns and rows. We'll have to store a new set of column vectors.
- uword* new_col_ptrs = memory::acquire<uword>(in_cols + 2);
- new_col_ptrs[in_cols + 1] = std::numeric_limits<uword>::max();
-
- uword* new_row_indices = memory::acquire<uword>(n_nonzero + 1);
- access::rw(new_row_indices[n_nonzero]) = 0;
-
- arrayops::fill_zeros(new_col_ptrs, in_cols + 1);
-
- const_iterator it = begin();
- const_iterator it_end = end();
-
- for(; it != it_end; ++it)
- {
- uword vector_position = (it.col() * n_rows) + it.row();
- new_row_indices[it.pos()] = vector_position % in_rows;
- ++new_col_ptrs[vector_position / in_rows + 1];
- }
-
- // Now sum the column counts to get the new column pointers.
- for(uword i = 1; i <= in_cols; i++)
- {
- access::rw(new_col_ptrs[i]) += new_col_ptrs[i - 1];
- }
-
- // Copy the new row indices.
- if(row_indices) { memory::release(access::rw(row_indices)); }
- if(col_ptrs) { memory::release(access::rw(col_ptrs)); }
-
- access::rw(row_indices) = new_row_indices;
- access::rw(col_ptrs) = new_col_ptrs;
-
- // Now set the size.
- access::rw(n_rows) = in_rows;
- access::rw(n_cols) = in_cols;
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::reshape_helper_intovec()
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
- invalidate_cache();
-
- const_iterator it = begin();
-
- const uword t_n_rows = n_rows;
- const uword t_n_nonzero = n_nonzero;
-
- for(uword i=0; i < t_n_nonzero; ++i)
- {
- const uword t_index = (it.col() * t_n_rows) + it.row();
-
- // ensure the iterator is pointing to the next element
- // before we overwrite the row index of the current element
- ++it;
-
- access::rw(row_indices[i]) = t_index;
- }
-
- access::rw(row_indices[n_nonzero]) = 0;
-
- access::rw(col_ptrs[0]) = 0;
- access::rw(col_ptrs[1]) = n_nonzero;
- access::rw(col_ptrs[2]) = std::numeric_limits<uword>::max();
-
- access::rw(n_rows) = (n_rows * n_cols);
- access::rw(n_cols) = 1;
- }
- //! NOTE: don't use this form; it's deprecated and will be removed
- template<typename eT>
- arma_deprecated
- inline
- void
- SpMat<eT>::reshape(const uword in_rows, const uword in_cols, const uword dim)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( (dim > 1), "SpMat::reshape(): parameter 'dim' must be 0 or 1" );
-
- if(dim == 0)
- {
- (*this).reshape(in_rows, in_cols);
- }
- else
- if(dim == 1)
- {
- arma_check( ((in_rows*in_cols) != n_elem), "SpMat::reshape(): changing the number of elements in a sparse matrix is currently not supported" );
-
- sync_csc();
-
- // Row-wise reshaping. This is more tedious and we will use a separate sparse matrix to do it.
- SpMat<eT> tmp(in_rows, in_cols);
-
- for(const_row_iterator it = begin_row(); it.pos() < n_nonzero; ++it)
- {
- uword vector_position = (it.row() * n_cols) + it.col();
-
- tmp((vector_position / in_cols), (vector_position % in_cols)) = (*it);
- }
-
- steal_mem(tmp);
- }
- }
- //! apply a functor to each non-zero element
- template<typename eT>
- template<typename functor>
- inline
- const SpMat<eT>&
- SpMat<eT>::for_each(functor F)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const uword N = (*this).n_nonzero;
-
- eT* rw_values = access::rwp(values);
-
- bool modified = false;
- bool has_zero = false;
-
- for(uword i=0; i < N; ++i)
- {
- eT& new_value = rw_values[i];
- const eT old_value = new_value;
-
- F(new_value);
-
- if(new_value != old_value) { modified = true; }
- if(new_value == eT(0) ) { has_zero = true; }
- }
-
- if(modified) { invalidate_cache(); }
- if(has_zero) { remove_zeros(); }
-
- return *this;
- }
- template<typename eT>
- template<typename functor>
- inline
- const SpMat<eT>&
- SpMat<eT>::for_each(functor F) const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- const uword N = (*this).n_nonzero;
-
- for(uword i=0; i < N; ++i)
- {
- F(values[i]);
- }
-
- return *this;
- }
- //! transform each non-zero element using a functor
- template<typename eT>
- template<typename functor>
- inline
- const SpMat<eT>&
- SpMat<eT>::transform(functor F)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
- invalidate_cache();
-
- const uword N = (*this).n_nonzero;
-
- eT* rw_values = access::rwp(values);
-
- bool has_zero = false;
-
- for(uword i=0; i < N; ++i)
- {
- eT& rw_values_i = rw_values[i];
-
- rw_values_i = eT( F(rw_values_i) );
-
- if(rw_values_i == eT(0)) { has_zero = true; }
- }
-
- if(has_zero) { remove_zeros(); }
-
- return *this;
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::replace(const eT old_val, const eT new_val)
- {
- arma_extra_debug_sigprint();
-
- if(old_val == eT(0))
- {
- arma_debug_warn("SpMat::replace(): replacement not done, as old_val = 0");
- }
- else
- {
- sync_csc();
- invalidate_cache();
-
- arrayops::replace(access::rwp(values), n_nonzero, old_val, new_val);
-
- if(new_val == eT(0)) { remove_zeros(); }
- }
-
- return *this;
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::clean(const typename get_pod_type<eT>::result threshold)
- {
- arma_extra_debug_sigprint();
-
- if(n_nonzero == 0) { return *this; }
-
- sync_csc();
- invalidate_cache();
-
- arrayops::clean(access::rwp(values), n_nonzero, threshold);
-
- remove_zeros();
-
- return *this;
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::zeros()
- {
- arma_extra_debug_sigprint();
-
- const bool already_done = ( (sync_state != 1) && (n_nonzero == 0) );
-
- if(already_done == false)
- {
- init(n_rows, n_cols);
- }
-
- return *this;
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::zeros(const uword in_elem)
- {
- arma_extra_debug_sigprint();
-
- if(vec_state == 2)
- {
- zeros(1, in_elem); // Row vector
- }
- else
- {
- zeros(in_elem, 1);
- }
-
- return *this;
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::zeros(const uword in_rows, const uword in_cols)
- {
- arma_extra_debug_sigprint();
-
- const bool already_done = ( (sync_state != 1) && (n_nonzero == 0) && (n_rows == in_rows) && (n_cols == in_cols) );
-
- if(already_done == false)
- {
- init(in_rows, in_cols);
- }
-
- return *this;
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::zeros(const SizeMat& s)
- {
- arma_extra_debug_sigprint();
-
- return (*this).zeros(s.n_rows, s.n_cols);
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::eye()
- {
- arma_extra_debug_sigprint();
-
- return (*this).eye(n_rows, n_cols);
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::eye(const uword in_rows, const uword in_cols)
- {
- arma_extra_debug_sigprint();
-
- const uword N = (std::min)(in_rows, in_cols);
-
- init(in_rows, in_cols, N);
-
- arrayops::inplace_set(access::rwp(values), eT(1), N);
-
- for(uword i = 0; i < N; ++i) { access::rw(row_indices[i]) = i; }
-
- for(uword i = 0; i <= N; ++i) { access::rw(col_ptrs[i]) = i; }
-
- // take into account non-square matrices
- for(uword i = (N+1); i <= in_cols; ++i) { access::rw(col_ptrs[i]) = N; }
-
- access::rw(n_nonzero) = N;
-
- return *this;
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::eye(const SizeMat& s)
- {
- arma_extra_debug_sigprint();
-
- return (*this).eye(s.n_rows, s.n_cols);
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::speye()
- {
- arma_extra_debug_sigprint();
-
- return (*this).eye(n_rows, n_cols);
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::speye(const uword in_n_rows, const uword in_n_cols)
- {
- arma_extra_debug_sigprint();
-
- return (*this).eye(in_n_rows, in_n_cols);
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::speye(const SizeMat& s)
- {
- arma_extra_debug_sigprint();
-
- return (*this).eye(s.n_rows, s.n_cols);
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::sprandu(const uword in_rows, const uword in_cols, const double density)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( ( (density < double(0)) || (density > double(1)) ), "sprandu(): density must be in the [0,1] interval" );
-
- const uword new_n_nonzero = uword(density * double(in_rows) * double(in_cols) + 0.5);
-
- init(in_rows, in_cols, new_n_nonzero);
-
- if(new_n_nonzero == 0) { return *this; }
-
- arma_rng::randu<eT>::fill( access::rwp(values), new_n_nonzero );
-
- uvec indices = linspace<uvec>( 0u, in_rows*in_cols-1, new_n_nonzero );
-
- // perturb the indices
- for(uword i=1; i < new_n_nonzero-1; ++i)
- {
- const uword index_left = indices[i-1];
- const uword index_right = indices[i+1];
-
- const uword center = (index_left + index_right) / 2;
-
- const uword delta1 = center - index_left - 1;
- const uword delta2 = index_right - center - 1;
-
- const uword min_delta = (std::min)(delta1, delta2);
-
- uword index_new = uword( double(center) + double(min_delta) * (2.0*randu()-1.0) );
-
- // paranoia, but better be safe than sorry
- if( (index_left < index_new) && (index_new < index_right) )
- {
- indices[i] = index_new;
- }
- }
-
- uword cur_index = 0;
- uword count = 0;
-
- for(uword lcol = 0; lcol < in_cols; ++lcol)
- for(uword lrow = 0; lrow < in_rows; ++lrow)
- {
- if(count == indices[cur_index])
- {
- access::rw(row_indices[cur_index]) = lrow;
- access::rw(col_ptrs[lcol + 1])++;
- ++cur_index;
- }
-
- ++count;
- }
-
- if(cur_index != new_n_nonzero)
- {
- // Fix size to correct size.
- mem_resize(cur_index);
- }
-
- // Sum column pointers.
- for(uword lcol = 1; lcol <= in_cols; ++lcol)
- {
- access::rw(col_ptrs[lcol]) += col_ptrs[lcol - 1];
- }
-
- return *this;
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::sprandu(const SizeMat& s, const double density)
- {
- arma_extra_debug_sigprint();
-
- return (*this).sprandu(s.n_rows, s.n_cols, density);
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::sprandn(const uword in_rows, const uword in_cols, const double density)
- {
- arma_extra_debug_sigprint();
-
- arma_debug_check( ( (density < double(0)) || (density > double(1)) ), "sprandn(): density must be in the [0,1] interval" );
-
- const uword new_n_nonzero = uword(density * double(in_rows) * double(in_cols) + 0.5);
-
- init(in_rows, in_cols, new_n_nonzero);
-
- if(new_n_nonzero == 0) { return *this; }
-
- arma_rng::randn<eT>::fill( access::rwp(values), new_n_nonzero );
-
- uvec indices = linspace<uvec>( 0u, in_rows*in_cols-1, new_n_nonzero );
-
- // perturb the indices
- for(uword i=1; i < new_n_nonzero-1; ++i)
- {
- const uword index_left = indices[i-1];
- const uword index_right = indices[i+1];
-
- const uword center = (index_left + index_right) / 2;
-
- const uword delta1 = center - index_left - 1;
- const uword delta2 = index_right - center - 1;
-
- const uword min_delta = (std::min)(delta1, delta2);
-
- uword index_new = uword( double(center) + double(min_delta) * (2.0*randu()-1.0) );
-
- // paranoia, but better be safe than sorry
- if( (index_left < index_new) && (index_new < index_right) )
- {
- indices[i] = index_new;
- }
- }
-
- uword cur_index = 0;
- uword count = 0;
-
- for(uword lcol = 0; lcol < in_cols; ++lcol)
- for(uword lrow = 0; lrow < in_rows; ++lrow)
- {
- if(count == indices[cur_index])
- {
- access::rw(row_indices[cur_index]) = lrow;
- access::rw(col_ptrs[lcol + 1])++;
- ++cur_index;
- }
-
- ++count;
- }
-
- if(cur_index != new_n_nonzero)
- {
- // Fix size to correct size.
- mem_resize(cur_index);
- }
-
- // Sum column pointers.
- for(uword lcol = 1; lcol <= in_cols; ++lcol)
- {
- access::rw(col_ptrs[lcol]) += col_ptrs[lcol - 1];
- }
-
- return *this;
- }
- template<typename eT>
- inline
- const SpMat<eT>&
- SpMat<eT>::sprandn(const SizeMat& s, const double density)
- {
- arma_extra_debug_sigprint();
-
- return (*this).sprandn(s.n_rows, s.n_cols, density);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::reset()
- {
- arma_extra_debug_sigprint();
- switch(vec_state)
- {
- default:
- init(0, 0);
- break;
-
- case 1:
- init(0, 1);
- break;
-
- case 2:
- init(1, 0);
- break;
- }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::reserve(const uword in_rows, const uword in_cols, const uword new_n_nonzero)
- {
- arma_extra_debug_sigprint();
-
- init(in_rows, in_cols, new_n_nonzero);
- }
- template<typename eT>
- template<typename T1>
- inline
- void
- SpMat<eT>::set_real(const SpBase<typename SpMat<eT>::pod_type,T1>& X)
- {
- arma_extra_debug_sigprint();
-
- SpMat_aux::set_real(*this, X);
- }
- template<typename eT>
- template<typename T1>
- inline
- void
- SpMat<eT>::set_imag(const SpBase<typename SpMat<eT>::pod_type,T1>& X)
- {
- arma_extra_debug_sigprint();
-
- SpMat_aux::set_imag(*this, X);
- }
- //! save the matrix to a file
- template<typename eT>
- inline
- arma_cold
- bool
- SpMat<eT>::save(const std::string name, const file_type type, const bool print_status) const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- bool save_okay;
-
- switch(type)
- {
- case csv_ascii:
- return (*this).save(csv_name(name), type, print_status);
- break;
-
- case arma_binary:
- save_okay = diskio::save_arma_binary(*this, name);
- break;
-
- case coord_ascii:
- save_okay = diskio::save_coord_ascii(*this, name);
- break;
-
- default:
- if(print_status) { arma_debug_warn("SpMat::save(): unsupported file type"); }
- save_okay = false;
- }
-
- if(print_status && (save_okay == false)) { arma_debug_warn("SpMat::save(): couldn't write to ", name); }
-
- return save_okay;
- }
- template<typename eT>
- inline
- arma_cold
- bool
- SpMat<eT>::save(const csv_name& spec, const file_type type, const bool print_status) const
- {
- arma_extra_debug_sigprint();
-
- if(type != csv_ascii)
- {
- arma_debug_check(true, "SpMat::save(): unsupported file type for csv_name()");
- return false;
- }
-
- const bool do_trans = bool(spec.opts.flags & csv_opts::flag_trans );
- const bool no_header = bool(spec.opts.flags & csv_opts::flag_no_header );
- bool with_header = bool(spec.opts.flags & csv_opts::flag_with_header);
-
- arma_extra_debug_print("SpMat::save(csv_name): enabled flags:");
-
- if(do_trans ) { arma_extra_debug_print("trans"); }
- if(no_header ) { arma_extra_debug_print("no_header"); }
- if(with_header) { arma_extra_debug_print("with_header"); }
-
- if(no_header) { with_header = false; }
-
- if(with_header)
- {
- if( (spec.header_ro.n_cols != 1) && (spec.header_ro.n_rows != 1) )
- {
- if(print_status) { arma_debug_warn("SpMat::save(): given header must have a vector layout"); }
- return false;
- }
-
- for(uword i=0; i < spec.header_ro.n_elem; ++i)
- {
- const std::string& token = spec.header_ro.at(i);
-
- if(token.find(',') != std::string::npos)
- {
- if(print_status) { arma_debug_warn("SpMat::save(): token within the header contains a comma: '", token, "'"); }
- return false;
- }
- }
-
- const uword save_n_cols = (do_trans) ? (*this).n_rows : (*this).n_cols;
-
- if(spec.header_ro.n_elem != save_n_cols)
- {
- if(print_status) { arma_debug_warn("SpMat::save(): size mistmach between header and matrix"); }
- return false;
- }
- }
-
- bool save_okay = false;
-
- if(do_trans)
- {
- const SpMat<eT> tmp = (*this).st();
-
- save_okay = diskio::save_csv_ascii(tmp, spec.filename, spec.header_ro, with_header);
- }
- else
- {
- save_okay = diskio::save_csv_ascii(*this, spec.filename, spec.header_ro, with_header);
- }
-
- if((print_status == true) && (save_okay == false))
- {
- arma_debug_warn("SpMat::save(): couldn't write to ", spec.filename);
- }
-
- return save_okay;
- }
- //! save the matrix to a stream
- template<typename eT>
- inline
- arma_cold
- bool
- SpMat<eT>::save(std::ostream& os, const file_type type, const bool print_status) const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- bool save_okay;
-
- switch(type)
- {
- case csv_ascii:
- save_okay = diskio::save_csv_ascii(*this, os);
- break;
-
- case arma_binary:
- save_okay = diskio::save_arma_binary(*this, os);
- break;
-
- case coord_ascii:
- save_okay = diskio::save_coord_ascii(*this, os);
- break;
-
- default:
- if(print_status) { arma_debug_warn("SpMat::save(): unsupported file type"); }
- save_okay = false;
- }
-
- if(print_status && (save_okay == false)) { arma_debug_warn("SpMat::save(): couldn't write to the given stream"); }
-
- return save_okay;
- }
- //! load a matrix from a file
- template<typename eT>
- inline
- arma_cold
- bool
- SpMat<eT>::load(const std::string name, const file_type type, const bool print_status)
- {
- arma_extra_debug_sigprint();
-
- invalidate_cache();
-
- bool load_okay;
- std::string err_msg;
-
- switch(type)
- {
- // case auto_detect:
- // load_okay = diskio::load_auto_detect(*this, name, err_msg);
- // break;
-
- case csv_ascii:
- return (*this).load(csv_name(name), type, print_status);
- break;
-
- case arma_binary:
- load_okay = diskio::load_arma_binary(*this, name, err_msg);
- break;
-
- case coord_ascii:
- load_okay = diskio::load_coord_ascii(*this, name, err_msg);
- break;
-
- default:
- if(print_status) { arma_debug_warn("SpMat::load(): unsupported file type"); }
- load_okay = false;
- }
-
- if(print_status && (load_okay == false))
- {
- if(err_msg.length() > 0)
- {
- arma_debug_warn("SpMat::load(): ", err_msg, name);
- }
- else
- {
- arma_debug_warn("SpMat::load(): couldn't read ", name);
- }
- }
-
- if(load_okay == false)
- {
- (*this).reset();
- }
-
- return load_okay;
- }
- template<typename eT>
- inline
- arma_cold
- bool
- SpMat<eT>::load(const csv_name& spec, const file_type type, const bool print_status)
- {
- arma_extra_debug_sigprint();
-
- if(type != csv_ascii)
- {
- arma_debug_check(true, "SpMat::load(): unsupported file type for csv_name()");
- return false;
- }
-
- const bool do_trans = bool(spec.opts.flags & csv_opts::flag_trans );
- const bool no_header = bool(spec.opts.flags & csv_opts::flag_no_header );
- bool with_header = bool(spec.opts.flags & csv_opts::flag_with_header);
-
- arma_extra_debug_print("SpMat::load(csv_name): enabled flags:");
-
- if(do_trans ) { arma_extra_debug_print("trans"); }
- if(no_header ) { arma_extra_debug_print("no_header"); }
- if(with_header) { arma_extra_debug_print("with_header"); }
-
- if(no_header) { with_header = false; }
-
- bool load_okay = false;
- std::string err_msg;
-
- if(do_trans)
- {
- SpMat<eT> tmp_mat;
-
- load_okay = diskio::load_csv_ascii(tmp_mat, spec.filename, err_msg, spec.header_rw, with_header);
-
- if(load_okay)
- {
- (*this) = tmp_mat.st();
-
- if(with_header)
- {
- // field::set_size() preserves data if the number of elements hasn't changed
- spec.header_rw.set_size(spec.header_rw.n_elem, 1);
- }
- }
- }
- else
- {
- load_okay = diskio::load_csv_ascii(*this, spec.filename, err_msg, spec.header_rw, with_header);
- }
-
- if(print_status == true)
- {
- if(load_okay == false)
- {
- if(err_msg.length() > 0)
- {
- arma_debug_warn("SpMat::load(): ", err_msg, spec.filename);
- }
- else
- {
- arma_debug_warn("SpMat::load(): couldn't read ", spec.filename);
- }
- }
- else
- {
- const uword load_n_cols = (do_trans) ? (*this).n_rows : (*this).n_cols;
-
- if(with_header && (spec.header_rw.n_elem != load_n_cols))
- {
- arma_debug_warn("SpMat::load(): size mistmach between header and matrix");
- }
- }
- }
-
- if(load_okay == false)
- {
- (*this).reset();
-
- if(with_header) { spec.header_rw.reset(); }
- }
-
- return load_okay;
- }
- //! load a matrix from a stream
- template<typename eT>
- inline
- arma_cold
- bool
- SpMat<eT>::load(std::istream& is, const file_type type, const bool print_status)
- {
- arma_extra_debug_sigprint();
-
- invalidate_cache();
-
- bool load_okay;
- std::string err_msg;
-
- switch(type)
- {
- // case auto_detect:
- // load_okay = diskio::load_auto_detect(*this, is, err_msg);
- // break;
-
- case csv_ascii:
- load_okay = diskio::load_csv_ascii(*this, is, err_msg);
- break;
-
- case arma_binary:
- load_okay = diskio::load_arma_binary(*this, is, err_msg);
- break;
-
- case coord_ascii:
- load_okay = diskio::load_coord_ascii(*this, is, err_msg);
- break;
-
- default:
- if(print_status) { arma_debug_warn("SpMat::load(): unsupported file type"); }
- load_okay = false;
- }
-
- if(print_status && (load_okay == false))
- {
- if(err_msg.length() > 0)
- {
- arma_debug_warn("SpMat::load(): ", err_msg, "the given stream");
- }
- else
- {
- arma_debug_warn("SpMat::load(): couldn't load from the given stream");
- }
- }
-
- if(load_okay == false)
- {
- (*this).reset();
- }
-
- return load_okay;
- }
- //! save the matrix to a file, without printing any error messages
- template<typename eT>
- inline
- arma_cold
- bool
- SpMat<eT>::quiet_save(const std::string name, const file_type type) const
- {
- arma_extra_debug_sigprint();
-
- return (*this).save(name, type, false);
- }
- //! save the matrix to a stream, without printing any error messages
- template<typename eT>
- inline
- arma_cold
- bool
- SpMat<eT>::quiet_save(std::ostream& os, const file_type type) const
- {
- arma_extra_debug_sigprint();
-
- return (*this).save(os, type, false);
- }
- //! load a matrix from a file, without printing any error messages
- template<typename eT>
- inline
- arma_cold
- bool
- SpMat<eT>::quiet_load(const std::string name, const file_type type)
- {
- arma_extra_debug_sigprint();
-
- return (*this).load(name, type, false);
- }
- //! load a matrix from a stream, without printing any error messages
- template<typename eT>
- inline
- arma_cold
- bool
- SpMat<eT>::quiet_load(std::istream& is, const file_type type)
- {
- arma_extra_debug_sigprint();
-
- return (*this).load(is, type, false);
- }
- /**
- * Initialize the matrix to the specified size. Data is not preserved, so the matrix is assumed to be entirely sparse (empty).
- */
- template<typename eT>
- inline
- void
- SpMat<eT>::init(uword in_rows, uword in_cols, const uword new_n_nonzero)
- {
- arma_extra_debug_sigprint();
-
- invalidate_cache(); // placed here, as init() is used during matrix modification
-
- // Clean out the existing memory.
- if(values ) { memory::release(access::rw(values)); }
- if(row_indices) { memory::release(access::rw(row_indices)); }
- if(col_ptrs ) { memory::release(access::rw(col_ptrs)); }
-
- init_cold(in_rows, in_cols, new_n_nonzero);
- }
- template<typename eT>
- inline
- void
- arma_cold
- SpMat<eT>::init_cold(uword in_rows, uword in_cols, const uword new_n_nonzero)
- {
- arma_extra_debug_sigprint();
-
- // Verify that we are allowed to do this.
- if(vec_state > 0)
- {
- if((in_rows == 0) && (in_cols == 0))
- {
- if(vec_state == 1) { in_cols = 1; }
- if(vec_state == 2) { in_rows = 1; }
- }
- else
- {
- if(vec_state == 1) { arma_debug_check( (in_cols != 1), "SpMat::init(): object is a column vector; requested size is not compatible" ); }
- if(vec_state == 2) { arma_debug_check( (in_rows != 1), "SpMat::init(): object is a row vector; requested size is not compatible" ); }
- }
- }
-
- #if defined(ARMA_64BIT_WORD)
- const char* error_message = "SpMat::init(): requested size is too large";
- #else
- const char* error_message = "SpMat::init(): requested size is too large; suggest to compile in C++11 mode and/or enable ARMA_64BIT_WORD";
- #endif
-
- // Ensure that n_elem can hold the result of (n_rows * n_cols)
- arma_debug_check
- (
- (
- ( (in_rows > ARMA_MAX_UHWORD) || (in_cols > ARMA_MAX_UHWORD) )
- ? ( (double(in_rows) * double(in_cols)) > double(ARMA_MAX_UWORD) )
- : false
- ),
- error_message
- );
-
- access::rw(col_ptrs) = memory::acquire<uword>(in_cols + 2);
- access::rw(values) = memory::acquire<eT> (new_n_nonzero + 1);
- access::rw(row_indices) = memory::acquire<uword>(new_n_nonzero + 1);
-
- // fill column pointers with 0,
- // except for the last element which contains the maximum possible element
- // (so iterators terminate correctly).
- arrayops::fill_zeros(access::rwp(col_ptrs), in_cols + 1);
-
- access::rw(col_ptrs[in_cols + 1]) = std::numeric_limits<uword>::max();
-
- access::rw( values[new_n_nonzero]) = 0;
- access::rw(row_indices[new_n_nonzero]) = 0;
-
- // Set the new size accordingly.
- access::rw(n_rows) = in_rows;
- access::rw(n_cols) = in_cols;
- access::rw(n_elem) = (in_rows * in_cols);
- access::rw(n_nonzero) = new_n_nonzero;
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::init(const std::string& text)
- {
- arma_extra_debug_sigprint();
-
- Mat<eT> tmp(text);
-
- if(vec_state == 1)
- {
- if((tmp.n_elem > 0) && tmp.is_vec())
- {
- access::rw(tmp.n_rows) = tmp.n_elem;
- access::rw(tmp.n_cols) = 1;
- }
- }
-
- if(vec_state == 2)
- {
- if((tmp.n_elem > 0) && tmp.is_vec())
- {
- access::rw(tmp.n_rows) = 1;
- access::rw(tmp.n_cols) = tmp.n_elem;
- }
- }
-
- (*this).operator=(tmp);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::init(const SpMat<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- if(this == &x) { return; }
-
- bool init_done = false;
-
- #if defined(ARMA_USE_OPENMP)
- if(x.sync_state == 1)
- {
- #pragma omp critical (arma_SpMat_init)
- if(x.sync_state == 1)
- {
- (*this).init(x.cache);
- init_done = true;
- }
- }
- #elif (defined(ARMA_USE_CXX11) && !defined(ARMA_DONT_USE_CXX11_MUTEX))
- if(x.sync_state == 1)
- {
- x.cache_mutex.lock();
- if(x.sync_state == 1)
- {
- (*this).init(x.cache);
- init_done = true;
- }
- x.cache_mutex.unlock();
- }
- #else
- if(x.sync_state == 1)
- {
- (*this).init(x.cache);
- init_done = true;
- }
- #endif
-
- if(init_done == false)
- {
- (*this).init_simple(x);
- }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::init(const MapMat<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- const uword x_n_rows = x.n_rows;
- const uword x_n_cols = x.n_cols;
- const uword x_n_nz = x.get_n_nonzero();
-
- init(x_n_rows, x_n_cols, x_n_nz);
-
- if(x_n_nz == 0) { return; }
-
- typename MapMat<eT>::map_type& x_map_ref = *(x.map_ptr);
-
- typename MapMat<eT>::map_type::const_iterator x_it = x_map_ref.begin();
-
- uword x_col = 0;
- uword x_col_index_start = 0;
- uword x_col_index_endp1 = x_n_rows;
-
- for(uword i=0; i < x_n_nz; ++i)
- {
- const std::pair<uword, eT>& x_entry = (*x_it);
-
- const uword x_index = x_entry.first;
- const eT x_val = x_entry.second;
-
- // have we gone past the curent column?
- if(x_index >= x_col_index_endp1)
- {
- x_col = x_index / x_n_rows;
-
- x_col_index_start = x_col * x_n_rows;
- x_col_index_endp1 = x_col_index_start + x_n_rows;
- }
-
- const uword x_row = x_index - x_col_index_start;
-
- // // sanity check
- //
- // const uword tmp_x_row = x_index % x_n_rows;
- // const uword tmp_x_col = x_index / x_n_rows;
- //
- // if(x_row != tmp_x_row) { cout << "x_row != tmp_x_row" << endl; exit(-1); }
- // if(x_col != tmp_x_col) { cout << "x_col != tmp_x_col" << endl; exit(-1); }
-
- access::rw(values[i]) = x_val;
- access::rw(row_indices[i]) = x_row;
-
- access::rw(col_ptrs[ x_col + 1 ])++;
-
- ++x_it;
- }
-
-
- for(uword i = 0; i < x_n_cols; ++i)
- {
- access::rw(col_ptrs[i + 1]) += col_ptrs[i];
- }
-
-
- // // OLD METHOD
- //
- // for(uword i=0; i < x_n_nz; ++i)
- // {
- // const std::pair<uword, eT>& x_entry = (*x_it);
- //
- // const uword x_index = x_entry.first;
- // const eT x_val = x_entry.second;
- //
- // const uword x_row = x_index % x_n_rows;
- // const uword x_col = x_index / x_n_rows;
- //
- // access::rw(values[i]) = x_val;
- // access::rw(row_indices[i]) = x_row;
- //
- // access::rw(col_ptrs[ x_col + 1 ])++;
- //
- // ++x_it;
- // }
- //
- //
- // for(uword i = 0; i < x_n_cols; ++i)
- // {
- // access::rw(col_ptrs[i + 1]) += col_ptrs[i];
- // }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::init_simple(const SpMat<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- if(this == &x) { return; }
-
- init(x.n_rows, x.n_cols, x.n_nonzero);
-
- if(x.values ) { arrayops::copy(access::rwp(values), x.values, x.n_nonzero + 1); }
- if(x.row_indices) { arrayops::copy(access::rwp(row_indices), x.row_indices, x.n_nonzero + 1); }
- if(x.col_ptrs ) { arrayops::copy(access::rwp(col_ptrs), x.col_ptrs, x.n_cols + 1); }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::init_batch_std(const Mat<uword>& locs, const Mat<eT>& vals, const bool sort_locations)
- {
- arma_extra_debug_sigprint();
-
- // Resize to correct number of elements.
- mem_resize(vals.n_elem);
-
- // Reset column pointers to zero.
- arrayops::fill_zeros(access::rwp(col_ptrs), n_cols + 1);
-
- bool actually_sorted = true;
-
- if(sort_locations == true)
- {
- // check if we really need a time consuming sort
-
- const uword locs_n_cols = locs.n_cols;
-
- for(uword i = 1; i < locs_n_cols; ++i)
- {
- const uword* locs_i = locs.colptr(i );
- const uword* locs_im1 = locs.colptr(i-1);
-
- const uword row_i = locs_i[0];
- const uword col_i = locs_i[1];
-
- const uword row_im1 = locs_im1[0];
- const uword col_im1 = locs_im1[1];
-
- if( (col_i < col_im1) || ((col_i == col_im1) && (row_i <= row_im1)) )
- {
- actually_sorted = false;
- break;
- }
- }
-
- if(actually_sorted == false)
- {
- // see op_sort_index_bones.hpp for the definition of arma_sort_index_packet and arma_sort_index_helper_ascend
-
- std::vector< arma_sort_index_packet<uword> > packet_vec(locs_n_cols);
-
- const uword* locs_mem = locs.memptr();
-
- for(uword i = 0; i < locs_n_cols; ++i)
- {
- const uword row = (*locs_mem); locs_mem++;
- const uword col = (*locs_mem); locs_mem++;
-
- packet_vec[i].val = (col * n_rows) + row;
- packet_vec[i].index = i;
- }
-
- arma_sort_index_helper_ascend<uword> comparator;
-
- std::sort( packet_vec.begin(), packet_vec.end(), comparator );
-
- // insert the elements in the sorted order
- for(uword i = 0; i < locs_n_cols; ++i)
- {
- const uword index = packet_vec[i].index;
-
- const uword* locs_i = locs.colptr(index);
-
- const uword row_i = locs_i[0];
- const uword col_i = locs_i[1];
-
- arma_debug_check( ( (row_i >= n_rows) || (col_i >= n_cols) ), "SpMat::SpMat(): invalid row or column index" );
-
- if(i > 0)
- {
- const uword prev_index = packet_vec[i-1].index;
-
- const uword* locs_im1 = locs.colptr(prev_index);
-
- const uword row_im1 = locs_im1[0];
- const uword col_im1 = locs_im1[1];
-
- arma_debug_check( ( (row_i == row_im1) && (col_i == col_im1) ), "SpMat::SpMat(): detected identical locations" );
- }
-
- access::rw(values[i]) = vals[index];
- access::rw(row_indices[i]) = row_i;
-
- access::rw(col_ptrs[ col_i + 1 ])++;
- }
- }
- }
-
- if( (sort_locations == false) || (actually_sorted == true) )
- {
- // Now set the values and row indices correctly.
- // Increment the column pointers in each column (so they are column "counts").
-
- const uword locs_n_cols = locs.n_cols;
-
- for(uword i=0; i < locs_n_cols; ++i)
- {
- const uword* locs_i = locs.colptr(i);
-
- const uword row_i = locs_i[0];
- const uword col_i = locs_i[1];
-
- arma_debug_check( ( (row_i >= n_rows) || (col_i >= n_cols) ), "SpMat::SpMat(): invalid row or column index" );
-
- if(i > 0)
- {
- const uword* locs_im1 = locs.colptr(i-1);
-
- const uword row_im1 = locs_im1[0];
- const uword col_im1 = locs_im1[1];
-
- arma_debug_check
- (
- ( (col_i < col_im1) || ((col_i == col_im1) && (row_i < row_im1)) ),
- "SpMat::SpMat(): out of order points; either pass sort_locations = true, or sort points in column-major ordering"
- );
-
- arma_debug_check( ( (col_i == col_im1) && (row_i == row_im1) ), "SpMat::SpMat(): detected identical locations" );
- }
-
- access::rw(values[i]) = vals[i];
- access::rw(row_indices[i]) = row_i;
-
- access::rw(col_ptrs[ col_i + 1 ])++;
- }
- }
-
- // Now fix the column pointers.
- for(uword i = 0; i < n_cols; ++i)
- {
- access::rw(col_ptrs[i + 1]) += col_ptrs[i];
- }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::init_batch_add(const Mat<uword>& locs, const Mat<eT>& vals, const bool sort_locations)
- {
- arma_extra_debug_sigprint();
-
- if(locs.n_cols < 2)
- {
- init_batch_std(locs, vals, false);
- return;
- }
-
- // Reset column pointers to zero.
- arrayops::fill_zeros(access::rwp(col_ptrs), n_cols + 1);
-
- bool actually_sorted = true;
-
- if(sort_locations == true)
- {
- // sort_index() uses std::sort() which may use quicksort... so we better
- // make sure it's not already sorted before taking an O(N^2) sort penalty.
- for(uword i = 1; i < locs.n_cols; ++i)
- {
- const uword* locs_i = locs.colptr(i );
- const uword* locs_im1 = locs.colptr(i-1);
-
- if( (locs_i[1] < locs_im1[1]) || (locs_i[1] == locs_im1[1] && locs_i[0] <= locs_im1[0]) )
- {
- actually_sorted = false;
- break;
- }
- }
-
- if(actually_sorted == false)
- {
- // This may not be the fastest possible implementation but it maximizes code reuse.
- Col<uword> abslocs(locs.n_cols);
-
- for(uword i = 0; i < locs.n_cols; ++i)
- {
- const uword* locs_i = locs.colptr(i);
-
- abslocs[i] = locs_i[1] * n_rows + locs_i[0];
- }
-
- uvec sorted_indices = sort_index(abslocs); // Ascending sort.
-
- // work out the number of unique elments
- uword n_unique = 1; // first element is unique
-
- for(uword i=1; i < sorted_indices.n_elem; ++i)
- {
- const uword* locs_i = locs.colptr( sorted_indices[i ] );
- const uword* locs_im1 = locs.colptr( sorted_indices[i-1] );
-
- if( (locs_i[1] != locs_im1[1]) || (locs_i[0] != locs_im1[0]) ) { ++n_unique; }
- }
-
- // resize to correct number of elements
- mem_resize(n_unique);
-
- // Now we add the elements in this sorted order.
- uword count = 0;
-
- // first element
- {
- const uword i = 0;
- const uword* locs_i = locs.colptr( sorted_indices[i] );
-
- arma_debug_check( ( (locs_i[0] >= n_rows) || (locs_i[1] >= n_cols) ), "SpMat::SpMat(): invalid row or column index" );
-
- access::rw(values[count]) = vals[ sorted_indices[i] ];
- access::rw(row_indices[count]) = locs_i[0];
-
- access::rw(col_ptrs[ locs_i[1] + 1 ])++;
- }
-
- for(uword i=1; i < sorted_indices.n_elem; ++i)
- {
- const uword* locs_i = locs.colptr( sorted_indices[i ] );
- const uword* locs_im1 = locs.colptr( sorted_indices[i-1] );
-
- arma_debug_check( ( (locs_i[0] >= n_rows) || (locs_i[1] >= n_cols) ), "SpMat::SpMat(): invalid row or column index" );
-
- if( (locs_i[1] == locs_im1[1]) && (locs_i[0] == locs_im1[0]) )
- {
- access::rw(values[count]) += vals[ sorted_indices[i] ];
- }
- else
- {
- count++;
- access::rw(values[count]) = vals[ sorted_indices[i] ];
- access::rw(row_indices[count]) = locs_i[0];
-
- access::rw(col_ptrs[ locs_i[1] + 1 ])++;
- }
- }
- }
- }
-
- if( (sort_locations == false) || (actually_sorted == true) )
- {
- // work out the number of unique elments
- uword n_unique = 1; // first element is unique
-
- for(uword i=1; i < locs.n_cols; ++i)
- {
- const uword* locs_i = locs.colptr(i );
- const uword* locs_im1 = locs.colptr(i-1);
-
- if( (locs_i[1] != locs_im1[1]) || (locs_i[0] != locs_im1[0]) ) { ++n_unique; }
- }
-
- // resize to correct number of elements
- mem_resize(n_unique);
-
- // Now set the values and row indices correctly.
- // Increment the column pointers in each column (so they are column "counts").
-
- uword count = 0;
-
- // first element
- {
- const uword i = 0;
- const uword* locs_i = locs.colptr(i);
-
- arma_debug_check( ( (locs_i[0] >= n_rows) || (locs_i[1] >= n_cols) ), "SpMat::SpMat(): invalid row or column index" );
-
- access::rw(values[count]) = vals[i];
- access::rw(row_indices[count]) = locs_i[0];
-
- access::rw(col_ptrs[ locs_i[1] + 1 ])++;
- }
-
- for(uword i=1; i < locs.n_cols; ++i)
- {
- const uword* locs_i = locs.colptr(i );
- const uword* locs_im1 = locs.colptr(i-1);
-
- arma_debug_check( ( (locs_i[0] >= n_rows) || (locs_i[1] >= n_cols) ), "SpMat::SpMat(): invalid row or column index" );
-
- arma_debug_check
- (
- ( (locs_i[1] < locs_im1[1]) || (locs_i[1] == locs_im1[1] && locs_i[0] < locs_im1[0]) ),
- "SpMat::SpMat(): out of order points; either pass sort_locations = true, or sort points in column-major ordering"
- );
-
- if( (locs_i[1] == locs_im1[1]) && (locs_i[0] == locs_im1[0]) )
- {
- access::rw(values[count]) += vals[i];
- }
- else
- {
- count++;
-
- access::rw(values[count]) = vals[i];
- access::rw(row_indices[count]) = locs_i[0];
-
- access::rw(col_ptrs[ locs_i[1] + 1 ])++;
- }
- }
- }
-
- // Now fix the column pointers.
- for(uword i = 0; i < n_cols; ++i)
- {
- access::rw(col_ptrs[i + 1]) += col_ptrs[i];
- }
- }
- //! constructor used by SpRow and SpCol classes
- template<typename eT>
- inline
- SpMat<eT>::SpMat(const arma_vec_indicator&, const uword in_vec_state)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(in_vec_state)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- const uword in_n_rows = (in_vec_state == 2) ? 1 : 0;
- const uword in_n_cols = (in_vec_state == 1) ? 1 : 0;
-
- init_cold(in_n_rows, in_n_cols);
- }
- //! constructor used by SpRow and SpCol classes
- template<typename eT>
- inline
- SpMat<eT>::SpMat(const arma_vec_indicator&, const uword in_n_rows, const uword in_n_cols, const uword in_vec_state)
- : n_rows(0)
- , n_cols(0)
- , n_elem(0)
- , n_nonzero(0)
- , vec_state(in_vec_state)
- , values(NULL)
- , row_indices(NULL)
- , col_ptrs(NULL)
- {
- arma_extra_debug_sigprint_this(this);
-
- init_cold(in_n_rows, in_n_cols);
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::mem_resize(const uword new_n_nonzero)
- {
- arma_extra_debug_sigprint();
-
- invalidate_cache(); // placed here, as mem_resize() is used during matrix modification
-
- if(n_nonzero == new_n_nonzero) { return; }
-
- eT* new_values = memory::acquire<eT> (new_n_nonzero + 1);
- uword* new_row_indices = memory::acquire<uword>(new_n_nonzero + 1);
-
- if( (n_nonzero > 0 ) && (new_n_nonzero > 0) )
- {
- // Copy old elements.
- uword copy_len = (std::min)(n_nonzero, new_n_nonzero);
-
- arrayops::copy(new_values, values, copy_len);
- arrayops::copy(new_row_indices, row_indices, copy_len);
- }
-
- if(values) { memory::release(access::rw(values)); }
- if(row_indices) { memory::release(access::rw(row_indices)); }
-
- access::rw(values) = new_values;
- access::rw(row_indices) = new_row_indices;
-
- // Set the "fake end" of the matrix by setting the last value and row index to 0.
- // This helps the iterators work correctly.
- access::rw( values[new_n_nonzero]) = 0;
- access::rw(row_indices[new_n_nonzero]) = 0;
-
- access::rw(n_nonzero) = new_n_nonzero;
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::sync() const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::remove_zeros()
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- invalidate_cache(); // placed here, as remove_zeros() is used during matrix modification
-
- const uword old_n_nonzero = n_nonzero;
- uword new_n_nonzero = 0;
-
- const eT* old_values = values;
-
- for(uword i=0; i < old_n_nonzero; ++i)
- {
- new_n_nonzero += (old_values[i] != eT(0)) ? uword(1) : uword(0);
- }
-
- if(new_n_nonzero != old_n_nonzero)
- {
- if(new_n_nonzero == 0) { init(n_rows, n_cols); return; }
-
- SpMat<eT> tmp(arma_reserve_indicator(), n_rows, n_cols, new_n_nonzero);
-
- uword new_index = 0;
-
- const_iterator it = begin();
- const_iterator it_end = end();
-
- for(; it != it_end; ++it)
- {
- const eT val = eT(*it);
-
- if(val != eT(0))
- {
- access::rw(tmp.values[new_index]) = val;
- access::rw(tmp.row_indices[new_index]) = it.row();
- access::rw(tmp.col_ptrs[it.col() + 1])++;
- ++new_index;
- }
- }
-
- for(uword i=0; i < n_cols; ++i)
- {
- access::rw(tmp.col_ptrs[i + 1]) += tmp.col_ptrs[i];
- }
-
- steal_mem(tmp);
- }
- }
- // Steal memory from another matrix.
- template<typename eT>
- inline
- void
- SpMat<eT>::steal_mem(SpMat<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- if(this == &x) { return; }
-
- bool layout_ok = false;
-
- if((*this).vec_state == x.vec_state)
- {
- layout_ok = true;
- }
- else
- {
- if( ((*this).vec_state == 1) && (x.n_cols == 1) ) { layout_ok = true; }
- if( ((*this).vec_state == 2) && (x.n_rows == 1) ) { layout_ok = true; }
- }
-
- if(layout_ok)
- {
- x.sync_csc();
-
- steal_mem_simple(x);
-
- x.invalidate_cache();
-
- invalidate_cache();
- }
- else
- {
- (*this).operator=(x);
- }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::steal_mem_simple(SpMat<eT>& x)
- {
- arma_extra_debug_sigprint();
-
- if(this == &x) { return; }
-
- if(values ) { memory::release(access::rw(values)); }
- if(row_indices) { memory::release(access::rw(row_indices)); }
- if(col_ptrs ) { memory::release(access::rw(col_ptrs)); }
-
- access::rw(n_rows) = x.n_rows;
- access::rw(n_cols) = x.n_cols;
- access::rw(n_elem) = x.n_elem;
- access::rw(n_nonzero) = x.n_nonzero;
-
- access::rw(values) = x.values;
- access::rw(row_indices) = x.row_indices;
- access::rw(col_ptrs) = x.col_ptrs;
-
- // Set other matrix to empty.
- access::rw(x.n_rows) = 0;
- access::rw(x.n_cols) = 0;
- access::rw(x.n_elem) = 0;
- access::rw(x.n_nonzero) = 0;
-
- access::rw(x.values) = NULL;
- access::rw(x.row_indices) = NULL;
- access::rw(x.col_ptrs) = NULL;
- }
- template<typename eT>
- template<typename T1, typename Functor>
- arma_hot
- inline
- void
- SpMat<eT>::init_xform(const SpBase<eT,T1>& A, const Functor& func)
- {
- arma_extra_debug_sigprint();
-
- // if possible, avoid doing a copy and instead apply func to the generated elements
- if(SpProxy<T1>::Q_is_generated)
- {
- (*this) = A.get_ref();
-
- const uword nnz = n_nonzero;
-
- eT* t_values = access::rwp(values);
-
- bool has_zero = false;
-
- for(uword i=0; i < nnz; ++i)
- {
- eT& t_values_i = t_values[i];
-
- t_values_i = func(t_values_i);
-
- if(t_values_i == eT(0)) { has_zero = true; }
- }
-
- if(has_zero) { remove_zeros(); }
- }
- else
- {
- init_xform_mt(A.get_ref(), func);
- }
- }
- template<typename eT>
- template<typename eT2, typename T1, typename Functor>
- arma_hot
- inline
- void
- SpMat<eT>::init_xform_mt(const SpBase<eT2,T1>& A, const Functor& func)
- {
- arma_extra_debug_sigprint();
-
- const SpProxy<T1> P(A.get_ref());
-
- if( (P.is_alias(*this) == true) || (is_SpMat<typename SpProxy<T1>::stored_type>::value == true) )
- {
- // NOTE: unwrap_spmat will convert a submatrix to a matrix, which in effect takes care of aliasing with submatrices;
- // NOTE: however, when more delayed ops are implemented, more elaborate handling of aliasing will be necessary
- const unwrap_spmat<typename SpProxy<T1>::stored_type> tmp(P.Q);
-
- const SpMat<eT2>& x = tmp.M;
-
- if(void_ptr(this) != void_ptr(&x))
- {
- init(x.n_rows, x.n_cols, x.n_nonzero);
-
- arrayops::copy(access::rwp(row_indices), x.row_indices, x.n_nonzero + 1);
- arrayops::copy(access::rwp(col_ptrs), x.col_ptrs, x.n_cols + 1);
- }
-
-
- // initialise the elements array with a transformed version of the elements from x
-
- const uword nnz = n_nonzero;
-
- const eT2* x_values = x.values;
- eT* t_values = access::rwp(values);
-
- bool has_zero = false;
-
- for(uword i=0; i < nnz; ++i)
- {
- eT& t_values_i = t_values[i];
-
- t_values_i = func(x_values[i]); // NOTE: func() must produce a value of type eT (ie. act as a convertor between eT2 and eT)
-
- if(t_values_i == eT(0)) { has_zero = true; }
- }
-
- if(has_zero) { remove_zeros(); }
- }
- else
- {
- init(P.get_n_rows(), P.get_n_cols(), P.get_n_nonzero());
-
- typename SpProxy<T1>::const_iterator_type it = P.begin();
- typename SpProxy<T1>::const_iterator_type it_end = P.end();
-
- bool has_zero = false;
-
- while(it != it_end)
- {
- const eT val = func(*it); // NOTE: func() must produce a value of type eT (ie. act as a convertor between eT2 and eT)
-
- if(val == eT(0)) { has_zero = true; }
-
- access::rw(row_indices[it.pos()]) = it.row();
- access::rw(values[it.pos()]) = val;
- ++access::rw(col_ptrs[it.col() + 1]);
- ++it;
- }
-
- // Now sum column pointers.
- for(uword c = 1; c <= n_cols; ++c)
- {
- access::rw(col_ptrs[c]) += col_ptrs[c - 1];
- }
-
- if(has_zero) { remove_zeros(); }
- }
- }
- template<typename eT>
- arma_inline
- bool
- SpMat<eT>::is_alias(const SpMat<eT>& X) const
- {
- return (&X == this);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::iterator
- SpMat<eT>::begin()
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- return iterator(*this);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_iterator
- SpMat<eT>::begin() const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- return const_iterator(*this);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_iterator
- SpMat<eT>::cbegin() const
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
-
- return const_iterator(*this);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::iterator
- SpMat<eT>::end()
- {
- sync_csc();
-
- return iterator(*this, 0, n_cols, n_nonzero);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_iterator
- SpMat<eT>::end() const
- {
- sync_csc();
-
- return const_iterator(*this, 0, n_cols, n_nonzero);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_iterator
- SpMat<eT>::cend() const
- {
- sync_csc();
-
- return const_iterator(*this, 0, n_cols, n_nonzero);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::col_iterator
- SpMat<eT>::begin_col(const uword col_num)
- {
- sync_csc();
-
- return col_iterator(*this, 0, col_num);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_col_iterator
- SpMat<eT>::begin_col(const uword col_num) const
- {
- sync_csc();
-
- return const_col_iterator(*this, 0, col_num);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::col_iterator
- SpMat<eT>::begin_col_no_sync(const uword col_num)
- {
- return col_iterator(*this, 0, col_num);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_col_iterator
- SpMat<eT>::begin_col_no_sync(const uword col_num) const
- {
- return const_col_iterator(*this, 0, col_num);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::col_iterator
- SpMat<eT>::end_col(const uword col_num)
- {
- sync_csc();
-
- return col_iterator(*this, 0, col_num + 1);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_col_iterator
- SpMat<eT>::end_col(const uword col_num) const
- {
- sync_csc();
-
- return const_col_iterator(*this, 0, col_num + 1);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::col_iterator
- SpMat<eT>::end_col_no_sync(const uword col_num)
- {
- return col_iterator(*this, 0, col_num + 1);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_col_iterator
- SpMat<eT>::end_col_no_sync(const uword col_num) const
- {
- return const_col_iterator(*this, 0, col_num + 1);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::row_iterator
- SpMat<eT>::begin_row(const uword row_num)
- {
- sync_csc();
-
- return row_iterator(*this, row_num, 0);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_row_iterator
- SpMat<eT>::begin_row(const uword row_num) const
- {
- sync_csc();
-
- return const_row_iterator(*this, row_num, 0);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::row_iterator
- SpMat<eT>::end_row()
- {
- sync_csc();
-
- return row_iterator(*this, n_nonzero);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_row_iterator
- SpMat<eT>::end_row() const
- {
- sync_csc();
-
- return const_row_iterator(*this, n_nonzero);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::row_iterator
- SpMat<eT>::end_row(const uword row_num)
- {
- sync_csc();
-
- return row_iterator(*this, row_num + 1, 0);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_row_iterator
- SpMat<eT>::end_row(const uword row_num) const
- {
- sync_csc();
-
- return const_row_iterator(*this, row_num + 1, 0);
- }
- template<typename eT>
- inline
- typename SpMat<eT>::row_col_iterator
- SpMat<eT>::begin_row_col()
- {
- sync_csc();
-
- return begin();
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_row_col_iterator
- SpMat<eT>::begin_row_col() const
- {
- sync_csc();
-
- return begin();
- }
- template<typename eT>
- inline typename SpMat<eT>::row_col_iterator
- SpMat<eT>::end_row_col()
- {
- sync_csc();
-
- return end();
- }
- template<typename eT>
- inline
- typename SpMat<eT>::const_row_col_iterator
- SpMat<eT>::end_row_col() const
- {
- sync_csc();
-
- return end();
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::clear()
- {
- (*this).reset();
- }
- template<typename eT>
- inline
- bool
- SpMat<eT>::empty() const
- {
- return (n_elem == 0);
- }
- template<typename eT>
- inline
- uword
- SpMat<eT>::size() const
- {
- return n_elem;
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- SpMat_MapMat_val<eT>
- SpMat<eT>::front()
- {
- arma_debug_check( (n_elem == 0), "SpMat::front(): matrix is empty" );
-
- return SpMat_MapMat_val<eT>((*this), cache, 0, 0);
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- eT
- SpMat<eT>::front() const
- {
- arma_debug_check( (n_elem == 0), "SpMat::front(): matrix is empty" );
-
- return get_value(0,0);
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- SpMat_MapMat_val<eT>
- SpMat<eT>::back()
- {
- arma_debug_check( (n_elem == 0), "SpMat::back(): matrix is empty" );
-
- return SpMat_MapMat_val<eT>((*this), cache, n_rows-1, n_cols-1);
- }
- template<typename eT>
- arma_inline
- arma_warn_unused
- eT
- SpMat<eT>::back() const
- {
- arma_debug_check( (n_elem == 0), "SpMat::back(): matrix is empty" );
-
- return get_value(n_rows-1, n_cols-1);
- }
- template<typename eT>
- inline
- arma_hot
- arma_warn_unused
- eT
- SpMat<eT>::get_value(const uword i) const
- {
- const MapMat<eT>& const_cache = cache; // declare as const for clarity of intent
-
- // get the element from the cache if it has more recent data than CSC
-
- return (sync_state == 1) ? const_cache.operator[](i) : get_value_csc(i);
- }
- template<typename eT>
- inline
- arma_hot
- arma_warn_unused
- eT
- SpMat<eT>::get_value(const uword in_row, const uword in_col) const
- {
- const MapMat<eT>& const_cache = cache; // declare as const for clarity of intent
-
- // get the element from the cache if it has more recent data than CSC
-
- return (sync_state == 1) ? const_cache.at(in_row, in_col) : get_value_csc(in_row, in_col);
- }
- template<typename eT>
- inline
- arma_hot
- arma_warn_unused
- eT
- SpMat<eT>::get_value_csc(const uword i) const
- {
- // First convert to the actual location.
- uword lcol = i / n_rows; // Integer division.
- uword lrow = i % n_rows;
-
- return get_value_csc(lrow, lcol);
- }
- template<typename eT>
- inline
- arma_hot
- arma_warn_unused
- const eT*
- SpMat<eT>::find_value_csc(const uword in_row, const uword in_col) const
- {
- const uword col_offset = col_ptrs[in_col ];
- const uword next_col_offset = col_ptrs[in_col + 1];
-
- const uword* start_ptr = &row_indices[ col_offset];
- const uword* end_ptr = &row_indices[next_col_offset];
-
- const uword* pos_ptr = std::lower_bound(start_ptr, end_ptr, in_row); // binary search
-
- if( (pos_ptr != end_ptr) && ((*pos_ptr) == in_row) )
- {
- const uword offset = uword(pos_ptr - start_ptr);
- const uword index = offset + col_offset;
-
- return &(values[index]);
- }
-
- return NULL;
- }
- template<typename eT>
- inline
- arma_hot
- arma_warn_unused
- eT
- SpMat<eT>::get_value_csc(const uword in_row, const uword in_col) const
- {
- const eT* val_ptr = find_value_csc(in_row, in_col);
-
- return (val_ptr != NULL) ? eT(*val_ptr) : eT(0);
- }
- template<typename eT>
- inline
- arma_hot
- arma_warn_unused
- bool
- SpMat<eT>::try_set_value_csc(const uword in_row, const uword in_col, const eT in_val)
- {
- const eT* val_ptr = find_value_csc(in_row, in_col);
-
- // element not found, ie. it's zero; fail if trying to set it to non-zero value
- if(val_ptr == NULL) { return (in_val == eT(0)); }
-
- // fail if trying to erase an existing element
- if(in_val == eT(0)) { return false; }
-
- access::rw(*val_ptr) = in_val;
-
- invalidate_cache();
-
- return true;
- }
- template<typename eT>
- inline
- arma_hot
- arma_warn_unused
- bool
- SpMat<eT>::try_add_value_csc(const uword in_row, const uword in_col, const eT in_val)
- {
- const eT* val_ptr = find_value_csc(in_row, in_col);
-
- // element not found, ie. it's zero; fail if trying to add a non-zero value
- if(val_ptr == NULL) { return (in_val == eT(0)); }
-
- const eT new_val = eT(*val_ptr) + in_val;
-
- // fail if trying to erase an existing element
- if(new_val == eT(0)) { return false; }
-
- access::rw(*val_ptr) = new_val;
-
- invalidate_cache();
-
- return true;
- }
- template<typename eT>
- inline
- arma_hot
- arma_warn_unused
- bool
- SpMat<eT>::try_sub_value_csc(const uword in_row, const uword in_col, const eT in_val)
- {
- const eT* val_ptr = find_value_csc(in_row, in_col);
-
- // element not found, ie. it's zero; fail if trying to subtract a non-zero value
- if(val_ptr == NULL) { return (in_val == eT(0)); }
-
- const eT new_val = eT(*val_ptr) - in_val;
-
- // fail if trying to erase an existing element
- if(new_val == eT(0)) { return false; }
-
- access::rw(*val_ptr) = new_val;
-
- invalidate_cache();
-
- return true;
- }
- template<typename eT>
- inline
- arma_hot
- arma_warn_unused
- bool
- SpMat<eT>::try_mul_value_csc(const uword in_row, const uword in_col, const eT in_val)
- {
- const eT* val_ptr = find_value_csc(in_row, in_col);
-
- // element not found, ie. it's zero; succeed if given value is finite; zero multiplied by anything is zero, except for nan and inf
- if(val_ptr == NULL) { return arma_isfinite(in_val); }
-
- const eT new_val = eT(*val_ptr) * in_val;
-
- // fail if trying to erase an existing element
- if(new_val == eT(0)) { return false; }
-
- access::rw(*val_ptr) = new_val;
-
- invalidate_cache();
-
- return true;
- }
- template<typename eT>
- inline
- arma_hot
- arma_warn_unused
- bool
- SpMat<eT>::try_div_value_csc(const uword in_row, const uword in_col, const eT in_val)
- {
- const eT* val_ptr = find_value_csc(in_row, in_col);
-
- // element not found, ie. it's zero; succeed if given value is not zero and not nan; zero divided by anything is zero, except for zero and nan
- if(val_ptr == NULL) { return ((in_val != eT(0)) && (arma_isnan(in_val) == false)); }
-
- const eT new_val = eT(*val_ptr) / in_val;
-
- // fail if trying to erase an existing element
- if(new_val == eT(0)) { return false; }
-
- access::rw(*val_ptr) = new_val;
-
- invalidate_cache();
-
- return true;
- }
- /**
- * Insert an element at the given position, and return a reference to it.
- * The element will be set to 0, unless otherwise specified.
- * If the element already exists, its value will be overwritten.
- */
- template<typename eT>
- inline
- arma_warn_unused
- eT&
- SpMat<eT>::insert_element(const uword in_row, const uword in_col, const eT val)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
- invalidate_cache();
-
- // We will assume the new element does not exist and begin the search for
- // where to insert it. If we find that it already exists, we will then
- // overwrite it.
- uword colptr = col_ptrs[in_col ];
- uword next_colptr = col_ptrs[in_col + 1];
-
- uword pos = colptr; // The position in the matrix of this value.
-
- if(colptr != next_colptr)
- {
- // There are other elements in this column, so we must find where this
- // element will fit as compared to those.
- while(pos < next_colptr && in_row > row_indices[pos])
- {
- pos++;
- }
-
- // We aren't inserting into the last position, so it is still possible
- // that the element may exist.
- if(pos != next_colptr && row_indices[pos] == in_row)
- {
- // It already exists. Then, just overwrite it.
- access::rw(values[pos]) = val;
-
- return access::rw(values[pos]);
- }
- }
-
-
- //
- // Element doesn't exist, so we have to insert it
- //
-
- // We have to update the rest of the column pointers.
- for(uword i = in_col + 1; i < n_cols + 1; i++)
- {
- access::rw(col_ptrs[i])++; // We are only inserting one new element.
- }
-
- const uword old_n_nonzero = n_nonzero;
-
- access::rw(n_nonzero)++; // Add to count of nonzero elements.
-
- // Allocate larger memory.
- eT* new_values = memory::acquire<eT> (n_nonzero + 1);
- uword* new_row_indices = memory::acquire<uword>(n_nonzero + 1);
-
- // Copy things over, before the new element.
- if(pos > 0)
- {
- arrayops::copy(new_values, values, pos);
- arrayops::copy(new_row_indices, row_indices, pos);
- }
-
- // Insert the new element.
- new_values[pos] = val;
- new_row_indices[pos] = in_row;
-
- // Copy the rest of things over (including the extra element at the end).
- arrayops::copy(new_values + pos + 1, values + pos, (old_n_nonzero - pos) + 1);
- arrayops::copy(new_row_indices + pos + 1, row_indices + pos, (old_n_nonzero - pos) + 1);
-
- // Assign new pointers.
- if(values) { memory::release(access::rw(values)); }
- if(row_indices) { memory::release(access::rw(row_indices)); }
-
- access::rw(values) = new_values;
- access::rw(row_indices) = new_row_indices;
-
- return access::rw(values[pos]);
- }
- /**
- * Delete an element at the given position.
- */
- template<typename eT>
- inline
- void
- SpMat<eT>::delete_element(const uword in_row, const uword in_col)
- {
- arma_extra_debug_sigprint();
-
- sync_csc();
- invalidate_cache();
-
- // We assume the element exists (although... it may not) and look for its
- // exact position. If it doesn't exist... well, we don't need to do anything.
- uword colptr = col_ptrs[in_col];
- uword next_colptr = col_ptrs[in_col + 1];
-
- if(colptr != next_colptr)
- {
- // There's at least one element in this column.
- // Let's see if we are one of them.
- for(uword pos = colptr; pos < next_colptr; pos++)
- {
- if(in_row == row_indices[pos])
- {
- --access::rw(n_nonzero); // Remove one from the count of nonzero elements.
-
- // Found it. Now remove it.
-
- // Make new arrays.
- eT* new_values = memory::acquire<eT> (n_nonzero + 1);
- uword* new_row_indices = memory::acquire<uword>(n_nonzero + 1);
-
- if(pos > 0)
- {
- arrayops::copy(new_values, values, pos);
- arrayops::copy(new_row_indices, row_indices, pos);
- }
-
- arrayops::copy(new_values + pos, values + pos + 1, (n_nonzero - pos) + 1);
- arrayops::copy(new_row_indices + pos, row_indices + pos + 1, (n_nonzero - pos) + 1);
-
- if(values) { memory::release(access::rw(values)); }
- if(row_indices) { memory::release(access::rw(row_indices)); }
-
- access::rw(values) = new_values;
- access::rw(row_indices) = new_row_indices;
-
- // And lastly, update all the column pointers (decrement by one).
- for(uword i = in_col + 1; i < n_cols + 1; i++)
- {
- --access::rw(col_ptrs[i]); // We only removed one element.
- }
-
- return; // There is nothing left to do.
- }
- }
- }
-
- return; // The element does not exist, so there's nothing for us to do.
- }
- template<typename eT>
- arma_inline
- void
- SpMat<eT>::invalidate_cache() const
- {
- arma_extra_debug_sigprint();
-
- if(sync_state == 0) { return; }
-
- cache.reset();
-
- sync_state = 0;
- }
- template<typename eT>
- arma_inline
- void
- SpMat<eT>::invalidate_csc() const
- {
- arma_extra_debug_sigprint();
-
- sync_state = 1;
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::sync_cache() const
- {
- arma_extra_debug_sigprint();
-
- // using approach adapted from http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/
- //
- // OpenMP mode:
- // sync_state uses atomic read/write, which has an implied flush;
- // flush is also implicitly executed at the entrance and the exit of critical section;
- // data races are prevented by the 'critical' directive
- //
- // C++11 mode:
- // underlying type for sync_state is std::atomic<int>;
- // reading and writing to sync_state uses std::memory_order_seq_cst which has an implied fence;
- // data races are prevented via the mutex
-
- #if defined(ARMA_USE_OPENMP)
- {
- if(sync_state == 0)
- {
- #pragma omp critical (arma_SpMat_cache)
- {
- sync_cache_simple();
- }
- }
- }
- #elif (defined(ARMA_USE_CXX11) && !defined(ARMA_DONT_USE_CXX11_MUTEX))
- {
- if(sync_state == 0)
- {
- cache_mutex.lock();
-
- sync_cache_simple();
-
- cache_mutex.unlock();
- }
- }
- #else
- {
- sync_cache_simple();
- }
- #endif
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::sync_cache_simple() const
- {
- arma_extra_debug_sigprint();
-
- if(sync_state == 0)
- {
- cache = (*this);
- sync_state = 2;
- }
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::sync_csc() const
- {
- arma_extra_debug_sigprint();
-
- #if defined(ARMA_USE_OPENMP)
- if(sync_state == 1)
- {
- #pragma omp critical (arma_SpMat_cache)
- {
- sync_csc_simple();
- }
- }
- #elif (defined(ARMA_USE_CXX11) && !defined(ARMA_DONT_USE_CXX11_MUTEX))
- if(sync_state == 1)
- {
- cache_mutex.lock();
-
- sync_csc_simple();
-
- cache_mutex.unlock();
- }
- #else
- {
- sync_csc_simple();
- }
- #endif
- }
- template<typename eT>
- inline
- void
- SpMat<eT>::sync_csc_simple() const
- {
- arma_extra_debug_sigprint();
-
- // method:
- // 1. construct temporary matrix to prevent the cache from getting zapped
- // 2. steal memory from the temporary matrix
-
- // sync_state is only set to 1 by non-const element access operators,
- // so the shenanigans with const_cast are to satisfy the compiler
-
- // see also the note in sync_cache() above
-
- if(sync_state == 1)
- {
- SpMat<eT>& x = const_cast< SpMat<eT>& >(*this);
-
- SpMat<eT> tmp(cache);
-
- x.steal_mem_simple(tmp);
-
- sync_state = 2;
- }
- }
- //
- // SpMat_aux
- template<typename eT, typename T1>
- inline
- void
- SpMat_aux::set_real(SpMat<eT>& out, const SpBase<eT,T1>& X)
- {
- arma_extra_debug_sigprint();
-
- const unwrap_spmat<T1> tmp(X.get_ref());
- const SpMat<eT>& A = tmp.M;
-
- arma_debug_assert_same_size( out, A, "SpMat::set_real()" );
-
- out = A;
- }
- template<typename eT, typename T1>
- inline
- void
- SpMat_aux::set_imag(SpMat<eT>&, const SpBase<eT,T1>&)
- {
- arma_extra_debug_sigprint();
- }
- template<typename T, typename T1>
- inline
- void
- SpMat_aux::set_real(SpMat< std::complex<T> >& out, const SpBase<T,T1>& X)
- {
- arma_extra_debug_sigprint();
-
- typedef typename std::complex<T> eT;
-
- const unwrap_spmat<T1> U(X.get_ref());
- const SpMat<T>& Y = U.M;
-
- arma_debug_assert_same_size(out, Y, "SpMat::set_real()");
-
- SpMat<eT> tmp(Y,arma::imag(out)); // arma:: prefix required due to bugs in GCC 4.4 - 4.6
-
- out.steal_mem(tmp);
- }
- template<typename T, typename T1>
- inline
- void
- SpMat_aux::set_imag(SpMat< std::complex<T> >& out, const SpBase<T,T1>& X)
- {
- arma_extra_debug_sigprint();
-
- typedef typename std::complex<T> eT;
-
- const unwrap_spmat<T1> U(X.get_ref());
- const SpMat<T>& Y = U.M;
-
- arma_debug_assert_same_size(out, Y, "SpMat::set_imag()");
-
- SpMat<eT> tmp(arma::real(out),Y); // arma:: prefix required due to bugs in GCC 4.4 - 4.6
-
- out.steal_mem(tmp);
- }
- #ifdef ARMA_EXTRA_SPMAT_MEAT
- #include ARMA_INCFILE_WRAP(ARMA_EXTRA_SPMAT_MEAT)
- #endif
- //! @}
|