MatX.cpp 112 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../precompiled.h"
  22. //===============================================================
  23. //
  24. // idMatX
  25. //
  26. //===============================================================
  27. float idMatX::temp[MATX_MAX_TEMP+4];
  28. float * idMatX::tempPtr = (float *) ( ( (int) idMatX::temp + 15 ) & ~15 );
  29. int idMatX::tempIndex = 0;
  30. /*
  31. ============
  32. idMatX::ChangeSize
  33. ============
  34. */
  35. void idMatX::ChangeSize( int rows, int columns, bool makeZero ) {
  36. int alloc = ( rows * columns + 3 ) & ~3;
  37. if ( alloc > alloced && alloced != -1 ) {
  38. float *oldMat = mat;
  39. mat = (float *) Mem_Alloc16( alloc * sizeof( float ), TAG_MATH );
  40. if ( makeZero ) {
  41. memset( mat, 0, alloc * sizeof( float ) );
  42. }
  43. alloced = alloc;
  44. if ( oldMat ) {
  45. int minRow = Min( numRows, rows );
  46. int minColumn = Min( numColumns, columns );
  47. for ( int i = 0; i < minRow; i++ ) {
  48. for ( int j = 0; j < minColumn; j++ ) {
  49. mat[ i * columns + j ] = oldMat[ i * numColumns + j ];
  50. }
  51. }
  52. Mem_Free16( oldMat );
  53. }
  54. } else {
  55. if ( columns < numColumns ) {
  56. int minRow = Min( numRows, rows );
  57. for ( int i = 0; i < minRow; i++ ) {
  58. for ( int j = 0; j < columns; j++ ) {
  59. mat[ i * columns + j ] = mat[ i * numColumns + j ];
  60. }
  61. }
  62. } else if ( columns > numColumns ) {
  63. for ( int i = Min( numRows, rows ) - 1; i >= 0; i-- ) {
  64. if ( makeZero ) {
  65. for ( int j = columns - 1; j >= numColumns; j-- ) {
  66. mat[ i * columns + j ] = 0.0f;
  67. }
  68. }
  69. for ( int j = numColumns - 1; j >= 0; j-- ) {
  70. mat[ i * columns + j ] = mat[ i * numColumns + j ];
  71. }
  72. }
  73. }
  74. if ( makeZero && rows > numRows ) {
  75. memset( mat + numRows * columns, 0, ( rows - numRows ) * columns * sizeof( float ) );
  76. }
  77. }
  78. numRows = rows;
  79. numColumns = columns;
  80. MATX_CLEAREND();
  81. }
  82. /*
  83. ============
  84. idMatX::RemoveRow
  85. ============
  86. */
  87. idMatX &idMatX::RemoveRow( int r ) {
  88. int i;
  89. assert( r < numRows );
  90. numRows--;
  91. for ( i = r; i < numRows; i++ ) {
  92. memcpy( &mat[i * numColumns], &mat[( i + 1 ) * numColumns], numColumns * sizeof( float ) );
  93. }
  94. return *this;
  95. }
  96. /*
  97. ============
  98. idMatX::RemoveColumn
  99. ============
  100. */
  101. idMatX &idMatX::RemoveColumn( int r ) {
  102. int i;
  103. assert( r < numColumns );
  104. numColumns--;
  105. for ( i = 0; i < numRows - 1; i++ ) {
  106. memmove( &mat[i * numColumns + r], &mat[i * ( numColumns + 1 ) + r + 1], numColumns * sizeof( float ) );
  107. }
  108. memmove( &mat[i * numColumns + r], &mat[i * ( numColumns + 1 ) + r + 1], ( numColumns - r ) * sizeof( float ) );
  109. return *this;
  110. }
  111. /*
  112. ============
  113. idMatX::RemoveRowColumn
  114. ============
  115. */
  116. idMatX &idMatX::RemoveRowColumn( int r ) {
  117. int i;
  118. assert( r < numRows && r < numColumns );
  119. numRows--;
  120. numColumns--;
  121. if ( r > 0 ) {
  122. for ( i = 0; i < r - 1; i++ ) {
  123. memmove( &mat[i * numColumns + r], &mat[i * ( numColumns + 1 ) + r + 1], numColumns * sizeof( float ) );
  124. }
  125. memmove( &mat[i * numColumns + r], &mat[i * ( numColumns + 1 ) + r + 1], ( numColumns - r ) * sizeof( float ) );
  126. }
  127. memcpy( &mat[r * numColumns], &mat[( r + 1 ) * ( numColumns + 1 )], r * sizeof( float ) );
  128. for ( i = r; i < numRows - 1; i++ ) {
  129. memcpy( &mat[i * numColumns + r], &mat[( i + 1 ) * ( numColumns + 1 ) + r + 1], numColumns * sizeof( float ) );
  130. }
  131. memcpy( &mat[i * numColumns + r], &mat[( i + 1 ) * ( numColumns + 1 ) + r + 1], ( numColumns - r ) * sizeof( float ) );
  132. return *this;
  133. }
  134. /*
  135. ========================
  136. idMatX::CopyLowerToUpperTriangle
  137. ========================
  138. */
  139. void idMatX::CopyLowerToUpperTriangle() {
  140. assert( ( GetNumColumns() & 3 ) == 0 );
  141. assert( GetNumColumns() >= GetNumRows() );
  142. #ifdef ID_WIN_X86_SSE_INTRIN
  143. const int n = GetNumColumns();
  144. const int m = GetNumRows();
  145. const int n0 = 0;
  146. const int n1 = n;
  147. const int n2 = ( n << 1 );
  148. const int n3 = ( n << 1 ) + n;
  149. const int n4 = ( n << 2 );
  150. const int b1 = ( ( m - 0 ) >> 1 ) & 1; // ( m & 3 ) > 1
  151. const int b2 = ( ( m - 1 ) >> 1 ) & 1; // ( m & 3 ) > 2 (provided ( m & 3 ) > 0)
  152. const int n1_masked = ( n & -b1 );
  153. const int n2_masked = ( n & -b1 ) + ( n & -b2 );
  154. const __m128 mask0 = __m128c( _mm_set_epi32( 0, 0, 0, -1 ) );
  155. const __m128 mask1 = __m128c( _mm_set_epi32( 0, 0, -1, -1 ) );
  156. const __m128 mask2 = __m128c( _mm_set_epi32( 0, -1, -1, -1 ) );
  157. const __m128 mask3 = __m128c( _mm_set_epi32( -1, -1, -1, -1 ) );
  158. const __m128 bottomMask[2] = { __m128c( _mm_set1_epi32( 0 ) ), __m128c( _mm_set1_epi32( -1 ) ) };
  159. float * __restrict basePtr = ToFloatPtr();
  160. for ( int i = 0; i < m - 3; i += 4 ) {
  161. // copy top left diagonal 4x4 block elements
  162. __m128 r0 = _mm_and_ps( _mm_load_ps( basePtr + n0 ), mask0 );
  163. __m128 r1 = _mm_and_ps( _mm_load_ps( basePtr + n1 ), mask1 );
  164. __m128 r2 = _mm_and_ps( _mm_load_ps( basePtr + n2 ), mask2 );
  165. __m128 r3 = _mm_and_ps( _mm_load_ps( basePtr + n3 ), mask3 );
  166. __m128 t0 = _mm_unpacklo_ps( r0, r2 ); // x0, z0, x1, z1
  167. __m128 t1 = _mm_unpackhi_ps( r0, r2 ); // x2, z2, x3, z3
  168. __m128 t2 = _mm_unpacklo_ps( r1, r3 ); // y0, w0, y1, w1
  169. __m128 t3 = _mm_unpackhi_ps( r1, r3 ); // y2, w2, y3, w3
  170. __m128 s0 = _mm_unpacklo_ps( t0, t2 ); // x0, y0, z0, w0
  171. __m128 s1 = _mm_unpackhi_ps( t0, t2 ); // x1, y1, z1, w1
  172. __m128 s2 = _mm_unpacklo_ps( t1, t3 ); // x2, y2, z2, w2
  173. __m128 s3 = _mm_unpackhi_ps( t1, t3 ); // x3, y3, z3, w3
  174. r0 = _mm_or_ps( r0, s0 );
  175. r1 = _mm_or_ps( r1, s1 );
  176. r2 = _mm_or_ps( r2, s2 );
  177. r3 = _mm_or_ps( r3, s3 );
  178. _mm_store_ps( basePtr + n0, r0 );
  179. _mm_store_ps( basePtr + n1, r1 );
  180. _mm_store_ps( basePtr + n2, r2 );
  181. _mm_store_ps( basePtr + n3, r3 );
  182. // copy one column of 4x4 blocks to one row of 4x4 blocks
  183. const float * __restrict srcPtr = basePtr;
  184. float * __restrict dstPtr = basePtr;
  185. for ( int j = i + 4; j < m - 3; j += 4 ) {
  186. srcPtr += n4;
  187. dstPtr += 4;
  188. __m128 r0 = _mm_load_ps( srcPtr + n0 );
  189. __m128 r1 = _mm_load_ps( srcPtr + n1 );
  190. __m128 r2 = _mm_load_ps( srcPtr + n2 );
  191. __m128 r3 = _mm_load_ps( srcPtr + n3 );
  192. __m128 t0 = _mm_unpacklo_ps( r0, r2 ); // x0, z0, x1, z1
  193. __m128 t1 = _mm_unpackhi_ps( r0, r2 ); // x2, z2, x3, z3
  194. __m128 t2 = _mm_unpacklo_ps( r1, r3 ); // y0, w0, y1, w1
  195. __m128 t3 = _mm_unpackhi_ps( r1, r3 ); // y2, w2, y3, w3
  196. r0 = _mm_unpacklo_ps( t0, t2 ); // x0, y0, z0, w0
  197. r1 = _mm_unpackhi_ps( t0, t2 ); // x1, y1, z1, w1
  198. r2 = _mm_unpacklo_ps( t1, t3 ); // x2, y2, z2, w2
  199. r3 = _mm_unpackhi_ps( t1, t3 ); // x3, y3, z3, w3
  200. _mm_store_ps( dstPtr + n0, r0 );
  201. _mm_store_ps( dstPtr + n1, r1 );
  202. _mm_store_ps( dstPtr + n2, r2 );
  203. _mm_store_ps( dstPtr + n3, r3 );
  204. }
  205. // copy the last partial 4x4 block elements
  206. if ( m & 3 ) {
  207. srcPtr += n4;
  208. dstPtr += 4;
  209. __m128 r0 = _mm_load_ps( srcPtr + n0 );
  210. __m128 r1 = _mm_and_ps( _mm_load_ps( srcPtr + n1_masked ), bottomMask[b1] );
  211. __m128 r2 = _mm_and_ps( _mm_load_ps( srcPtr + n2_masked ), bottomMask[b2] );
  212. __m128 r3 = _mm_setzero_ps();
  213. __m128 t0 = _mm_unpacklo_ps( r0, r2 ); // x0, z0, x1, z1
  214. __m128 t1 = _mm_unpackhi_ps( r0, r2 ); // x2, z2, x3, z3
  215. __m128 t2 = _mm_unpacklo_ps( r1, r3 ); // y0, w0, y1, w1
  216. __m128 t3 = _mm_unpackhi_ps( r1, r3 ); // y2, w2, y3, w3
  217. r0 = _mm_unpacklo_ps( t0, t2 ); // x0, y0, z0, w0
  218. r1 = _mm_unpackhi_ps( t0, t2 ); // x1, y1, z1, w1
  219. r2 = _mm_unpacklo_ps( t1, t3 ); // x2, y2, z2, w2
  220. r3 = _mm_unpackhi_ps( t1, t3 ); // x3, y3, z3, w3
  221. _mm_store_ps( dstPtr + n0, r0 );
  222. _mm_store_ps( dstPtr + n1, r1 );
  223. _mm_store_ps( dstPtr + n2, r2 );
  224. _mm_store_ps( dstPtr + n3, r3 );
  225. }
  226. basePtr += n4 + 4;
  227. }
  228. // copy the lower right partial diagonal 4x4 block elements
  229. if ( m & 3 ) {
  230. __m128 r0 = _mm_and_ps( _mm_load_ps( basePtr + n0 ), mask0 );
  231. __m128 r1 = _mm_and_ps( _mm_load_ps( basePtr + n1_masked ), _mm_and_ps( mask1, bottomMask[b1] ) );
  232. __m128 r2 = _mm_and_ps( _mm_load_ps( basePtr + n2_masked ), _mm_and_ps( mask2, bottomMask[b2] ) );
  233. __m128 r3 = _mm_setzero_ps();
  234. __m128 t0 = _mm_unpacklo_ps( r0, r2 ); // x0, z0, x1, z1
  235. __m128 t1 = _mm_unpackhi_ps( r0, r2 ); // x2, z2, x3, z3
  236. __m128 t2 = _mm_unpacklo_ps( r1, r3 ); // y0, w0, y1, w1
  237. __m128 t3 = _mm_unpackhi_ps( r1, r3 ); // y2, w2, y3, w3
  238. __m128 s0 = _mm_unpacklo_ps( t0, t2 ); // x0, y0, z0, w0
  239. __m128 s1 = _mm_unpackhi_ps( t0, t2 ); // x1, y1, z1, w1
  240. __m128 s2 = _mm_unpacklo_ps( t1, t3 ); // x2, y2, z2, w2
  241. r0 = _mm_or_ps( r0, s0 );
  242. r1 = _mm_or_ps( r1, s1 );
  243. r2 = _mm_or_ps( r2, s2 );
  244. _mm_store_ps( basePtr + n2_masked, r2 );
  245. _mm_store_ps( basePtr + n1_masked, r1 );
  246. _mm_store_ps( basePtr + n0, r0 );
  247. }
  248. #else
  249. const int n = GetNumColumns();
  250. const int m = GetNumRows();
  251. for ( int i = 0; i < m; i++ ) {
  252. const float * __restrict ptr = ToFloatPtr() + ( i + 1 ) * n + i;
  253. float * __restrict dstPtr = ToFloatPtr() + i * n;
  254. for ( int j = i + 1; j < m; j++ ) {
  255. dstPtr[j] = ptr[0];
  256. ptr += n;
  257. }
  258. }
  259. #endif
  260. #ifdef _DEBUG
  261. for ( int i = 0; i < numRows; i++ ) {
  262. for ( int j = 0; j < numRows; j++ ) {
  263. assert( mat[ i * numColumns + j ] == mat[ j * numColumns + i ] );
  264. }
  265. }
  266. #endif
  267. }
  268. /*
  269. ============
  270. idMatX::IsOrthogonal
  271. returns true if (*this) * this->Transpose() == Identity
  272. ============
  273. */
  274. bool idMatX::IsOrthogonal( const float epsilon ) const {
  275. float *ptr1, *ptr2, sum;
  276. if ( !IsSquare() ) {
  277. return false;
  278. }
  279. ptr1 = mat;
  280. for ( int i = 0; i < numRows; i++ ) {
  281. for ( int j = 0; j < numColumns; j++ ) {
  282. ptr2 = mat + j;
  283. sum = ptr1[0] * ptr2[0] - (float) ( i == j );
  284. for ( int n = 1; n < numColumns; n++ ) {
  285. ptr2 += numColumns;
  286. sum += ptr1[n] * ptr2[0];
  287. }
  288. if ( idMath::Fabs( sum ) > epsilon ) {
  289. return false;
  290. }
  291. }
  292. ptr1 += numColumns;
  293. }
  294. return true;
  295. }
  296. /*
  297. ============
  298. idMatX::IsOrthonormal
  299. returns true if (*this) * this->Transpose() == Identity and the length of each column vector is 1
  300. ============
  301. */
  302. bool idMatX::IsOrthonormal( const float epsilon ) const {
  303. float *ptr1, *ptr2, sum;
  304. if ( !IsSquare() ) {
  305. return false;
  306. }
  307. ptr1 = mat;
  308. for ( int i = 0; i < numRows; i++ ) {
  309. for ( int j = 0; j < numColumns; j++ ) {
  310. ptr2 = mat + j;
  311. sum = ptr1[0] * ptr2[0] - (float) ( i == j );
  312. for ( int n = 1; n < numColumns; n++ ) {
  313. ptr2 += numColumns;
  314. sum += ptr1[n] * ptr2[0];
  315. }
  316. if ( idMath::Fabs( sum ) > epsilon ) {
  317. return false;
  318. }
  319. }
  320. ptr1 += numColumns;
  321. ptr2 = mat + i;
  322. sum = ptr2[0] * ptr2[0] - 1.0f;
  323. for ( int j = 1; j < numRows; j++ ) {
  324. ptr2 += numColumns;
  325. sum += ptr2[j] * ptr2[j];
  326. }
  327. if ( idMath::Fabs( sum ) > epsilon ) {
  328. return false;
  329. }
  330. }
  331. return true;
  332. }
  333. /*
  334. ============
  335. idMatX::IsPMatrix
  336. returns true if the matrix is a P-matrix
  337. A square matrix is a P-matrix if all its principal minors are positive.
  338. ============
  339. */
  340. bool idMatX::IsPMatrix( const float epsilon ) const {
  341. int i, j;
  342. float d;
  343. idMatX m;
  344. if ( !IsSquare() ) {
  345. return false;
  346. }
  347. if ( numRows <= 0 ) {
  348. return true;
  349. }
  350. if ( (*this)[0][0] <= epsilon ) {
  351. return false;
  352. }
  353. if ( numRows <= 1 ) {
  354. return true;
  355. }
  356. m.SetData( numRows - 1, numColumns - 1, MATX_ALLOCA( ( numRows - 1 ) * ( numColumns - 1 ) ) );
  357. for ( i = 1; i < numRows; i++ ) {
  358. for ( j = 1; j < numColumns; j++ ) {
  359. m[i-1][j-1] = (*this)[i][j];
  360. }
  361. }
  362. if ( !m.IsPMatrix( epsilon ) ) {
  363. return false;
  364. }
  365. for ( i = 1; i < numRows; i++ ) {
  366. d = (*this)[i][0] / (*this)[0][0];
  367. for ( j = 1; j < numColumns; j++ ) {
  368. m[i-1][j-1] = (*this)[i][j] - d * (*this)[0][j];
  369. }
  370. }
  371. if ( !m.IsPMatrix( epsilon ) ) {
  372. return false;
  373. }
  374. return true;
  375. }
  376. /*
  377. ============
  378. idMatX::IsZMatrix
  379. returns true if the matrix is a Z-matrix
  380. A square matrix M is a Z-matrix if M[i][j] <= 0 for all i != j.
  381. ============
  382. */
  383. bool idMatX::IsZMatrix( const float epsilon ) const {
  384. int i, j;
  385. if ( !IsSquare() ) {
  386. return false;
  387. }
  388. for ( i = 0; i < numRows; i++ ) {
  389. for ( j = 0; j < numColumns; j++ ) {
  390. if ( (*this)[i][j] > epsilon && i != j ) {
  391. return false;
  392. }
  393. }
  394. }
  395. return true;
  396. }
  397. /*
  398. ============
  399. idMatX::IsPositiveDefinite
  400. returns true if the matrix is Positive Definite (PD)
  401. A square matrix M of order n is said to be PD if y'My > 0 for all vectors y of dimension n, y != 0.
  402. ============
  403. */
  404. bool idMatX::IsPositiveDefinite( const float epsilon ) const {
  405. int i, j, k;
  406. float d, s;
  407. idMatX m;
  408. // the matrix must be square
  409. if ( !IsSquare() ) {
  410. return false;
  411. }
  412. // copy matrix
  413. m.SetData( numRows, numColumns, MATX_ALLOCA( numRows * numColumns ) );
  414. m = *this;
  415. // add transpose
  416. for ( i = 0; i < numRows; i++ ) {
  417. for ( j = 0; j < numColumns; j++ ) {
  418. m[i][j] += (*this)[j][i];
  419. }
  420. }
  421. // test Positive Definiteness with Gaussian pivot steps
  422. for ( i = 0; i < numRows; i++ ) {
  423. for ( j = i; j < numColumns; j++ ) {
  424. if ( m[j][j] <= epsilon ) {
  425. return false;
  426. }
  427. }
  428. d = 1.0f / m[i][i];
  429. for ( j = i + 1; j < numColumns; j++ ) {
  430. s = d * m[j][i];
  431. m[j][i] = 0.0f;
  432. for ( k = i + 1; k < numRows; k++ ) {
  433. m[j][k] -= s * m[i][k];
  434. }
  435. }
  436. }
  437. return true;
  438. }
  439. /*
  440. ============
  441. idMatX::IsSymmetricPositiveDefinite
  442. returns true if the matrix is Symmetric Positive Definite (PD)
  443. ============
  444. */
  445. bool idMatX::IsSymmetricPositiveDefinite( const float epsilon ) const {
  446. idMatX m;
  447. // the matrix must be symmetric
  448. if ( !IsSymmetric( epsilon ) ) {
  449. return false;
  450. }
  451. // copy matrix
  452. m.SetData( numRows, numColumns, MATX_ALLOCA( numRows * numColumns ) );
  453. m = *this;
  454. // being able to obtain Cholesky factors is both a necessary and sufficient condition for positive definiteness
  455. return m.Cholesky_Factor();
  456. }
  457. /*
  458. ============
  459. idMatX::IsPositiveSemiDefinite
  460. returns true if the matrix is Positive Semi Definite (PSD)
  461. A square matrix M of order n is said to be PSD if y'My >= 0 for all vectors y of dimension n, y != 0.
  462. ============
  463. */
  464. bool idMatX::IsPositiveSemiDefinite( const float epsilon ) const {
  465. int i, j, k;
  466. float d, s;
  467. idMatX m;
  468. // the matrix must be square
  469. if ( !IsSquare() ) {
  470. return false;
  471. }
  472. // copy original matrix
  473. m.SetData( numRows, numColumns, MATX_ALLOCA( numRows * numColumns ) );
  474. m = *this;
  475. // add transpose
  476. for ( i = 0; i < numRows; i++ ) {
  477. for ( j = 0; j < numColumns; j++ ) {
  478. m[i][j] += (*this)[j][i];
  479. }
  480. }
  481. // test Positive Semi Definiteness with Gaussian pivot steps
  482. for ( i = 0; i < numRows; i++ ) {
  483. for ( j = i; j < numColumns; j++ ) {
  484. if ( m[j][j] < -epsilon ) {
  485. return false;
  486. }
  487. if ( m[j][j] > epsilon ) {
  488. continue;
  489. }
  490. for ( k = 0; k < numRows; k++ ) {
  491. if ( idMath::Fabs( m[k][j] ) > epsilon ) {
  492. return false;
  493. }
  494. if ( idMath::Fabs( m[j][k] ) > epsilon ) {
  495. return false;
  496. }
  497. }
  498. }
  499. if ( m[i][i] <= epsilon ) {
  500. continue;
  501. }
  502. d = 1.0f / m[i][i];
  503. for ( j = i + 1; j < numColumns; j++ ) {
  504. s = d * m[j][i];
  505. m[j][i] = 0.0f;
  506. for ( k = i + 1; k < numRows; k++ ) {
  507. m[j][k] -= s * m[i][k];
  508. }
  509. }
  510. }
  511. return true;
  512. }
  513. /*
  514. ============
  515. idMatX::IsSymmetricPositiveSemiDefinite
  516. returns true if the matrix is Symmetric Positive Semi Definite (PSD)
  517. ============
  518. */
  519. bool idMatX::IsSymmetricPositiveSemiDefinite( const float epsilon ) const {
  520. // the matrix must be symmetric
  521. if ( !IsSymmetric( epsilon ) ) {
  522. return false;
  523. }
  524. return IsPositiveSemiDefinite( epsilon );
  525. }
  526. /*
  527. ============
  528. idMatX::LowerTriangularInverse
  529. in-place inversion of the lower triangular matrix
  530. ============
  531. */
  532. bool idMatX::LowerTriangularInverse() {
  533. int i, j, k;
  534. double d, sum;
  535. for ( i = 0; i < numRows; i++ ) {
  536. d = (*this)[i][i];
  537. if ( d == 0.0f ) {
  538. return false;
  539. }
  540. (*this)[i][i] = d = 1.0f / d;
  541. for ( j = 0; j < i; j++ ) {
  542. sum = 0.0f;
  543. for ( k = j; k < i; k++ ) {
  544. sum -= (*this)[i][k] * (*this)[k][j];
  545. }
  546. (*this)[i][j] = sum * d;
  547. }
  548. }
  549. return true;
  550. }
  551. /*
  552. ============
  553. idMatX::UpperTriangularInverse
  554. in-place inversion of the upper triangular matrix
  555. ============
  556. */
  557. bool idMatX::UpperTriangularInverse() {
  558. int i, j, k;
  559. double d, sum;
  560. for ( i = numRows-1; i >= 0; i-- ) {
  561. d = (*this)[i][i];
  562. if ( d == 0.0f ) {
  563. return false;
  564. }
  565. (*this)[i][i] = d = 1.0f / d;
  566. for ( j = numRows-1; j > i; j-- ) {
  567. sum = 0.0f;
  568. for ( k = j; k > i; k-- ) {
  569. sum -= (*this)[i][k] * (*this)[k][j];
  570. }
  571. (*this)[i][j] = sum * d;
  572. }
  573. }
  574. return true;
  575. }
  576. /*
  577. =============
  578. idMatX::ToString
  579. =============
  580. */
  581. const char *idMatX::ToString( int precision ) const {
  582. return idStr::FloatArrayToString( ToFloatPtr(), GetDimension(), precision );
  583. }
  584. /*
  585. ============
  586. idMatX::Update_RankOne
  587. Updates the matrix to obtain the matrix: A + alpha * v * w'
  588. ============
  589. */
  590. void idMatX::Update_RankOne( const idVecX &v, const idVecX &w, float alpha ) {
  591. int i, j;
  592. float s;
  593. assert( v.GetSize() >= numRows );
  594. assert( w.GetSize() >= numColumns );
  595. for ( i = 0; i < numRows; i++ ) {
  596. s = alpha * v[i];
  597. for ( j = 0; j < numColumns; j++ ) {
  598. (*this)[i][j] += s * w[j];
  599. }
  600. }
  601. }
  602. /*
  603. ============
  604. idMatX::Update_RankOneSymmetric
  605. Updates the matrix to obtain the matrix: A + alpha * v * v'
  606. ============
  607. */
  608. void idMatX::Update_RankOneSymmetric( const idVecX &v, float alpha ) {
  609. int i, j;
  610. float s;
  611. assert( numRows == numColumns );
  612. assert( v.GetSize() >= numRows );
  613. for ( i = 0; i < numRows; i++ ) {
  614. s = alpha * v[i];
  615. for ( j = 0; j < numColumns; j++ ) {
  616. (*this)[i][j] += s * v[j];
  617. }
  618. }
  619. }
  620. /*
  621. ============
  622. idMatX::Update_RowColumn
  623. Updates the matrix to obtain the matrix:
  624. [ 0 a 0 ]
  625. A + [ d b e ]
  626. [ 0 c 0 ]
  627. where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1], d = w[0,r-1], w[r] = 0.0f, e = w[r+1,numColumns-1]
  628. ============
  629. */
  630. void idMatX::Update_RowColumn( const idVecX &v, const idVecX &w, int r ) {
  631. int i;
  632. assert( w[r] == 0.0f );
  633. assert( v.GetSize() >= numColumns );
  634. assert( w.GetSize() >= numRows );
  635. for ( i = 0; i < numRows; i++ ) {
  636. (*this)[i][r] += v[i];
  637. }
  638. for ( i = 0; i < numColumns; i++ ) {
  639. (*this)[r][i] += w[i];
  640. }
  641. }
  642. /*
  643. ============
  644. idMatX::Update_RowColumnSymmetric
  645. Updates the matrix to obtain the matrix:
  646. [ 0 a 0 ]
  647. A + [ a b c ]
  648. [ 0 c 0 ]
  649. where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1]
  650. ============
  651. */
  652. void idMatX::Update_RowColumnSymmetric( const idVecX &v, int r ) {
  653. int i;
  654. assert( numRows == numColumns );
  655. assert( v.GetSize() >= numRows );
  656. for ( i = 0; i < r; i++ ) {
  657. (*this)[i][r] += v[i];
  658. (*this)[r][i] += v[i];
  659. }
  660. (*this)[r][r] += v[r];
  661. for ( i = r+1; i < numRows; i++ ) {
  662. (*this)[i][r] += v[i];
  663. (*this)[r][i] += v[i];
  664. }
  665. }
  666. /*
  667. ============
  668. idMatX::Update_Increment
  669. Updates the matrix to obtain the matrix:
  670. [ A a ]
  671. [ c b ]
  672. where: a = v[0,numRows-1], b = v[numRows], c = w[0,numColumns-1]], w[numColumns] = 0
  673. ============
  674. */
  675. void idMatX::Update_Increment( const idVecX &v, const idVecX &w ) {
  676. int i;
  677. assert( numRows == numColumns );
  678. assert( v.GetSize() >= numRows+1 );
  679. assert( w.GetSize() >= numColumns+1 );
  680. ChangeSize( numRows+1, numColumns+1, false );
  681. for ( i = 0; i < numRows; i++ ) {
  682. (*this)[i][numColumns-1] = v[i];
  683. }
  684. for ( i = 0; i < numColumns-1; i++ ) {
  685. (*this)[numRows-1][i] = w[i];
  686. }
  687. }
  688. /*
  689. ============
  690. idMatX::Update_IncrementSymmetric
  691. Updates the matrix to obtain the matrix:
  692. [ A a ]
  693. [ a b ]
  694. where: a = v[0,numRows-1], b = v[numRows]
  695. ============
  696. */
  697. void idMatX::Update_IncrementSymmetric( const idVecX &v ) {
  698. int i;
  699. assert( numRows == numColumns );
  700. assert( v.GetSize() >= numRows+1 );
  701. ChangeSize( numRows+1, numColumns+1, false );
  702. for ( i = 0; i < numRows-1; i++ ) {
  703. (*this)[i][numColumns-1] = v[i];
  704. }
  705. for ( i = 0; i < numColumns; i++ ) {
  706. (*this)[numRows-1][i] = v[i];
  707. }
  708. }
  709. /*
  710. ============
  711. idMatX::Update_Decrement
  712. Updates the matrix to obtain a matrix with row r and column r removed.
  713. ============
  714. */
  715. void idMatX::Update_Decrement( int r ) {
  716. RemoveRowColumn( r );
  717. }
  718. /*
  719. ============
  720. idMatX::Inverse_GaussJordan
  721. in-place inversion using Gauss-Jordan elimination
  722. ============
  723. */
  724. bool idMatX::Inverse_GaussJordan() {
  725. int i, j, k, r, c;
  726. float d, max;
  727. assert( numRows == numColumns );
  728. int *columnIndex = (int *) _alloca16( numRows * sizeof( int ) );
  729. int *rowIndex = (int *) _alloca16( numRows * sizeof( int ) );
  730. bool *pivot = (bool *) _alloca16( numRows * sizeof( bool ) );
  731. memset( pivot, 0, numRows * sizeof( bool ) );
  732. // elimination with full pivoting
  733. for ( i = 0; i < numRows; i++ ) {
  734. // search the whole matrix except for pivoted rows for the maximum absolute value
  735. max = 0.0f;
  736. r = c = 0;
  737. for ( j = 0; j < numRows; j++ ) {
  738. if ( !pivot[j] ) {
  739. for ( k = 0; k < numRows; k++ ) {
  740. if ( !pivot[k] ) {
  741. d = idMath::Fabs( (*this)[j][k] );
  742. if ( d > max ) {
  743. max = d;
  744. r = j;
  745. c = k;
  746. }
  747. }
  748. }
  749. }
  750. }
  751. if ( max == 0.0f ) {
  752. // matrix is not invertible
  753. return false;
  754. }
  755. pivot[c] = true;
  756. // swap rows such that entry (c,c) has the pivot entry
  757. if ( r != c ) {
  758. SwapRows( r, c );
  759. }
  760. // keep track of the row permutation
  761. rowIndex[i] = r;
  762. columnIndex[i] = c;
  763. // scale the row to make the pivot entry equal to 1
  764. d = 1.0f / (*this)[c][c];
  765. (*this)[c][c] = 1.0f;
  766. for ( k = 0; k < numRows; k++ ) {
  767. (*this)[c][k] *= d;
  768. }
  769. // zero out the pivot column entries in the other rows
  770. for ( j = 0; j < numRows; j++ ) {
  771. if ( j != c ) {
  772. d = (*this)[j][c];
  773. (*this)[j][c] = 0.0f;
  774. for ( k = 0; k < numRows; k++ ) {
  775. (*this)[j][k] -= (*this)[c][k] * d;
  776. }
  777. }
  778. }
  779. }
  780. // reorder rows to store the inverse of the original matrix
  781. for ( j = numRows - 1; j >= 0; j-- ) {
  782. if ( rowIndex[j] != columnIndex[j] ) {
  783. for ( k = 0; k < numRows; k++ ) {
  784. d = (*this)[k][rowIndex[j]];
  785. (*this)[k][rowIndex[j]] = (*this)[k][columnIndex[j]];
  786. (*this)[k][columnIndex[j]] = d;
  787. }
  788. }
  789. }
  790. return true;
  791. }
  792. /*
  793. ============
  794. idMatX::Inverse_UpdateRankOne
  795. Updates the in-place inverse using the Sherman-Morrison formula to obtain the inverse for the matrix: A + alpha * v * w'
  796. ============
  797. */
  798. bool idMatX::Inverse_UpdateRankOne( const idVecX &v, const idVecX &w, float alpha ) {
  799. int i, j;
  800. float beta, s;
  801. idVecX y, z;
  802. assert( numRows == numColumns );
  803. assert( v.GetSize() >= numColumns );
  804. assert( w.GetSize() >= numRows );
  805. y.SetData( numRows, VECX_ALLOCA( numRows ) );
  806. z.SetData( numRows, VECX_ALLOCA( numRows ) );
  807. Multiply( y, v );
  808. TransposeMultiply( z, w );
  809. beta = 1.0f + ( w * y );
  810. if ( beta == 0.0f ) {
  811. return false;
  812. }
  813. alpha /= beta;
  814. for ( i = 0; i < numRows; i++ ) {
  815. s = y[i] * alpha;
  816. for ( j = 0; j < numColumns; j++ ) {
  817. (*this)[i][j] -= s * z[j];
  818. }
  819. }
  820. return true;
  821. }
  822. /*
  823. ============
  824. idMatX::Inverse_UpdateRowColumn
  825. Updates the in-place inverse to obtain the inverse for the matrix:
  826. [ 0 a 0 ]
  827. A + [ d b e ]
  828. [ 0 c 0 ]
  829. where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1], d = w[0,r-1], w[r] = 0.0f, e = w[r+1,numColumns-1]
  830. ============
  831. */
  832. bool idMatX::Inverse_UpdateRowColumn( const idVecX &v, const idVecX &w, int r ) {
  833. idVecX s;
  834. assert( numRows == numColumns );
  835. assert( v.GetSize() >= numColumns );
  836. assert( w.GetSize() >= numRows );
  837. assert( r >= 0 && r < numRows && r < numColumns );
  838. assert( w[r] == 0.0f );
  839. s.SetData( Max( numRows, numColumns ), VECX_ALLOCA( Max( numRows, numColumns ) ) );
  840. s.Zero();
  841. s[r] = 1.0f;
  842. if ( !Inverse_UpdateRankOne( v, s, 1.0f ) ) {
  843. return false;
  844. }
  845. if ( !Inverse_UpdateRankOne( s, w, 1.0f ) ) {
  846. return false;
  847. }
  848. return true;
  849. }
  850. /*
  851. ============
  852. idMatX::Inverse_UpdateIncrement
  853. Updates the in-place inverse to obtain the inverse for the matrix:
  854. [ A a ]
  855. [ c b ]
  856. where: a = v[0,numRows-1], b = v[numRows], c = w[0,numColumns-1], w[numColumns] = 0
  857. ============
  858. */
  859. bool idMatX::Inverse_UpdateIncrement( const idVecX &v, const idVecX &w ) {
  860. idVecX v2;
  861. assert( numRows == numColumns );
  862. assert( v.GetSize() >= numRows+1 );
  863. assert( w.GetSize() >= numColumns+1 );
  864. ChangeSize( numRows+1, numColumns+1, true );
  865. (*this)[numRows-1][numRows-1] = 1.0f;
  866. v2.SetData( numRows, VECX_ALLOCA( numRows ) );
  867. v2 = v;
  868. v2[numRows-1] -= 1.0f;
  869. return Inverse_UpdateRowColumn( v2, w, numRows-1 );
  870. }
  871. /*
  872. ============
  873. idMatX::Inverse_UpdateDecrement
  874. Updates the in-place inverse to obtain the inverse of the matrix with row r and column r removed.
  875. v and w should store the column and row of the original matrix respectively.
  876. ============
  877. */
  878. bool idMatX::Inverse_UpdateDecrement( const idVecX &v, const idVecX &w, int r ) {
  879. idVecX v1, w1;
  880. assert( numRows == numColumns );
  881. assert( v.GetSize() >= numRows );
  882. assert( w.GetSize() >= numColumns );
  883. assert( r >= 0 && r < numRows && r < numColumns );
  884. v1.SetData( numRows, VECX_ALLOCA( numRows ) );
  885. w1.SetData( numRows, VECX_ALLOCA( numRows ) );
  886. // update the row and column to identity
  887. v1 = -v;
  888. w1 = -w;
  889. v1[r] += 1.0f;
  890. w1[r] = 0.0f;
  891. if ( !Inverse_UpdateRowColumn( v1, w1, r ) ) {
  892. return false;
  893. }
  894. // physically remove the row and column
  895. Update_Decrement( r );
  896. return true;
  897. }
  898. /*
  899. ============
  900. idMatX::Inverse_Solve
  901. Solve Ax = b with A inverted
  902. ============
  903. */
  904. void idMatX::Inverse_Solve( idVecX &x, const idVecX &b ) const {
  905. Multiply( x, b );
  906. }
  907. /*
  908. ============
  909. idMatX::LU_Factor
  910. in-place factorization: LU
  911. L is a triangular matrix stored in the lower triangle.
  912. L has ones on the diagonal that are not stored.
  913. U is a triangular matrix stored in the upper triangle.
  914. If index != NULL partial pivoting is used for numerical stability.
  915. If index != NULL it must point to an array of numRow integers and is used to keep track of the row permutation.
  916. If det != NULL the determinant of the matrix is calculated and stored.
  917. ============
  918. */
  919. bool idMatX::LU_Factor( int *index, float *det ) {
  920. int i, j, k, newi, min;
  921. double s, t, d, w;
  922. // if partial pivoting should be used
  923. if ( index ) {
  924. for ( i = 0; i < numRows; i++ ) {
  925. index[i] = i;
  926. }
  927. }
  928. w = 1.0f;
  929. min = Min( numRows, numColumns );
  930. for ( i = 0; i < min; i++ ) {
  931. newi = i;
  932. s = idMath::Fabs( (*this)[i][i] );
  933. if ( index ) {
  934. // find the largest absolute pivot
  935. for ( j = i + 1; j < numRows; j++ ) {
  936. t = idMath::Fabs( (*this)[j][i] );
  937. if ( t > s ) {
  938. newi = j;
  939. s = t;
  940. }
  941. }
  942. }
  943. if ( s == 0.0f ) {
  944. return false;
  945. }
  946. if ( newi != i && index ) {
  947. w = -w;
  948. // swap index elements
  949. k = index[i];
  950. index[i] = index[newi];
  951. index[newi] = k;
  952. // swap rows
  953. for ( j = 0; j < numColumns; j++ ) {
  954. t = (*this)[newi][j];
  955. (*this)[newi][j] = (*this)[i][j];
  956. (*this)[i][j] = t;
  957. }
  958. }
  959. if ( i < numRows ) {
  960. d = 1.0f / (*this)[i][i];
  961. for ( j = i + 1; j < numRows; j++ ) {
  962. (*this)[j][i] *= d;
  963. }
  964. }
  965. if ( i < min-1 ) {
  966. for ( j = i + 1; j < numRows; j++ ) {
  967. d = (*this)[j][i];
  968. for ( k = i + 1; k < numColumns; k++ ) {
  969. (*this)[j][k] -= d * (*this)[i][k];
  970. }
  971. }
  972. }
  973. }
  974. if ( det ) {
  975. for ( i = 0; i < numRows; i++ ) {
  976. w *= (*this)[i][i];
  977. }
  978. *det = w;
  979. }
  980. return true;
  981. }
  982. /*
  983. ============
  984. idMatX::LU_UpdateRankOne
  985. Updates the in-place LU factorization to obtain the factors for the matrix: LU + alpha * v * w'
  986. ============
  987. */
  988. bool idMatX::LU_UpdateRankOne( const idVecX &v, const idVecX &w, float alpha, int *index ) {
  989. int i, j, max;
  990. float *y, *z;
  991. double diag, beta, p0, p1, d;
  992. assert( v.GetSize() >= numColumns );
  993. assert( w.GetSize() >= numRows );
  994. y = (float *) _alloca16( v.GetSize() * sizeof( float ) );
  995. z = (float *) _alloca16( w.GetSize() * sizeof( float ) );
  996. if ( index != NULL ) {
  997. for ( i = 0; i < numRows; i++ ) {
  998. y[i] = alpha * v[index[i]];
  999. }
  1000. } else {
  1001. for ( i = 0; i < numRows; i++ ) {
  1002. y[i] = alpha * v[i];
  1003. }
  1004. }
  1005. memcpy( z, w.ToFloatPtr(), w.GetSize() * sizeof( float ) );
  1006. max = Min( numRows, numColumns );
  1007. for ( i = 0; i < max; i++ ) {
  1008. diag = (*this)[i][i];
  1009. p0 = y[i];
  1010. p1 = z[i];
  1011. diag += p0 * p1;
  1012. if ( diag == 0.0f ) {
  1013. return false;
  1014. }
  1015. beta = p1 / diag;
  1016. (*this)[i][i] = diag;
  1017. for ( j = i+1; j < numColumns; j++ ) {
  1018. d = (*this)[i][j];
  1019. d += p0 * z[j];
  1020. z[j] -= beta * d;
  1021. (*this)[i][j] = d;
  1022. }
  1023. for ( j = i+1; j < numRows; j++ ) {
  1024. d = (*this)[j][i];
  1025. y[j] -= p0 * d;
  1026. d += beta * y[j];
  1027. (*this)[j][i] = d;
  1028. }
  1029. }
  1030. return true;
  1031. }
  1032. /*
  1033. ============
  1034. idMatX::LU_UpdateRowColumn
  1035. Updates the in-place LU factorization to obtain the factors for the matrix:
  1036. [ 0 a 0 ]
  1037. LU + [ d b e ]
  1038. [ 0 c 0 ]
  1039. where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1], d = w[0,r-1], w[r] = 0.0f, e = w[r+1,numColumns-1]
  1040. ============
  1041. */
  1042. bool idMatX::LU_UpdateRowColumn( const idVecX &v, const idVecX &w, int r, int *index ) {
  1043. #if 0
  1044. idVecX s;
  1045. assert( v.GetSize() >= numColumns );
  1046. assert( w.GetSize() >= numRows );
  1047. assert( r >= 0 && r < numRows && r < numColumns );
  1048. assert( w[r] == 0.0f );
  1049. s.SetData( Max( numRows, numColumns ), VECX_ALLOCA( Max( numRows, numColumns ) ) );
  1050. s.Zero();
  1051. s[r] = 1.0f;
  1052. if ( !LU_UpdateRankOne( v, s, 1.0f, index ) ) {
  1053. return false;
  1054. }
  1055. if ( !LU_UpdateRankOne( s, w, 1.0f, index ) ) {
  1056. return false;
  1057. }
  1058. return true;
  1059. #else
  1060. int i, j, min, max, rp;
  1061. float *y0, *y1, *z0, *z1;
  1062. double diag, beta0, beta1, p0, p1, q0, q1, d;
  1063. assert( v.GetSize() >= numColumns );
  1064. assert( w.GetSize() >= numRows );
  1065. assert( r >= 0 && r < numColumns && r < numRows );
  1066. assert( w[r] == 0.0f );
  1067. y0 = (float *) _alloca16( v.GetSize() * sizeof( float ) );
  1068. z0 = (float *) _alloca16( w.GetSize() * sizeof( float ) );
  1069. y1 = (float *) _alloca16( v.GetSize() * sizeof( float ) );
  1070. z1 = (float *) _alloca16( w.GetSize() * sizeof( float ) );
  1071. if ( index != NULL ) {
  1072. for ( i = 0; i < numRows; i++ ) {
  1073. y0[i] = v[index[i]];
  1074. }
  1075. rp = r;
  1076. for ( i = 0; i < numRows; i++ ) {
  1077. if ( index[i] == r ) {
  1078. rp = i;
  1079. break;
  1080. }
  1081. }
  1082. } else {
  1083. memcpy( y0, v.ToFloatPtr(), v.GetSize() * sizeof( float ) );
  1084. rp = r;
  1085. }
  1086. memset( y1, 0, v.GetSize() * sizeof( float ) );
  1087. y1[rp] = 1.0f;
  1088. memset( z0, 0, w.GetSize() * sizeof( float ) );
  1089. z0[r] = 1.0f;
  1090. memcpy( z1, w.ToFloatPtr(), w.GetSize() * sizeof( float ) );
  1091. // update the beginning of the to be updated row and column
  1092. min = Min( r, rp );
  1093. for ( i = 0; i < min; i++ ) {
  1094. p0 = y0[i];
  1095. beta1 = z1[i] / (*this)[i][i];
  1096. (*this)[i][r] += p0;
  1097. for ( j = i+1; j < numColumns; j++ ) {
  1098. z1[j] -= beta1 * (*this)[i][j];
  1099. }
  1100. for ( j = i+1; j < numRows; j++ ) {
  1101. y0[j] -= p0 * (*this)[j][i];
  1102. }
  1103. (*this)[rp][i] += beta1;
  1104. }
  1105. // update the lower right corner starting at r,r
  1106. max = Min( numRows, numColumns );
  1107. for ( i = min; i < max; i++ ) {
  1108. diag = (*this)[i][i];
  1109. p0 = y0[i];
  1110. p1 = z0[i];
  1111. diag += p0 * p1;
  1112. if ( diag == 0.0f ) {
  1113. return false;
  1114. }
  1115. beta0 = p1 / diag;
  1116. q0 = y1[i];
  1117. q1 = z1[i];
  1118. diag += q0 * q1;
  1119. if ( diag == 0.0f ) {
  1120. return false;
  1121. }
  1122. beta1 = q1 / diag;
  1123. (*this)[i][i] = diag;
  1124. for ( j = i+1; j < numColumns; j++ ) {
  1125. d = (*this)[i][j];
  1126. d += p0 * z0[j];
  1127. z0[j] -= beta0 * d;
  1128. d += q0 * z1[j];
  1129. z1[j] -= beta1 * d;
  1130. (*this)[i][j] = d;
  1131. }
  1132. for ( j = i+1; j < numRows; j++ ) {
  1133. d = (*this)[j][i];
  1134. y0[j] -= p0 * d;
  1135. d += beta0 * y0[j];
  1136. y1[j] -= q0 * d;
  1137. d += beta1 * y1[j];
  1138. (*this)[j][i] = d;
  1139. }
  1140. }
  1141. return true;
  1142. #endif
  1143. }
  1144. /*
  1145. ============
  1146. idMatX::LU_UpdateIncrement
  1147. Updates the in-place LU factorization to obtain the factors for the matrix:
  1148. [ A a ]
  1149. [ c b ]
  1150. where: a = v[0,numRows-1], b = v[numRows], c = w[0,numColumns-1], w[numColumns] = 0
  1151. ============
  1152. */
  1153. bool idMatX::LU_UpdateIncrement( const idVecX &v, const idVecX &w, int *index ) {
  1154. int i, j;
  1155. float sum;
  1156. assert( numRows == numColumns );
  1157. assert( v.GetSize() >= numRows+1 );
  1158. assert( w.GetSize() >= numColumns+1 );
  1159. ChangeSize( numRows+1, numColumns+1, true );
  1160. // add row to L
  1161. for ( i = 0; i < numRows - 1; i++ ) {
  1162. sum = w[i];
  1163. for ( j = 0; j < i; j++ ) {
  1164. sum -= (*this)[numRows - 1][j] * (*this)[j][i];
  1165. }
  1166. (*this)[numRows - 1 ][i] = sum / (*this)[i][i];
  1167. }
  1168. // add row to the permutation index
  1169. if ( index != NULL ) {
  1170. index[numRows - 1] = numRows - 1;
  1171. }
  1172. // add column to U
  1173. for ( i = 0; i < numRows; i++ ) {
  1174. if ( index != NULL ) {
  1175. sum = v[index[i]];
  1176. } else {
  1177. sum = v[i];
  1178. }
  1179. for ( j = 0; j < i; j++ ) {
  1180. sum -= (*this)[i][j] * (*this)[j][numRows - 1];
  1181. }
  1182. (*this)[i][numRows - 1] = sum;
  1183. }
  1184. return true;
  1185. }
  1186. /*
  1187. ============
  1188. idMatX::LU_UpdateDecrement
  1189. Updates the in-place LU factorization to obtain the factors for the matrix with row r and column r removed.
  1190. v and w should store the column and row of the original matrix respectively.
  1191. If index != NULL then u should store row index[r] of the original matrix. If index == NULL then u = w.
  1192. ============
  1193. */
  1194. bool idMatX::LU_UpdateDecrement( const idVecX &v, const idVecX &w, const idVecX &u, int r, int *index ) {
  1195. int i, p;
  1196. idVecX v1, w1;
  1197. assert( numRows == numColumns );
  1198. assert( v.GetSize() >= numColumns );
  1199. assert( w.GetSize() >= numRows );
  1200. assert( r >= 0 && r < numRows && r < numColumns );
  1201. v1.SetData( numRows, VECX_ALLOCA( numRows ) );
  1202. w1.SetData( numRows, VECX_ALLOCA( numRows ) );
  1203. if ( index != NULL ) {
  1204. // find the pivot row
  1205. for ( p = i = 0; i < numRows; i++ ) {
  1206. if ( index[i] == r ) {
  1207. p = i;
  1208. break;
  1209. }
  1210. }
  1211. // update the row and column to identity
  1212. v1 = -v;
  1213. w1 = -u;
  1214. if ( p != r ) {
  1215. SwapValues( v1[index[r]], v1[index[p]] );
  1216. SwapValues( index[r], index[p] );
  1217. }
  1218. v1[r] += 1.0f;
  1219. w1[r] = 0.0f;
  1220. if ( !LU_UpdateRowColumn( v1, w1, r, index ) ) {
  1221. return false;
  1222. }
  1223. if ( p != r ) {
  1224. if ( idMath::Fabs( u[p] ) < 1e-4f ) {
  1225. // NOTE: an additional row interchange is required for numerical stability
  1226. }
  1227. // move row index[r] of the original matrix to row index[p] of the original matrix
  1228. v1.Zero();
  1229. v1[index[p]] = 1.0f;
  1230. w1 = u - w;
  1231. if ( !LU_UpdateRankOne( v1, w1, 1.0f, index ) ) {
  1232. return false;
  1233. }
  1234. }
  1235. // remove the row from the permutation index
  1236. for ( i = r; i < numRows - 1; i++ ) {
  1237. index[i] = index[i+1];
  1238. }
  1239. for ( i = 0; i < numRows - 1; i++ ) {
  1240. if ( index[i] > r ) {
  1241. index[i]--;
  1242. }
  1243. }
  1244. } else {
  1245. v1 = -v;
  1246. w1 = -w;
  1247. v1[r] += 1.0f;
  1248. w1[r] = 0.0f;
  1249. if ( !LU_UpdateRowColumn( v1, w1, r, index ) ) {
  1250. return false;
  1251. }
  1252. }
  1253. // physically remove the row and column
  1254. Update_Decrement( r );
  1255. return true;
  1256. }
  1257. /*
  1258. ============
  1259. idMatX::LU_Solve
  1260. Solve Ax = b with A factored in-place as: LU
  1261. ============
  1262. */
  1263. void idMatX::LU_Solve( idVecX &x, const idVecX &b, const int *index ) const {
  1264. int i, j;
  1265. double sum;
  1266. assert( x.GetSize() == numColumns && b.GetSize() == numRows );
  1267. // solve L
  1268. for ( i = 0; i < numRows; i++ ) {
  1269. if ( index != NULL ) {
  1270. sum = b[index[i]];
  1271. } else {
  1272. sum = b[i];
  1273. }
  1274. for ( j = 0; j < i; j++ ) {
  1275. sum -= (*this)[i][j] * x[j];
  1276. }
  1277. x[i] = sum;
  1278. }
  1279. // solve U
  1280. for ( i = numRows - 1; i >= 0; i-- ) {
  1281. sum = x[i];
  1282. for ( j = i + 1; j < numRows; j++ ) {
  1283. sum -= (*this)[i][j] * x[j];
  1284. }
  1285. x[i] = sum / (*this)[i][i];
  1286. }
  1287. }
  1288. /*
  1289. ============
  1290. idMatX::LU_Inverse
  1291. Calculates the inverse of the matrix which is factored in-place as LU
  1292. ============
  1293. */
  1294. void idMatX::LU_Inverse( idMatX &inv, const int *index ) const {
  1295. int i, j;
  1296. idVecX x, b;
  1297. assert( numRows == numColumns );
  1298. x.SetData( numRows, VECX_ALLOCA( numRows ) );
  1299. b.SetData( numRows, VECX_ALLOCA( numRows ) );
  1300. b.Zero();
  1301. inv.SetSize( numRows, numColumns );
  1302. for ( i = 0; i < numRows; i++ ) {
  1303. b[i] = 1.0f;
  1304. LU_Solve( x, b, index );
  1305. for ( j = 0; j < numRows; j++ ) {
  1306. inv[j][i] = x[j];
  1307. }
  1308. b[i] = 0.0f;
  1309. }
  1310. }
  1311. /*
  1312. ============
  1313. idMatX::LU_UnpackFactors
  1314. Unpacks the in-place LU factorization.
  1315. ============
  1316. */
  1317. void idMatX::LU_UnpackFactors( idMatX &L, idMatX &U ) const {
  1318. int i, j;
  1319. L.Zero( numRows, numColumns );
  1320. U.Zero( numRows, numColumns );
  1321. for ( i = 0; i < numRows; i++ ) {
  1322. for ( j = 0; j < i; j++ ) {
  1323. L[i][j] = (*this)[i][j];
  1324. }
  1325. L[i][i] = 1.0f;
  1326. for ( j = i; j < numColumns; j++ ) {
  1327. U[i][j] = (*this)[i][j];
  1328. }
  1329. }
  1330. }
  1331. /*
  1332. ============
  1333. idMatX::LU_MultiplyFactors
  1334. Multiplies the factors of the in-place LU factorization to form the original matrix.
  1335. ============
  1336. */
  1337. void idMatX::LU_MultiplyFactors( idMatX &m, const int *index ) const {
  1338. int r, rp, i, j;
  1339. double sum;
  1340. m.SetSize( numRows, numColumns );
  1341. for ( r = 0; r < numRows; r++ ) {
  1342. if ( index != NULL ) {
  1343. rp = index[r];
  1344. } else {
  1345. rp = r;
  1346. }
  1347. // calculate row of matrix
  1348. for ( i = 0; i < numColumns; i++ ) {
  1349. if ( i >= r ) {
  1350. sum = (*this)[r][i];
  1351. } else {
  1352. sum = 0.0f;
  1353. }
  1354. for ( j = 0; j <= i && j < r; j++ ) {
  1355. sum += (*this)[r][j] * (*this)[j][i];
  1356. }
  1357. m[rp][i] = sum;
  1358. }
  1359. }
  1360. }
  1361. /*
  1362. ============
  1363. idMatX::QR_Factor
  1364. in-place factorization: QR
  1365. Q is an orthogonal matrix represented as a product of Householder matrices stored in the lower triangle and c.
  1366. R is a triangular matrix stored in the upper triangle except for the diagonal elements which are stored in d.
  1367. The initial matrix has to be square.
  1368. ============
  1369. */
  1370. bool idMatX::QR_Factor( idVecX &c, idVecX &d ) {
  1371. int i, j, k;
  1372. double scale, s, t, sum;
  1373. bool singular = false;
  1374. assert( numRows == numColumns );
  1375. assert( c.GetSize() >= numRows && d.GetSize() >= numRows );
  1376. for ( k = 0; k < numRows-1; k++ ) {
  1377. scale = 0.0f;
  1378. for ( i = k; i < numRows; i++ ) {
  1379. s = idMath::Fabs( (*this)[i][k] );
  1380. if ( s > scale ) {
  1381. scale = s;
  1382. }
  1383. }
  1384. if ( scale == 0.0f ) {
  1385. singular = true;
  1386. c[k] = d[k] = 0.0f;
  1387. } else {
  1388. s = 1.0f / scale;
  1389. for ( i = k; i < numRows; i++ ) {
  1390. (*this)[i][k] *= s;
  1391. }
  1392. sum = 0.0f;
  1393. for ( i = k; i < numRows; i++ ) {
  1394. s = (*this)[i][k];
  1395. sum += s * s;
  1396. }
  1397. s = idMath::Sqrt( sum );
  1398. if ( (*this)[k][k] < 0.0f ) {
  1399. s = -s;
  1400. }
  1401. (*this)[k][k] += s;
  1402. c[k] = s * (*this)[k][k];
  1403. d[k] = -scale * s;
  1404. for ( j = k+1; j < numRows; j++ ) {
  1405. sum = 0.0f;
  1406. for ( i = k; i < numRows; i++ ) {
  1407. sum += (*this)[i][k] * (*this)[i][j];
  1408. }
  1409. t = sum / c[k];
  1410. for ( i = k; i < numRows; i++ ) {
  1411. (*this)[i][j] -= t * (*this)[i][k];
  1412. }
  1413. }
  1414. }
  1415. }
  1416. d[numRows-1] = (*this)[ (numRows-1) ][ (numRows-1) ];
  1417. if ( d[numRows-1] == 0.0f ) {
  1418. singular = true;
  1419. }
  1420. return !singular;
  1421. }
  1422. /*
  1423. ============
  1424. idMatX::QR_Rotate
  1425. Performs a Jacobi rotation on the rows i and i+1 of the unpacked QR factors.
  1426. ============
  1427. */
  1428. void idMatX::QR_Rotate( idMatX &R, int i, float a, float b ) {
  1429. int j;
  1430. float f, c, s, w, y;
  1431. if ( a == 0.0f ) {
  1432. c = 0.0f;
  1433. s = ( b >= 0.0f ) ? 1.0f : -1.0f;
  1434. } else if ( idMath::Fabs( a ) > idMath::Fabs( b ) ) {
  1435. f = b / a;
  1436. c = idMath::Fabs( 1.0f / idMath::Sqrt( 1.0f + f * f ) );
  1437. if ( a < 0.0f ) {
  1438. c = -c;
  1439. }
  1440. s = f * c;
  1441. } else {
  1442. f = a / b;
  1443. s = idMath::Fabs( 1.0f / idMath::Sqrt( 1.0f + f * f ) );
  1444. if ( b < 0.0f ) {
  1445. s = -s;
  1446. }
  1447. c = f * s;
  1448. }
  1449. for ( j = i; j < numRows; j++ ) {
  1450. y = R[i][j];
  1451. w = R[i+1][j];
  1452. R[i][j] = c * y - s * w;
  1453. R[i+1][j] = s * y + c * w;
  1454. }
  1455. for ( j = 0; j < numRows; j++ ) {
  1456. y = (*this)[j][i];
  1457. w = (*this)[j][i+1];
  1458. (*this)[j][i] = c * y - s * w;
  1459. (*this)[j][i+1] = s * y + c * w;
  1460. }
  1461. }
  1462. /*
  1463. ============
  1464. idMatX::QR_UpdateRankOne
  1465. Updates the unpacked QR factorization to obtain the factors for the matrix: QR + alpha * v * w'
  1466. ============
  1467. */
  1468. bool idMatX::QR_UpdateRankOne( idMatX &R, const idVecX &v, const idVecX &w, float alpha ) {
  1469. int i, k;
  1470. float f;
  1471. idVecX u;
  1472. assert( v.GetSize() >= numColumns );
  1473. assert( w.GetSize() >= numRows );
  1474. u.SetData( v.GetSize(), VECX_ALLOCA( v.GetSize() ) );
  1475. TransposeMultiply( u, v );
  1476. u *= alpha;
  1477. for ( k = v.GetSize()-1; k > 0; k-- ) {
  1478. if ( u[k] != 0.0f ) {
  1479. break;
  1480. }
  1481. }
  1482. for ( i = k-1; i >= 0; i-- ) {
  1483. QR_Rotate( R, i, u[i], -u[i+1] );
  1484. if ( u[i] == 0.0f ) {
  1485. u[i] = idMath::Fabs( u[i+1] );
  1486. } else if ( idMath::Fabs( u[i] ) > idMath::Fabs( u[i+1] ) ) {
  1487. f = u[i+1] / u[i];
  1488. u[i] = idMath::Fabs( u[i] ) * idMath::Sqrt( 1.0f + f * f );
  1489. } else {
  1490. f = u[i] / u[i+1];
  1491. u[i] = idMath::Fabs( u[i+1] ) * idMath::Sqrt( 1.0f + f * f );
  1492. }
  1493. }
  1494. for ( i = 0; i < v.GetSize(); i++ ) {
  1495. R[0][i] += u[0] * w[i];
  1496. }
  1497. for ( i = 0; i < k; i++ ) {
  1498. QR_Rotate( R, i, -R[i][i], R[i+1][i] );
  1499. }
  1500. return true;
  1501. }
  1502. /*
  1503. ============
  1504. idMatX::QR_UpdateRowColumn
  1505. Updates the unpacked QR factorization to obtain the factors for the matrix:
  1506. [ 0 a 0 ]
  1507. QR + [ d b e ]
  1508. [ 0 c 0 ]
  1509. where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1], d = w[0,r-1], w[r] = 0.0f, e = w[r+1,numColumns-1]
  1510. ============
  1511. */
  1512. bool idMatX::QR_UpdateRowColumn( idMatX &R, const idVecX &v, const idVecX &w, int r ) {
  1513. idVecX s;
  1514. assert( v.GetSize() >= numColumns );
  1515. assert( w.GetSize() >= numRows );
  1516. assert( r >= 0 && r < numRows && r < numColumns );
  1517. assert( w[r] == 0.0f );
  1518. s.SetData( Max( numRows, numColumns ), VECX_ALLOCA( Max( numRows, numColumns ) ) );
  1519. s.Zero();
  1520. s[r] = 1.0f;
  1521. if ( !QR_UpdateRankOne( R, v, s, 1.0f ) ) {
  1522. return false;
  1523. }
  1524. if ( !QR_UpdateRankOne( R, s, w, 1.0f ) ) {
  1525. return false;
  1526. }
  1527. return true;
  1528. }
  1529. /*
  1530. ============
  1531. idMatX::QR_UpdateIncrement
  1532. Updates the unpacked QR factorization to obtain the factors for the matrix:
  1533. [ A a ]
  1534. [ c b ]
  1535. where: a = v[0,numRows-1], b = v[numRows], c = w[0,numColumns-1], w[numColumns] = 0
  1536. ============
  1537. */
  1538. bool idMatX::QR_UpdateIncrement( idMatX &R, const idVecX &v, const idVecX &w ) {
  1539. idVecX v2;
  1540. assert( numRows == numColumns );
  1541. assert( v.GetSize() >= numRows+1 );
  1542. assert( w.GetSize() >= numColumns+1 );
  1543. ChangeSize( numRows+1, numColumns+1, true );
  1544. (*this)[numRows-1][numRows-1] = 1.0f;
  1545. R.ChangeSize( R.numRows+1, R.numColumns+1, true );
  1546. R[R.numRows-1][R.numRows-1] = 1.0f;
  1547. v2.SetData( numRows, VECX_ALLOCA( numRows ) );
  1548. v2 = v;
  1549. v2[numRows-1] -= 1.0f;
  1550. return QR_UpdateRowColumn( R, v2, w, numRows-1 );
  1551. }
  1552. /*
  1553. ============
  1554. idMatX::QR_UpdateDecrement
  1555. Updates the unpacked QR factorization to obtain the factors for the matrix with row r and column r removed.
  1556. v and w should store the column and row of the original matrix respectively.
  1557. ============
  1558. */
  1559. bool idMatX::QR_UpdateDecrement( idMatX &R, const idVecX &v, const idVecX &w, int r ) {
  1560. idVecX v1, w1;
  1561. assert( numRows == numColumns );
  1562. assert( v.GetSize() >= numRows );
  1563. assert( w.GetSize() >= numColumns );
  1564. assert( r >= 0 && r < numRows && r < numColumns );
  1565. v1.SetData( numRows, VECX_ALLOCA( numRows ) );
  1566. w1.SetData( numRows, VECX_ALLOCA( numRows ) );
  1567. // update the row and column to identity
  1568. v1 = -v;
  1569. w1 = -w;
  1570. v1[r] += 1.0f;
  1571. w1[r] = 0.0f;
  1572. if ( !QR_UpdateRowColumn( R, v1, w1, r ) ) {
  1573. return false;
  1574. }
  1575. // physically remove the row and column
  1576. Update_Decrement( r );
  1577. R.Update_Decrement( r );
  1578. return true;
  1579. }
  1580. /*
  1581. ============
  1582. idMatX::QR_Solve
  1583. Solve Ax = b with A factored in-place as: QR
  1584. ============
  1585. */
  1586. void idMatX::QR_Solve( idVecX &x, const idVecX &b, const idVecX &c, const idVecX &d ) const {
  1587. int i, j;
  1588. double sum, t;
  1589. assert( numRows == numColumns );
  1590. assert( x.GetSize() >= numRows && b.GetSize() >= numRows );
  1591. assert( c.GetSize() >= numRows && d.GetSize() >= numRows );
  1592. for ( i = 0; i < numRows; i++ ) {
  1593. x[i] = b[i];
  1594. }
  1595. // multiply b with transpose of Q
  1596. for ( i = 0; i < numRows-1; i++ ) {
  1597. sum = 0.0f;
  1598. for ( j = i; j < numRows; j++ ) {
  1599. sum += (*this)[j][i] * x[j];
  1600. }
  1601. t = sum / c[i];
  1602. for ( j = i; j < numRows; j++ ) {
  1603. x[j] -= t * (*this)[j][i];
  1604. }
  1605. }
  1606. // backsubstitution with R
  1607. for ( i = numRows-1; i >= 0; i-- ) {
  1608. sum = x[i];
  1609. for ( j = i + 1; j < numRows; j++ ) {
  1610. sum -= (*this)[i][j] * x[j];
  1611. }
  1612. x[i] = sum / d[i];
  1613. }
  1614. }
  1615. /*
  1616. ============
  1617. idMatX::QR_Solve
  1618. Solve Ax = b with A factored as: QR
  1619. ============
  1620. */
  1621. void idMatX::QR_Solve( idVecX &x, const idVecX &b, const idMatX &R ) const {
  1622. int i, j;
  1623. double sum;
  1624. assert( numRows == numColumns );
  1625. // multiply b with transpose of Q
  1626. TransposeMultiply( x, b );
  1627. // backsubstitution with R
  1628. for ( i = numRows-1; i >= 0; i-- ) {
  1629. sum = x[i];
  1630. for ( j = i + 1; j < numRows; j++ ) {
  1631. sum -= R[i][j] * x[j];
  1632. }
  1633. x[i] = sum / R[i][i];
  1634. }
  1635. }
  1636. /*
  1637. ============
  1638. idMatX::QR_Inverse
  1639. Calculates the inverse of the matrix which is factored in-place as: QR
  1640. ============
  1641. */
  1642. void idMatX::QR_Inverse( idMatX &inv, const idVecX &c, const idVecX &d ) const {
  1643. int i, j;
  1644. idVecX x, b;
  1645. assert( numRows == numColumns );
  1646. x.SetData( numRows, VECX_ALLOCA( numRows ) );
  1647. b.SetData( numRows, VECX_ALLOCA( numRows ) );
  1648. b.Zero();
  1649. inv.SetSize( numRows, numColumns );
  1650. for ( i = 0; i < numRows; i++ ) {
  1651. b[i] = 1.0f;
  1652. QR_Solve( x, b, c, d );
  1653. for ( j = 0; j < numRows; j++ ) {
  1654. inv[j][i] = x[j];
  1655. }
  1656. b[i] = 0.0f;
  1657. }
  1658. }
  1659. /*
  1660. ============
  1661. idMatX::QR_UnpackFactors
  1662. Unpacks the in-place QR factorization.
  1663. ============
  1664. */
  1665. void idMatX::QR_UnpackFactors( idMatX &Q, idMatX &R, const idVecX &c, const idVecX &d ) const {
  1666. int i, j, k;
  1667. double sum;
  1668. Q.Identity( numRows, numColumns );
  1669. for ( i = 0; i < numColumns-1; i++ ) {
  1670. if ( c[i] == 0.0f ) {
  1671. continue;
  1672. }
  1673. for ( j = 0; j < numRows; j++ ) {
  1674. sum = 0.0f;
  1675. for ( k = i; k < numColumns; k++ ) {
  1676. sum += (*this)[k][i] * Q[j][k];
  1677. }
  1678. sum /= c[i];
  1679. for ( k = i; k < numColumns; k++ ) {
  1680. Q[j][k] -= sum * (*this)[k][i];
  1681. }
  1682. }
  1683. }
  1684. R.Zero( numRows, numColumns );
  1685. for ( i = 0; i < numRows; i++ ) {
  1686. R[i][i] = d[i];
  1687. for ( j = i+1; j < numColumns; j++ ) {
  1688. R[i][j] = (*this)[i][j];
  1689. }
  1690. }
  1691. }
  1692. /*
  1693. ============
  1694. idMatX::QR_MultiplyFactors
  1695. Multiplies the factors of the in-place QR factorization to form the original matrix.
  1696. ============
  1697. */
  1698. void idMatX::QR_MultiplyFactors( idMatX &m, const idVecX &c, const idVecX &d ) const {
  1699. int i, j, k;
  1700. double sum;
  1701. idMatX Q;
  1702. Q.Identity( numRows, numColumns );
  1703. for ( i = 0; i < numColumns-1; i++ ) {
  1704. if ( c[i] == 0.0f ) {
  1705. continue;
  1706. }
  1707. for ( j = 0; j < numRows; j++ ) {
  1708. sum = 0.0f;
  1709. for ( k = i; k < numColumns; k++ ) {
  1710. sum += (*this)[k][i] * Q[j][k];
  1711. }
  1712. sum /= c[i];
  1713. for ( k = i; k < numColumns; k++ ) {
  1714. Q[j][k] -= sum * (*this)[k][i];
  1715. }
  1716. }
  1717. }
  1718. for ( i = 0; i < numRows; i++ ) {
  1719. for ( j = 0; j < numColumns; j++ ) {
  1720. sum = Q[i][j] * d[i];
  1721. for ( k = 0; k < i; k++ ) {
  1722. sum += Q[i][k] * (*this)[j][k];
  1723. }
  1724. m[i][j] = sum;
  1725. }
  1726. }
  1727. }
  1728. /*
  1729. ============
  1730. idMatX::Pythag
  1731. Computes (a^2 + b^2)^1/2 without underflow or overflow.
  1732. ============
  1733. */
  1734. float idMatX::Pythag( float a, float b ) const {
  1735. double at, bt, ct;
  1736. at = idMath::Fabs( a );
  1737. bt = idMath::Fabs( b );
  1738. if ( at > bt ) {
  1739. ct = bt / at;
  1740. return at * idMath::Sqrt( 1.0f + ct * ct );
  1741. } else {
  1742. if ( bt ) {
  1743. ct = at / bt;
  1744. return bt * idMath::Sqrt( 1.0f + ct * ct );
  1745. } else {
  1746. return 0.0f;
  1747. }
  1748. }
  1749. }
  1750. /*
  1751. ============
  1752. idMatX::SVD_BiDiag
  1753. ============
  1754. */
  1755. void idMatX::SVD_BiDiag( idVecX &w, idVecX &rv1, float &anorm ) {
  1756. int i, j, k, l;
  1757. double f, h, r, g, s, scale;
  1758. anorm = 0.0f;
  1759. g = s = scale = 0.0f;
  1760. for ( i = 0; i < numColumns; i++ ) {
  1761. l = i + 1;
  1762. rv1[i] = scale * g;
  1763. g = s = scale = 0.0f;
  1764. if ( i < numRows ) {
  1765. for ( k = i; k < numRows; k++ ) {
  1766. scale += idMath::Fabs( (*this)[k][i] );
  1767. }
  1768. if ( scale ) {
  1769. for ( k = i; k < numRows; k++ ) {
  1770. (*this)[k][i] /= scale;
  1771. s += (*this)[k][i] * (*this)[k][i];
  1772. }
  1773. f = (*this)[i][i];
  1774. g = idMath::Sqrt( s );
  1775. if ( f >= 0.0f ) {
  1776. g = -g;
  1777. }
  1778. h = f * g - s;
  1779. (*this)[i][i] = f - g;
  1780. if ( i != (numColumns-1) ) {
  1781. for ( j = l; j < numColumns; j++ ) {
  1782. for ( s = 0.0f, k = i; k < numRows; k++ ) {
  1783. s += (*this)[k][i] * (*this)[k][j];
  1784. }
  1785. f = s / h;
  1786. for ( k = i; k < numRows; k++ ) {
  1787. (*this)[k][j] += f * (*this)[k][i];
  1788. }
  1789. }
  1790. }
  1791. for ( k = i; k < numRows; k++ ) {
  1792. (*this)[k][i] *= scale;
  1793. }
  1794. }
  1795. }
  1796. w[i] = scale * g;
  1797. g = s = scale = 0.0f;
  1798. if ( i < numRows && i != (numColumns-1) ) {
  1799. for ( k = l; k < numColumns; k++ ) {
  1800. scale += idMath::Fabs( (*this)[i][k] );
  1801. }
  1802. if ( scale ) {
  1803. for ( k = l; k < numColumns; k++ ) {
  1804. (*this)[i][k] /= scale;
  1805. s += (*this)[i][k] * (*this)[i][k];
  1806. }
  1807. f = (*this)[i][l];
  1808. g = idMath::Sqrt( s );
  1809. if ( f >= 0.0f ) {
  1810. g = -g;
  1811. }
  1812. h = 1.0f / ( f * g - s );
  1813. (*this)[i][l] = f - g;
  1814. for ( k = l; k < numColumns; k++ ) {
  1815. rv1[k] = (*this)[i][k] * h;
  1816. }
  1817. if ( i != (numRows-1) ) {
  1818. for ( j = l; j < numRows; j++ ) {
  1819. for ( s = 0.0f, k = l; k < numColumns; k++ ) {
  1820. s += (*this)[j][k] * (*this)[i][k];
  1821. }
  1822. for ( k = l; k < numColumns; k++ ) {
  1823. (*this)[j][k] += s * rv1[k];
  1824. }
  1825. }
  1826. }
  1827. for ( k = l; k < numColumns; k++ ) {
  1828. (*this)[i][k] *= scale;
  1829. }
  1830. }
  1831. }
  1832. r = idMath::Fabs( w[i] ) + idMath::Fabs( rv1[i] );
  1833. if ( r > anorm ) {
  1834. anorm = r;
  1835. }
  1836. }
  1837. }
  1838. /*
  1839. ============
  1840. idMatX::SVD_InitialWV
  1841. ============
  1842. */
  1843. void idMatX::SVD_InitialWV( idVecX &w, idMatX &V, idVecX &rv1 ) {
  1844. int i, j, k, l;
  1845. double f, g, s;
  1846. g = 0.0f;
  1847. for ( i = (numColumns-1); i >= 0; i-- ) {
  1848. l = i + 1;
  1849. if ( i < ( numColumns - 1 ) ) {
  1850. if ( g ) {
  1851. for ( j = l; j < numColumns; j++ ) {
  1852. V[j][i] = ((*this)[i][j] / (*this)[i][l]) / g;
  1853. }
  1854. // double division to reduce underflow
  1855. for ( j = l; j < numColumns; j++ ) {
  1856. for ( s = 0.0f, k = l; k < numColumns; k++ ) {
  1857. s += (*this)[i][k] * V[k][j];
  1858. }
  1859. for ( k = l; k < numColumns; k++ ) {
  1860. V[k][j] += s * V[k][i];
  1861. }
  1862. }
  1863. }
  1864. for ( j = l; j < numColumns; j++ ) {
  1865. V[i][j] = V[j][i] = 0.0f;
  1866. }
  1867. }
  1868. V[i][i] = 1.0f;
  1869. g = rv1[i];
  1870. }
  1871. for ( i = numColumns - 1 ; i >= 0; i-- ) {
  1872. l = i + 1;
  1873. g = w[i];
  1874. if ( i < (numColumns-1) ) {
  1875. for ( j = l; j < numColumns; j++ ) {
  1876. (*this)[i][j] = 0.0f;
  1877. }
  1878. }
  1879. if ( g ) {
  1880. g = 1.0f / g;
  1881. if ( i != (numColumns-1) ) {
  1882. for ( j = l; j < numColumns; j++ ) {
  1883. for ( s = 0.0f, k = l; k < numRows; k++ ) {
  1884. s += (*this)[k][i] * (*this)[k][j];
  1885. }
  1886. f = (s / (*this)[i][i]) * g;
  1887. for ( k = i; k < numRows; k++ ) {
  1888. (*this)[k][j] += f * (*this)[k][i];
  1889. }
  1890. }
  1891. }
  1892. for ( j = i; j < numRows; j++ ) {
  1893. (*this)[j][i] *= g;
  1894. }
  1895. }
  1896. else {
  1897. for ( j = i; j < numRows; j++ ) {
  1898. (*this)[j][i] = 0.0f;
  1899. }
  1900. }
  1901. (*this)[i][i] += 1.0f;
  1902. }
  1903. }
  1904. /*
  1905. ============
  1906. idMatX::SVD_Factor
  1907. in-place factorization: U * Diag(w) * V.Transpose()
  1908. known as the Singular Value Decomposition.
  1909. U is a column-orthogonal matrix which overwrites the original matrix.
  1910. w is a diagonal matrix with all elements >= 0 which are the singular values.
  1911. V is the transpose of an orthogonal matrix.
  1912. ============
  1913. */
  1914. bool idMatX::SVD_Factor( idVecX &w, idMatX &V ) {
  1915. int flag, i, its, j, jj, k, l, nm;
  1916. double c, f, h, s, x, y, z, r, g = 0.0f;
  1917. float anorm = 0.0f;
  1918. idVecX rv1;
  1919. if ( numRows < numColumns ) {
  1920. return false;
  1921. }
  1922. rv1.SetData( numColumns, VECX_ALLOCA( numColumns ) );
  1923. rv1.Zero();
  1924. w.Zero( numColumns );
  1925. V.Zero( numColumns, numColumns );
  1926. SVD_BiDiag( w, rv1, anorm );
  1927. SVD_InitialWV( w, V, rv1 );
  1928. for ( k = numColumns - 1; k >= 0; k-- ) {
  1929. for ( its = 1; its <= 30; its++ ) {
  1930. flag = 1;
  1931. nm = 0;
  1932. for ( l = k; l >= 0; l-- ) {
  1933. nm = l - 1;
  1934. if ( ( idMath::Fabs( rv1[l] ) + anorm ) == anorm /* idMath::Fabs( rv1[l] ) < idMath::FLT_EPSILON */ ) {
  1935. flag = 0;
  1936. break;
  1937. }
  1938. if ( ( idMath::Fabs( w[nm] ) + anorm ) == anorm /* idMath::Fabs( w[nm] ) < idMath::FLT_EPSILON */ ) {
  1939. break;
  1940. }
  1941. }
  1942. if ( flag ) {
  1943. c = 0.0f;
  1944. s = 1.0f;
  1945. for ( i = l; i <= k; i++ ) {
  1946. f = s * rv1[i];
  1947. if ( ( idMath::Fabs( f ) + anorm ) != anorm /* idMath::Fabs( f ) > idMath::FLT_EPSILON */ ) {
  1948. g = w[i];
  1949. h = Pythag( f, g );
  1950. w[i] = h;
  1951. h = 1.0f / h;
  1952. c = g * h;
  1953. s = -f * h;
  1954. for ( j = 0; j < numRows; j++ ) {
  1955. y = (*this)[j][nm];
  1956. z = (*this)[j][i];
  1957. (*this)[j][nm] = y * c + z * s;
  1958. (*this)[j][i] = z * c - y * s;
  1959. }
  1960. }
  1961. }
  1962. }
  1963. z = w[k];
  1964. if ( l == k ) {
  1965. if ( z < 0.0f ) {
  1966. w[k] = -z;
  1967. for ( j = 0; j < numColumns; j++ ) {
  1968. V[j][k] = -V[j][k];
  1969. }
  1970. }
  1971. break;
  1972. }
  1973. if ( its == 30 ) {
  1974. return false; // no convergence
  1975. }
  1976. x = w[l];
  1977. nm = k - 1;
  1978. y = w[nm];
  1979. g = rv1[nm];
  1980. h = rv1[k];
  1981. f = ( ( y - z ) * ( y + z ) + ( g - h ) * ( g + h ) ) / ( 2.0f * h * y );
  1982. g = Pythag( f, 1.0f );
  1983. r = ( f >= 0.0f ? g : - g );
  1984. f= ( ( x - z ) * ( x + z ) + h * ( ( y / ( f + r ) ) - h ) ) / x;
  1985. c = s = 1.0f;
  1986. for ( j = l; j <= nm; j++ ) {
  1987. i = j + 1;
  1988. g = rv1[i];
  1989. y = w[i];
  1990. h = s * g;
  1991. g = c * g;
  1992. z = Pythag( f, h );
  1993. rv1[j] = z;
  1994. c = f / z;
  1995. s = h / z;
  1996. f = x * c + g * s;
  1997. g = g * c - x * s;
  1998. h = y * s;
  1999. y = y * c;
  2000. for ( jj = 0; jj < numColumns; jj++ ) {
  2001. x = V[jj][j];
  2002. z = V[jj][i];
  2003. V[jj][j] = x * c + z * s;
  2004. V[jj][i] = z * c - x * s;
  2005. }
  2006. z = Pythag( f, h );
  2007. w[j] = z;
  2008. if ( z ) {
  2009. z = 1.0f / z;
  2010. c = f * z;
  2011. s = h * z;
  2012. }
  2013. f = ( c * g ) + ( s * y );
  2014. x = ( c * y ) - ( s * g );
  2015. for ( jj = 0; jj < numRows; jj++ ) {
  2016. y = (*this)[jj][j];
  2017. z = (*this)[jj][i];
  2018. (*this)[jj][j] = y * c + z * s;
  2019. (*this)[jj][i] = z * c - y * s;
  2020. }
  2021. }
  2022. rv1[l] = 0.0f;
  2023. rv1[k] = f;
  2024. w[k] = x;
  2025. }
  2026. }
  2027. return true;
  2028. }
  2029. /*
  2030. ============
  2031. idMatX::SVD_Solve
  2032. Solve Ax = b with A factored as: U * Diag(w) * V.Transpose()
  2033. ============
  2034. */
  2035. void idMatX::SVD_Solve( idVecX &x, const idVecX &b, const idVecX &w, const idMatX &V ) const {
  2036. int i, j;
  2037. double sum;
  2038. idVecX tmp;
  2039. assert( x.GetSize() >= numColumns );
  2040. assert( b.GetSize() >= numColumns );
  2041. assert( w.GetSize() == numColumns );
  2042. assert( V.GetNumRows() == numColumns && V.GetNumColumns() == numColumns );
  2043. tmp.SetData( numColumns, VECX_ALLOCA( numColumns ) );
  2044. for ( i = 0; i < numColumns; i++ ) {
  2045. sum = 0.0f;
  2046. if ( w[i] >= idMath::FLT_EPSILON ) {
  2047. for ( j = 0; j < numRows; j++ ) {
  2048. sum += (*this)[j][i] * b[j];
  2049. }
  2050. sum /= w[i];
  2051. }
  2052. tmp[i] = sum;
  2053. }
  2054. for ( i = 0; i < numColumns; i++ ) {
  2055. sum = 0.0f;
  2056. for ( j = 0; j < numColumns; j++ ) {
  2057. sum += V[i][j] * tmp[j];
  2058. }
  2059. x[i] = sum;
  2060. }
  2061. }
  2062. /*
  2063. ============
  2064. idMatX::SVD_Inverse
  2065. Calculates the inverse of the matrix which is factored in-place as: U * Diag(w) * V.Transpose()
  2066. ============
  2067. */
  2068. void idMatX::SVD_Inverse( idMatX &inv, const idVecX &w, const idMatX &V ) const {
  2069. int i, j, k;
  2070. double wi, sum;
  2071. idMatX V2;
  2072. assert( numRows == numColumns );
  2073. V2 = V;
  2074. // V * [diag(1/w[i])]
  2075. for ( i = 0; i < numRows; i++ ) {
  2076. wi = w[i];
  2077. wi = ( wi < idMath::FLT_EPSILON ) ? 0.0f : 1.0f / wi;
  2078. for ( j = 0; j < numColumns; j++ ) {
  2079. V2[j][i] *= wi;
  2080. }
  2081. }
  2082. // V * [diag(1/w[i])] * Ut
  2083. for ( i = 0; i < numRows; i++ ) {
  2084. for ( j = 0; j < numColumns; j++ ) {
  2085. sum = V2[i][0] * (*this)[j][0];
  2086. for ( k = 1; k < numColumns; k++ ) {
  2087. sum += V2[i][k] * (*this)[j][k];
  2088. }
  2089. inv[i][j] = sum;
  2090. }
  2091. }
  2092. }
  2093. /*
  2094. ============
  2095. idMatX::SVD_MultiplyFactors
  2096. Multiplies the factors of the in-place SVD factorization to form the original matrix.
  2097. ============
  2098. */
  2099. void idMatX::SVD_MultiplyFactors( idMatX &m, const idVecX &w, const idMatX &V ) const {
  2100. int r, i, j;
  2101. double sum;
  2102. m.SetSize( numRows, V.GetNumRows() );
  2103. for ( r = 0; r < numRows; r++ ) {
  2104. // calculate row of matrix
  2105. if ( w[r] >= idMath::FLT_EPSILON ) {
  2106. for ( i = 0; i < V.GetNumRows(); i++ ) {
  2107. sum = 0.0f;
  2108. for ( j = 0; j < numColumns; j++ ) {
  2109. sum += (*this)[r][j] * V[i][j];
  2110. }
  2111. m[r][i] = sum * w[r];
  2112. }
  2113. } else {
  2114. for ( i = 0; i < V.GetNumRows(); i++ ) {
  2115. m[r][i] = 0.0f;
  2116. }
  2117. }
  2118. }
  2119. }
  2120. /*
  2121. ============
  2122. idMatX::Cholesky_Factor
  2123. in-place Cholesky factorization: LL'
  2124. L is a triangular matrix stored in the lower triangle.
  2125. The upper triangle is not cleared.
  2126. The initial matrix has to be symmetric positive definite.
  2127. ============
  2128. */
  2129. bool idMatX::Cholesky_Factor() {
  2130. int i, j, k;
  2131. float *invSqrt;
  2132. double sum;
  2133. assert( numRows == numColumns );
  2134. invSqrt = (float *) _alloca16( numRows * sizeof( float ) );
  2135. for ( i = 0; i < numRows; i++ ) {
  2136. for ( j = 0; j < i; j++ ) {
  2137. sum = (*this)[i][j];
  2138. for ( k = 0; k < j; k++ ) {
  2139. sum -= (*this)[i][k] * (*this)[j][k];
  2140. }
  2141. (*this)[i][j] = sum * invSqrt[j];
  2142. }
  2143. sum = (*this)[i][i];
  2144. for ( k = 0; k < i; k++ ) {
  2145. sum -= (*this)[i][k] * (*this)[i][k];
  2146. }
  2147. if ( sum <= 0.0f ) {
  2148. return false;
  2149. }
  2150. invSqrt[i] = idMath::InvSqrt( sum );
  2151. (*this)[i][i] = invSqrt[i] * sum;
  2152. }
  2153. return true;
  2154. }
  2155. /*
  2156. ============
  2157. idMatX::Cholesky_UpdateRankOne
  2158. Updates the in-place Cholesky factorization to obtain the factors for the matrix: LL' + alpha * v * v'
  2159. If offset > 0 only the lower right corner starting at (offset, offset) is updated.
  2160. ============
  2161. */
  2162. bool idMatX::Cholesky_UpdateRankOne( const idVecX &v, float alpha, int offset ) {
  2163. int i, j;
  2164. float *y;
  2165. double diag, invDiag, diagSqr, newDiag, newDiagSqr, beta, p, d;
  2166. assert( numRows == numColumns );
  2167. assert( v.GetSize() >= numRows );
  2168. assert( offset >= 0 && offset < numRows );
  2169. y = (float *) _alloca16( v.GetSize() * sizeof( float ) );
  2170. memcpy( y, v.ToFloatPtr(), v.GetSize() * sizeof( float ) );
  2171. for ( i = offset; i < numColumns; i++ ) {
  2172. p = y[i];
  2173. diag = (*this)[i][i];
  2174. invDiag = 1.0f / diag;
  2175. diagSqr = diag * diag;
  2176. newDiagSqr = diagSqr + alpha * p * p;
  2177. if ( newDiagSqr <= 0.0f ) {
  2178. return false;
  2179. }
  2180. (*this)[i][i] = newDiag = idMath::Sqrt( newDiagSqr );
  2181. alpha /= newDiagSqr;
  2182. beta = p * alpha;
  2183. alpha *= diagSqr;
  2184. for ( j = i+1; j < numRows; j++ ) {
  2185. d = (*this)[j][i] * invDiag;
  2186. y[j] -= p * d;
  2187. d += beta * y[j];
  2188. (*this)[j][i] = d * newDiag;
  2189. }
  2190. }
  2191. return true;
  2192. }
  2193. /*
  2194. ============
  2195. idMatX::Cholesky_UpdateRowColumn
  2196. Updates the in-place Cholesky factorization to obtain the factors for the matrix:
  2197. [ 0 a 0 ]
  2198. LL' + [ a b c ]
  2199. [ 0 c 0 ]
  2200. where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1]
  2201. ============
  2202. */
  2203. bool idMatX::Cholesky_UpdateRowColumn( const idVecX &v, int r ) {
  2204. int i, j;
  2205. double sum;
  2206. float *original, *y;
  2207. idVecX addSub;
  2208. assert( numRows == numColumns );
  2209. assert( v.GetSize() >= numRows );
  2210. assert( r >= 0 && r < numRows );
  2211. addSub.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
  2212. if ( r == 0 ) {
  2213. if ( numColumns == 1 ) {
  2214. double v0 = v[0];
  2215. sum = (*this)[0][0];
  2216. sum = sum * sum;
  2217. sum = sum + v0;
  2218. if ( sum <= 0.0f ) {
  2219. return false;
  2220. }
  2221. (*this)[0][0] = idMath::Sqrt( sum );
  2222. return true;
  2223. }
  2224. for ( i = 0; i < numColumns; i++ ) {
  2225. addSub[i] = v[i];
  2226. }
  2227. } else {
  2228. original = (float *) _alloca16( numColumns * sizeof( float ) );
  2229. y = (float *) _alloca16( numColumns * sizeof( float ) );
  2230. // calculate original row/column of matrix
  2231. for ( i = 0; i < numRows; i++ ) {
  2232. sum = 0.0f;
  2233. for ( j = 0; j <= i; j++ ) {
  2234. sum += (*this)[r][j] * (*this)[i][j];
  2235. }
  2236. original[i] = sum;
  2237. }
  2238. // solve for y in L * y = original + v
  2239. for ( i = 0; i < r; i++ ) {
  2240. sum = original[i] + v[i];
  2241. for ( j = 0; j < i; j++ ) {
  2242. sum -= (*this)[r][j] * (*this)[i][j];
  2243. }
  2244. (*this)[r][i] = sum / (*this)[i][i];
  2245. }
  2246. // if the last row/column of the matrix is updated
  2247. if ( r == numColumns - 1 ) {
  2248. // only calculate new diagonal
  2249. sum = original[r] + v[r];
  2250. for ( j = 0; j < r; j++) {
  2251. sum -= (*this)[r][j] * (*this)[r][j];
  2252. }
  2253. if ( sum <= 0.0f ) {
  2254. return false;
  2255. }
  2256. (*this)[r][r] = idMath::Sqrt( sum );
  2257. return true;
  2258. }
  2259. // calculate the row/column to be added to the lower right sub matrix starting at (r, r)
  2260. for ( i = r; i < numColumns; i++ ) {
  2261. sum = 0.0f;
  2262. for ( j = 0; j <= r; j++ ) {
  2263. sum += (*this)[r][j] * (*this)[i][j];
  2264. }
  2265. addSub[i] = v[i] - ( sum - original[i] );
  2266. }
  2267. }
  2268. // add row/column to the lower right sub matrix starting at (r, r)
  2269. #if 0
  2270. idVecX v1, v2;
  2271. double d;
  2272. v1.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
  2273. v2.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
  2274. d = idMath::SQRT_1OVER2;
  2275. v1[r] = ( 0.5f * addSub[r] + 1.0f ) * d;
  2276. v2[r] = ( 0.5f * addSub[r] - 1.0f ) * d;
  2277. for ( i = r+1; i < numColumns; i++ ) {
  2278. v1[i] = v2[i] = addSub[i] * d;
  2279. }
  2280. // update
  2281. if ( !Cholesky_UpdateRankOne( v1, 1.0f, r ) ) {
  2282. return false;
  2283. }
  2284. // downdate
  2285. if ( !Cholesky_UpdateRankOne( v2, -1.0f, r ) ) {
  2286. return false;
  2287. }
  2288. #else
  2289. float *v1, *v2;
  2290. double diag, invDiag, diagSqr, newDiag, newDiagSqr;
  2291. double alpha1, alpha2, beta1, beta2, p1, p2, d;
  2292. v1 = (float *) _alloca16( numColumns * sizeof( float ) );
  2293. v2 = (float *) _alloca16( numColumns * sizeof( float ) );
  2294. d = idMath::SQRT_1OVER2;
  2295. v1[r] = ( 0.5f * addSub[r] + 1.0f ) * d;
  2296. v2[r] = ( 0.5f * addSub[r] - 1.0f ) * d;
  2297. for ( i = r+1; i < numColumns; i++ ) {
  2298. v1[i] = v2[i] = addSub[i] * d;
  2299. }
  2300. alpha1 = 1.0f;
  2301. alpha2 = -1.0f;
  2302. // simultaneous update/downdate of the sub matrix starting at (r, r)
  2303. for ( i = r; i < numColumns; i++ ) {
  2304. p1 = v1[i];
  2305. diag = (*this)[i][i];
  2306. invDiag = 1.0f / diag;
  2307. diagSqr = diag * diag;
  2308. newDiagSqr = diagSqr + alpha1 * p1 * p1;
  2309. if ( newDiagSqr <= 0.0f ) {
  2310. return false;
  2311. }
  2312. alpha1 /= newDiagSqr;
  2313. beta1 = p1 * alpha1;
  2314. alpha1 *= diagSqr;
  2315. p2 = v2[i];
  2316. diagSqr = newDiagSqr;
  2317. newDiagSqr = diagSqr + alpha2 * p2 * p2;
  2318. if ( newDiagSqr <= 0.0f ) {
  2319. return false;
  2320. }
  2321. (*this)[i][i] = newDiag = idMath::Sqrt( newDiagSqr );
  2322. alpha2 /= newDiagSqr;
  2323. beta2 = p2 * alpha2;
  2324. alpha2 *= diagSqr;
  2325. for ( j = i+1; j < numRows; j++ ) {
  2326. d = (*this)[j][i] * invDiag;
  2327. v1[j] -= p1 * d;
  2328. d += beta1 * v1[j];
  2329. v2[j] -= p2 * d;
  2330. d += beta2 * v2[j];
  2331. (*this)[j][i] = d * newDiag;
  2332. }
  2333. }
  2334. #endif
  2335. return true;
  2336. }
  2337. /*
  2338. ============
  2339. idMatX::Cholesky_UpdateIncrement
  2340. Updates the in-place Cholesky factorization to obtain the factors for the matrix:
  2341. [ A a ]
  2342. [ a b ]
  2343. where: a = v[0,numRows-1], b = v[numRows]
  2344. ============
  2345. */
  2346. bool idMatX::Cholesky_UpdateIncrement( const idVecX &v ) {
  2347. int i, j;
  2348. float *x;
  2349. double sum;
  2350. assert( numRows == numColumns );
  2351. assert( v.GetSize() >= numRows+1 );
  2352. ChangeSize( numRows+1, numColumns+1, false );
  2353. x = (float *) _alloca16( numRows * sizeof( float ) );
  2354. // solve for x in L * x = v
  2355. for ( i = 0; i < numRows - 1; i++ ) {
  2356. sum = v[i];
  2357. for ( j = 0; j < i; j++ ) {
  2358. sum -= (*this)[i][j] * x[j];
  2359. }
  2360. x[i] = sum / (*this)[i][i];
  2361. }
  2362. // calculate new row of L and calculate the square of the diagonal entry
  2363. sum = v[numRows - 1];
  2364. for ( i = 0; i < numRows - 1; i++ ) {
  2365. (*this)[numRows - 1][i] = x[i];
  2366. sum -= x[i] * x[i];
  2367. }
  2368. if ( sum <= 0.0f ) {
  2369. return false;
  2370. }
  2371. // store the diagonal entry
  2372. (*this)[numRows - 1][numRows - 1] = idMath::Sqrt( sum );
  2373. return true;
  2374. }
  2375. /*
  2376. ============
  2377. idMatX::Cholesky_UpdateDecrement
  2378. Updates the in-place Cholesky factorization to obtain the factors for the matrix with row r and column r removed.
  2379. v should store the row of the original matrix.
  2380. ============
  2381. */
  2382. bool idMatX::Cholesky_UpdateDecrement( const idVecX &v, int r ) {
  2383. idVecX v1;
  2384. assert( numRows == numColumns );
  2385. assert( v.GetSize() >= numRows );
  2386. assert( r >= 0 && r < numRows );
  2387. v1.SetData( numRows, VECX_ALLOCA( numRows ) );
  2388. // update the row and column to identity
  2389. v1 = -v;
  2390. v1[r] += 1.0f;
  2391. // NOTE: msvc compiler bug: the this pointer stored in edi is expected to stay
  2392. // untouched when calling Cholesky_UpdateRowColumn in the if statement
  2393. #if 0
  2394. if ( !Cholesky_UpdateRowColumn( v1, r ) ) {
  2395. #else
  2396. bool ret = Cholesky_UpdateRowColumn( v1, r );
  2397. if ( !ret ) {
  2398. #endif
  2399. return false;
  2400. }
  2401. // physically remove the row and column
  2402. Update_Decrement( r );
  2403. return true;
  2404. }
  2405. /*
  2406. ============
  2407. idMatX::Cholesky_Solve
  2408. Solve Ax = b with A factored in-place as: LL'
  2409. ============
  2410. */
  2411. void idMatX::Cholesky_Solve( idVecX &x, const idVecX &b ) const {
  2412. int i, j;
  2413. double sum;
  2414. assert( numRows == numColumns );
  2415. assert( x.GetSize() >= numRows && b.GetSize() >= numRows );
  2416. // solve L
  2417. for ( i = 0; i < numRows; i++ ) {
  2418. sum = b[i];
  2419. for ( j = 0; j < i; j++ ) {
  2420. sum -= (*this)[i][j] * x[j];
  2421. }
  2422. x[i] = sum / (*this)[i][i];
  2423. }
  2424. // solve Lt
  2425. for ( i = numRows - 1; i >= 0; i-- ) {
  2426. sum = x[i];
  2427. for ( j = i + 1; j < numRows; j++ ) {
  2428. sum -= (*this)[j][i] * x[j];
  2429. }
  2430. x[i] = sum / (*this)[i][i];
  2431. }
  2432. }
  2433. /*
  2434. ============
  2435. idMatX::Cholesky_Inverse
  2436. Calculates the inverse of the matrix which is factored in-place as: LL'
  2437. ============
  2438. */
  2439. void idMatX::Cholesky_Inverse( idMatX &inv ) const {
  2440. int i, j;
  2441. idVecX x, b;
  2442. assert( numRows == numColumns );
  2443. x.SetData( numRows, VECX_ALLOCA( numRows ) );
  2444. b.SetData( numRows, VECX_ALLOCA( numRows ) );
  2445. b.Zero();
  2446. inv.SetSize( numRows, numColumns );
  2447. for ( i = 0; i < numRows; i++ ) {
  2448. b[i] = 1.0f;
  2449. Cholesky_Solve( x, b );
  2450. for ( j = 0; j < numRows; j++ ) {
  2451. inv[j][i] = x[j];
  2452. }
  2453. b[i] = 0.0f;
  2454. }
  2455. }
  2456. /*
  2457. ============
  2458. idMatX::Cholesky_MultiplyFactors
  2459. Multiplies the factors of the in-place Cholesky factorization to form the original matrix.
  2460. ============
  2461. */
  2462. void idMatX::Cholesky_MultiplyFactors( idMatX &m ) const {
  2463. int r, i, j;
  2464. double sum;
  2465. m.SetSize( numRows, numColumns );
  2466. for ( r = 0; r < numRows; r++ ) {
  2467. // calculate row of matrix
  2468. for ( i = 0; i < numRows; i++ ) {
  2469. sum = 0.0f;
  2470. for ( j = 0; j <= i && j <= r; j++ ) {
  2471. sum += (*this)[r][j] * (*this)[i][j];
  2472. }
  2473. m[r][i] = sum;
  2474. }
  2475. }
  2476. }
  2477. /*
  2478. ============
  2479. idMatX::LDLT_Factor
  2480. in-place factorization: LDL'
  2481. L is a triangular matrix stored in the lower triangle.
  2482. L has ones on the diagonal that are not stored.
  2483. D is a diagonal matrix stored on the diagonal.
  2484. The upper triangle is not cleared.
  2485. The initial matrix has to be symmetric.
  2486. ============
  2487. */
  2488. bool idMatX::LDLT_Factor() {
  2489. int i, j, k;
  2490. float *v;
  2491. double d, sum;
  2492. assert( numRows == numColumns );
  2493. v = (float *) _alloca16( numRows * sizeof( float ) );
  2494. for ( i = 0; i < numRows; i++ ) {
  2495. sum = (*this)[i][i];
  2496. for ( j = 0; j < i; j++ ) {
  2497. d = (*this)[i][j];
  2498. v[j] = (*this)[j][j] * d;
  2499. sum -= v[j] * d;
  2500. }
  2501. if ( sum == 0.0f ) {
  2502. return false;
  2503. }
  2504. (*this)[i][i] = sum;
  2505. d = 1.0f / sum;
  2506. for ( j = i + 1; j < numRows; j++ ) {
  2507. sum = (*this)[j][i];
  2508. for ( k = 0; k < i; k++ ) {
  2509. sum -= (*this)[j][k] * v[k];
  2510. }
  2511. (*this)[j][i] = sum * d;
  2512. }
  2513. }
  2514. return true;
  2515. }
  2516. /*
  2517. ============
  2518. idMatX::LDLT_UpdateRankOne
  2519. Updates the in-place LDL' factorization to obtain the factors for the matrix: LDL' + alpha * v * v'
  2520. If offset > 0 only the lower right corner starting at (offset, offset) is updated.
  2521. ============
  2522. */
  2523. bool idMatX::LDLT_UpdateRankOne( const idVecX &v, float alpha, int offset ) {
  2524. int i, j;
  2525. float *y;
  2526. double diag, newDiag, beta, p, d;
  2527. assert( numRows == numColumns );
  2528. assert( v.GetSize() >= numRows );
  2529. assert( offset >= 0 && offset < numRows );
  2530. y = (float *) _alloca16( v.GetSize() * sizeof( float ) );
  2531. memcpy( y, v.ToFloatPtr(), v.GetSize() * sizeof( float ) );
  2532. for ( i = offset; i < numColumns; i++ ) {
  2533. p = y[i];
  2534. diag = (*this)[i][i];
  2535. (*this)[i][i] = newDiag = diag + alpha * p * p;
  2536. if ( newDiag == 0.0f ) {
  2537. return false;
  2538. }
  2539. alpha /= newDiag;
  2540. beta = p * alpha;
  2541. alpha *= diag;
  2542. for ( j = i+1; j < numRows; j++ ) {
  2543. d = (*this)[j][i];
  2544. y[j] -= p * d;
  2545. d += beta * y[j];
  2546. (*this)[j][i] = d;
  2547. }
  2548. }
  2549. return true;
  2550. }
  2551. /*
  2552. ============
  2553. idMatX::LDLT_UpdateRowColumn
  2554. Updates the in-place LDL' factorization to obtain the factors for the matrix:
  2555. [ 0 a 0 ]
  2556. LDL' + [ a b c ]
  2557. [ 0 c 0 ]
  2558. where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1]
  2559. ============
  2560. */
  2561. bool idMatX::LDLT_UpdateRowColumn( const idVecX &v, int r ) {
  2562. int i, j;
  2563. double sum;
  2564. float *original, *y;
  2565. idVecX addSub;
  2566. assert( numRows == numColumns );
  2567. assert( v.GetSize() >= numRows );
  2568. assert( r >= 0 && r < numRows );
  2569. addSub.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
  2570. if ( r == 0 ) {
  2571. if ( numColumns == 1 ) {
  2572. (*this)[0][0] += v[0];
  2573. return true;
  2574. }
  2575. for ( i = 0; i < numColumns; i++ ) {
  2576. addSub[i] = v[i];
  2577. }
  2578. } else {
  2579. original = (float *) _alloca16( numColumns * sizeof( float ) );
  2580. y = (float *) _alloca16( numColumns * sizeof( float ) );
  2581. // calculate original row/column of matrix
  2582. for ( i = 0; i < r; i++ ) {
  2583. y[i] = (*this)[r][i] * (*this)[i][i];
  2584. }
  2585. for ( i = 0; i < numColumns; i++ ) {
  2586. if ( i < r ) {
  2587. sum = (*this)[i][i] * (*this)[r][i];
  2588. } else if ( i == r ) {
  2589. sum = (*this)[r][r];
  2590. } else {
  2591. sum = (*this)[r][r] * (*this)[i][r];
  2592. }
  2593. for ( j = 0; j < i && j < r; j++ ) {
  2594. sum += (*this)[i][j] * y[j];
  2595. }
  2596. original[i] = sum;
  2597. }
  2598. // solve for y in L * y = original + v
  2599. for ( i = 0; i < r; i++ ) {
  2600. sum = original[i] + v[i];
  2601. for ( j = 0; j < i; j++ ) {
  2602. sum -= (*this)[i][j] * y[j];
  2603. }
  2604. y[i] = sum;
  2605. }
  2606. // calculate new row of L
  2607. for ( i = 0; i < r; i++ ) {
  2608. (*this)[r][i] = y[i] / (*this)[i][i];
  2609. }
  2610. // if the last row/column of the matrix is updated
  2611. if ( r == numColumns - 1 ) {
  2612. // only calculate new diagonal
  2613. sum = original[r] + v[r];
  2614. for ( j = 0; j < r; j++ ) {
  2615. sum -= (*this)[r][j] * y[j];
  2616. }
  2617. if ( sum == 0.0f ) {
  2618. return false;
  2619. }
  2620. (*this)[r][r] = sum;
  2621. return true;
  2622. }
  2623. // calculate the row/column to be added to the lower right sub matrix starting at (r, r)
  2624. for ( i = 0; i < r; i++ ) {
  2625. y[i] = (*this)[r][i] * (*this)[i][i];
  2626. }
  2627. for ( i = r; i < numColumns; i++ ) {
  2628. if ( i == r ) {
  2629. sum = (*this)[r][r];
  2630. } else {
  2631. sum = (*this)[r][r] * (*this)[i][r];
  2632. }
  2633. for ( j = 0; j < r; j++ ) {
  2634. sum += (*this)[i][j] * y[j];
  2635. }
  2636. addSub[i] = v[i] - ( sum - original[i] );
  2637. }
  2638. }
  2639. // add row/column to the lower right sub matrix starting at (r, r)
  2640. #if 0
  2641. idVecX v1, v2;
  2642. double d;
  2643. v1.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
  2644. v2.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
  2645. d = idMath::SQRT_1OVER2;
  2646. v1[r] = ( 0.5f * addSub[r] + 1.0f ) * d;
  2647. v2[r] = ( 0.5f * addSub[r] - 1.0f ) * d;
  2648. for ( i = r+1; i < numColumns; i++ ) {
  2649. v1[i] = v2[i] = addSub[i] * d;
  2650. }
  2651. // update
  2652. if ( !LDLT_UpdateRankOne( v1, 1.0f, r ) ) {
  2653. return false;
  2654. }
  2655. // downdate
  2656. if ( !LDLT_UpdateRankOne( v2, -1.0f, r ) ) {
  2657. return false;
  2658. }
  2659. #else
  2660. float *v1, *v2;
  2661. double d, diag, newDiag, p1, p2, alpha1, alpha2, beta1, beta2;
  2662. v1 = (float *) _alloca16( numColumns * sizeof( float ) );
  2663. v2 = (float *) _alloca16( numColumns * sizeof( float ) );
  2664. d = idMath::SQRT_1OVER2;
  2665. v1[r] = ( 0.5f * addSub[r] + 1.0f ) * d;
  2666. v2[r] = ( 0.5f * addSub[r] - 1.0f ) * d;
  2667. for ( i = r+1; i < numColumns; i++ ) {
  2668. v1[i] = v2[i] = addSub[i] * d;
  2669. }
  2670. alpha1 = 1.0f;
  2671. alpha2 = -1.0f;
  2672. // simultaneous update/downdate of the sub matrix starting at (r, r)
  2673. for ( i = r; i < numColumns; i++ ) {
  2674. diag = (*this)[i][i];
  2675. p1 = v1[i];
  2676. newDiag = diag + alpha1 * p1 * p1;
  2677. if ( newDiag == 0.0f ) {
  2678. return false;
  2679. }
  2680. alpha1 /= newDiag;
  2681. beta1 = p1 * alpha1;
  2682. alpha1 *= diag;
  2683. diag = newDiag;
  2684. p2 = v2[i];
  2685. newDiag = diag + alpha2 * p2 * p2;
  2686. if ( newDiag == 0.0f ) {
  2687. return false;
  2688. }
  2689. alpha2 /= newDiag;
  2690. beta2 = p2 * alpha2;
  2691. alpha2 *= diag;
  2692. (*this)[i][i] = newDiag;
  2693. for ( j = i+1; j < numRows; j++ ) {
  2694. d = (*this)[j][i];
  2695. v1[j] -= p1 * d;
  2696. d += beta1 * v1[j];
  2697. v2[j] -= p2 * d;
  2698. d += beta2 * v2[j];
  2699. (*this)[j][i] = d;
  2700. }
  2701. }
  2702. #endif
  2703. return true;
  2704. }
  2705. /*
  2706. ============
  2707. idMatX::LDLT_UpdateIncrement
  2708. Updates the in-place LDL' factorization to obtain the factors for the matrix:
  2709. [ A a ]
  2710. [ a b ]
  2711. where: a = v[0,numRows-1], b = v[numRows]
  2712. ============
  2713. */
  2714. bool idMatX::LDLT_UpdateIncrement( const idVecX &v ) {
  2715. int i, j;
  2716. float *x;
  2717. double sum, d;
  2718. assert( numRows == numColumns );
  2719. assert( v.GetSize() >= numRows+1 );
  2720. ChangeSize( numRows+1, numColumns+1, false );
  2721. x = (float *) _alloca16( numRows * sizeof( float ) );
  2722. // solve for x in L * x = v
  2723. for ( i = 0; i < numRows - 1; i++ ) {
  2724. sum = v[i];
  2725. for ( j = 0; j < i; j++ ) {
  2726. sum -= (*this)[i][j] * x[j];
  2727. }
  2728. x[i] = sum;
  2729. }
  2730. // calculate new row of L and calculate the diagonal entry
  2731. sum = v[numRows - 1];
  2732. for ( i = 0; i < numRows - 1; i++ ) {
  2733. (*this)[numRows - 1][i] = d = x[i] / (*this)[i][i];
  2734. sum -= d * x[i];
  2735. }
  2736. if ( sum == 0.0f ) {
  2737. return false;
  2738. }
  2739. // store the diagonal entry
  2740. (*this)[numRows - 1][numRows - 1] = sum;
  2741. return true;
  2742. }
  2743. /*
  2744. ============
  2745. idMatX::LDLT_UpdateDecrement
  2746. Updates the in-place LDL' factorization to obtain the factors for the matrix with row r and column r removed.
  2747. v should store the row of the original matrix.
  2748. ============
  2749. */
  2750. bool idMatX::LDLT_UpdateDecrement( const idVecX &v, int r ) {
  2751. idVecX v1;
  2752. assert( numRows == numColumns );
  2753. assert( v.GetSize() >= numRows );
  2754. assert( r >= 0 && r < numRows );
  2755. v1.SetData( numRows, VECX_ALLOCA( numRows ) );
  2756. // update the row and column to identity
  2757. v1 = -v;
  2758. v1[r] += 1.0f;
  2759. // NOTE: msvc compiler bug: the this pointer stored in edi is expected to stay
  2760. // untouched when calling LDLT_UpdateRowColumn in the if statement
  2761. #if 0
  2762. if ( !LDLT_UpdateRowColumn( v1, r ) ) {
  2763. #else
  2764. bool ret = LDLT_UpdateRowColumn( v1, r );
  2765. if ( !ret ) {
  2766. #endif
  2767. return false;
  2768. }
  2769. // physically remove the row and column
  2770. Update_Decrement( r );
  2771. return true;
  2772. }
  2773. /*
  2774. ============
  2775. idMatX::LDLT_Solve
  2776. Solve Ax = b with A factored in-place as: LDL'
  2777. ============
  2778. */
  2779. void idMatX::LDLT_Solve( idVecX &x, const idVecX &b ) const {
  2780. int i, j;
  2781. double sum;
  2782. assert( numRows == numColumns );
  2783. assert( x.GetSize() >= numRows && b.GetSize() >= numRows );
  2784. // solve L
  2785. for ( i = 0; i < numRows; i++ ) {
  2786. sum = b[i];
  2787. for ( j = 0; j < i; j++ ) {
  2788. sum -= (*this)[i][j] * x[j];
  2789. }
  2790. x[i] = sum;
  2791. }
  2792. // solve D
  2793. for ( i = 0; i < numRows; i++ ) {
  2794. x[i] /= (*this)[i][i];
  2795. }
  2796. // solve Lt
  2797. for ( i = numRows - 2; i >= 0; i-- ) {
  2798. sum = x[i];
  2799. for ( j = i + 1; j < numRows; j++ ) {
  2800. sum -= (*this)[j][i] * x[j];
  2801. }
  2802. x[i] = sum;
  2803. }
  2804. }
  2805. /*
  2806. ============
  2807. idMatX::LDLT_Inverse
  2808. Calculates the inverse of the matrix which is factored in-place as: LDL'
  2809. ============
  2810. */
  2811. void idMatX::LDLT_Inverse( idMatX &inv ) const {
  2812. int i, j;
  2813. idVecX x, b;
  2814. assert( numRows == numColumns );
  2815. x.SetData( numRows, VECX_ALLOCA( numRows ) );
  2816. b.SetData( numRows, VECX_ALLOCA( numRows ) );
  2817. b.Zero();
  2818. inv.SetSize( numRows, numColumns );
  2819. for ( i = 0; i < numRows; i++ ) {
  2820. b[i] = 1.0f;
  2821. LDLT_Solve( x, b );
  2822. for ( j = 0; j < numRows; j++ ) {
  2823. inv[j][i] = x[j];
  2824. }
  2825. b[i] = 0.0f;
  2826. }
  2827. }
  2828. /*
  2829. ============
  2830. idMatX::LDLT_UnpackFactors
  2831. Unpacks the in-place LDL' factorization.
  2832. ============
  2833. */
  2834. void idMatX::LDLT_UnpackFactors( idMatX &L, idMatX &D ) const {
  2835. int i, j;
  2836. L.Zero( numRows, numColumns );
  2837. D.Zero( numRows, numColumns );
  2838. for ( i = 0; i < numRows; i++ ) {
  2839. for ( j = 0; j < i; j++ ) {
  2840. L[i][j] = (*this)[i][j];
  2841. }
  2842. L[i][i] = 1.0f;
  2843. D[i][i] = (*this)[i][i];
  2844. }
  2845. }
  2846. /*
  2847. ============
  2848. idMatX::LDLT_MultiplyFactors
  2849. Multiplies the factors of the in-place LDL' factorization to form the original matrix.
  2850. ============
  2851. */
  2852. void idMatX::LDLT_MultiplyFactors( idMatX &m ) const {
  2853. int r, i, j;
  2854. float *v;
  2855. double sum;
  2856. v = (float *) _alloca16( numRows * sizeof( float ) );
  2857. m.SetSize( numRows, numColumns );
  2858. for ( r = 0; r < numRows; r++ ) {
  2859. // calculate row of matrix
  2860. for ( i = 0; i < r; i++ ) {
  2861. v[i] = (*this)[r][i] * (*this)[i][i];
  2862. }
  2863. for ( i = 0; i < numColumns; i++ ) {
  2864. if ( i < r ) {
  2865. sum = (*this)[i][i] * (*this)[r][i];
  2866. } else if ( i == r ) {
  2867. sum = (*this)[r][r];
  2868. } else {
  2869. sum = (*this)[r][r] * (*this)[i][r];
  2870. }
  2871. for ( j = 0; j < i && j < r; j++ ) {
  2872. sum += (*this)[i][j] * v[j];
  2873. }
  2874. m[r][i] = sum;
  2875. }
  2876. }
  2877. }
  2878. /*
  2879. ============
  2880. idMatX::TriDiagonal_ClearTriangles
  2881. ============
  2882. */
  2883. void idMatX::TriDiagonal_ClearTriangles() {
  2884. int i, j;
  2885. assert( numRows == numColumns );
  2886. for ( i = 0; i < numRows-2; i++ ) {
  2887. for ( j = i+2; j < numColumns; j++ ) {
  2888. (*this)[i][j] = 0.0f;
  2889. (*this)[j][i] = 0.0f;
  2890. }
  2891. }
  2892. }
  2893. /*
  2894. ============
  2895. idMatX::TriDiagonal_Solve
  2896. Solve Ax = b with A being tridiagonal.
  2897. ============
  2898. */
  2899. bool idMatX::TriDiagonal_Solve( idVecX &x, const idVecX &b ) const {
  2900. int i;
  2901. float d;
  2902. idVecX tmp;
  2903. assert( numRows == numColumns );
  2904. assert( x.GetSize() >= numRows && b.GetSize() >= numRows );
  2905. tmp.SetData( numRows, VECX_ALLOCA( numRows ) );
  2906. d = (*this)[0][0];
  2907. if ( d == 0.0f ) {
  2908. return false;
  2909. }
  2910. d = 1.0f / d;
  2911. x[0] = b[0] * d;
  2912. for ( i = 1; i < numRows; i++ ) {
  2913. tmp[i] = (*this)[i-1][i] * d;
  2914. d = (*this)[i][i] - (*this)[i][i-1] * tmp[i];
  2915. if ( d == 0.0f ) {
  2916. return false;
  2917. }
  2918. d = 1.0f / d;
  2919. x[i] = ( b[i] - (*this)[i][i-1] * x[i-1] ) * d;
  2920. }
  2921. for ( i = numRows - 2; i >= 0; i-- ) {
  2922. x[i] -= tmp[i+1] * x[i+1];
  2923. }
  2924. return true;
  2925. }
  2926. /*
  2927. ============
  2928. idMatX::TriDiagonal_Inverse
  2929. Calculates the inverse of a tri-diagonal matrix.
  2930. ============
  2931. */
  2932. void idMatX::TriDiagonal_Inverse( idMatX &inv ) const {
  2933. int i, j;
  2934. idVecX x, b;
  2935. assert( numRows == numColumns );
  2936. x.SetData( numRows, VECX_ALLOCA( numRows ) );
  2937. b.SetData( numRows, VECX_ALLOCA( numRows ) );
  2938. b.Zero();
  2939. inv.SetSize( numRows, numColumns );
  2940. for ( i = 0; i < numRows; i++ ) {
  2941. b[i] = 1.0f;
  2942. TriDiagonal_Solve( x, b );
  2943. for ( j = 0; j < numRows; j++ ) {
  2944. inv[j][i] = x[j];
  2945. }
  2946. b[i] = 0.0f;
  2947. }
  2948. }
  2949. /*
  2950. ============
  2951. idMatX::HouseholderReduction
  2952. Householder reduction to symmetric tri-diagonal form.
  2953. The original matrix is replaced by an orthogonal matrix effecting the accumulated householder transformations.
  2954. The diagonal elements of the diagonal matrix are stored in diag.
  2955. The off-diagonal elements of the diagonal matrix are stored in subd.
  2956. The initial matrix has to be symmetric.
  2957. ============
  2958. */
  2959. void idMatX::HouseholderReduction( idVecX &diag, idVecX &subd ) {
  2960. int i0, i1, i2, i3;
  2961. float h, f, g, invH, halfFdivH, scale, invScale, sum;
  2962. assert( numRows == numColumns );
  2963. diag.SetSize( numRows );
  2964. subd.SetSize( numRows );
  2965. for ( i0 = numRows-1, i3 = numRows-2; i0 >= 1; i0--, i3-- ) {
  2966. h = 0.0f;
  2967. scale = 0.0f;
  2968. if ( i3 > 0 ) {
  2969. for ( i2 = 0; i2 <= i3; i2++ ) {
  2970. scale += idMath::Fabs( (*this)[i0][i2] );
  2971. }
  2972. if ( scale == 0 ) {
  2973. subd[i0] = (*this)[i0][i3];
  2974. } else {
  2975. invScale = 1.0f / scale;
  2976. for (i2 = 0; i2 <= i3; i2++)
  2977. {
  2978. (*this)[i0][i2] *= invScale;
  2979. h += (*this)[i0][i2] * (*this)[i0][i2];
  2980. }
  2981. f = (*this)[i0][i3];
  2982. g = idMath::Sqrt( h );
  2983. if ( f > 0.0f ) {
  2984. g = -g;
  2985. }
  2986. subd[i0] = scale * g;
  2987. h -= f * g;
  2988. (*this)[i0][i3] = f - g;
  2989. f = 0.0f;
  2990. invH = 1.0f / h;
  2991. for (i1 = 0; i1 <= i3; i1++) {
  2992. (*this)[i1][i0] = (*this)[i0][i1] * invH;
  2993. g = 0.0f;
  2994. for (i2 = 0; i2 <= i1; i2++) {
  2995. g += (*this)[i1][i2] * (*this)[i0][i2];
  2996. }
  2997. for (i2 = i1+1; i2 <= i3; i2++) {
  2998. g += (*this)[i2][i1] * (*this)[i0][i2];
  2999. }
  3000. subd[i1] = g * invH;
  3001. f += subd[i1] * (*this)[i0][i1];
  3002. }
  3003. halfFdivH = 0.5f * f * invH;
  3004. for ( i1 = 0; i1 <= i3; i1++ ) {
  3005. f = (*this)[i0][i1];
  3006. g = subd[i1] - halfFdivH * f;
  3007. subd[i1] = g;
  3008. for ( i2 = 0; i2 <= i1; i2++ ) {
  3009. (*this)[i1][i2] -= f * subd[i2] + g * (*this)[i0][i2];
  3010. }
  3011. }
  3012. }
  3013. } else {
  3014. subd[i0] = (*this)[i0][i3];
  3015. }
  3016. diag[i0] = h;
  3017. }
  3018. diag[0] = 0.0f;
  3019. subd[0] = 0.0f;
  3020. for ( i0 = 0, i3 = -1; i0 <= numRows-1; i0++, i3++ ) {
  3021. if ( diag[i0] ) {
  3022. for ( i1 = 0; i1 <= i3; i1++ ) {
  3023. sum = 0.0f;
  3024. for (i2 = 0; i2 <= i3; i2++) {
  3025. sum += (*this)[i0][i2] * (*this)[i2][i1];
  3026. }
  3027. for ( i2 = 0; i2 <= i3; i2++ ) {
  3028. (*this)[i2][i1] -= sum * (*this)[i2][i0];
  3029. }
  3030. }
  3031. }
  3032. diag[i0] = (*this)[i0][i0];
  3033. (*this)[i0][i0] = 1.0f;
  3034. for ( i1 = 0; i1 <= i3; i1++ ) {
  3035. (*this)[i1][i0] = 0.0f;
  3036. (*this)[i0][i1] = 0.0f;
  3037. }
  3038. }
  3039. // re-order
  3040. for ( i0 = 1, i3 = 0; i0 < numRows; i0++, i3++ ) {
  3041. subd[i3] = subd[i0];
  3042. }
  3043. subd[numRows-1] = 0.0f;
  3044. }
  3045. /*
  3046. ============
  3047. idMatX::QL
  3048. QL algorithm with implicit shifts to determine the eigenvalues and eigenvectors of a symmetric tri-diagonal matrix.
  3049. diag contains the diagonal elements of the symmetric tri-diagonal matrix on input and is overwritten with the eigenvalues.
  3050. subd contains the off-diagonal elements of the symmetric tri-diagonal matrix and is destroyed.
  3051. This matrix has to be either the identity matrix to determine the eigenvectors for a symmetric tri-diagonal matrix,
  3052. or the matrix returned by the Householder reduction to determine the eigenvalues for the original symmetric matrix.
  3053. ============
  3054. */
  3055. bool idMatX::QL( idVecX &diag, idVecX &subd ) {
  3056. const int maxIter = 32;
  3057. int i0, i1, i2, i3;
  3058. float a, b, f, g, r, p, s, c;
  3059. assert( numRows == numColumns );
  3060. for ( i0 = 0; i0 < numRows; i0++ ) {
  3061. for ( i1 = 0; i1 < maxIter; i1++ ) {
  3062. for ( i2 = i0; i2 <= numRows - 2; i2++ ) {
  3063. a = idMath::Fabs( diag[i2] ) + idMath::Fabs( diag[i2+1] );
  3064. if ( idMath::Fabs( subd[i2] ) + a == a ) {
  3065. break;
  3066. }
  3067. }
  3068. if ( i2 == i0 ) {
  3069. break;
  3070. }
  3071. g = ( diag[i0+1] - diag[i0] ) / ( 2.0f * subd[i0] );
  3072. r = idMath::Sqrt( g * g + 1.0f );
  3073. if ( g < 0.0f ) {
  3074. g = diag[i2] - diag[i0] + subd[i0] / ( g - r );
  3075. } else {
  3076. g = diag[i2] - diag[i0] + subd[i0] / ( g + r );
  3077. }
  3078. s = 1.0f;
  3079. c = 1.0f;
  3080. p = 0.0f;
  3081. for ( i3 = i2 - 1; i3 >= i0; i3-- ) {
  3082. f = s * subd[i3];
  3083. b = c * subd[i3];
  3084. if ( idMath::Fabs( f ) >= idMath::Fabs( g ) ) {
  3085. c = g / f;
  3086. r = idMath::Sqrt( c * c + 1.0f );
  3087. subd[i3+1] = f * r;
  3088. s = 1.0f / r;
  3089. c *= s;
  3090. } else {
  3091. s = f / g;
  3092. r = idMath::Sqrt( s * s + 1.0f );
  3093. subd[i3+1] = g * r;
  3094. c = 1.0f / r;
  3095. s *= c;
  3096. }
  3097. g = diag[i3+1] - p;
  3098. r = ( diag[i3] - g ) * s + 2.0f * b * c;
  3099. p = s * r;
  3100. diag[i3+1] = g + p;
  3101. g = c * r - b;
  3102. for ( int i4 = 0; i4 < numRows; i4++ ) {
  3103. f = (*this)[i4][i3+1];
  3104. (*this)[i4][i3+1] = s * (*this)[i4][i3] + c * f;
  3105. (*this)[i4][i3] = c * (*this)[i4][i3] - s * f;
  3106. }
  3107. }
  3108. diag[i0] -= p;
  3109. subd[i0] = g;
  3110. subd[i2] = 0.0f;
  3111. }
  3112. if ( i1 == maxIter ) {
  3113. return false;
  3114. }
  3115. }
  3116. return true;
  3117. }
  3118. /*
  3119. ============
  3120. idMatX::Eigen_SolveSymmetricTriDiagonal
  3121. Determine eigen values and eigen vectors for a symmetric tri-diagonal matrix.
  3122. The eigen values are stored in 'eigenValues'.
  3123. Column i of the original matrix will store the eigen vector corresponding to the eigenValues[i].
  3124. The initial matrix has to be symmetric tri-diagonal.
  3125. ============
  3126. */
  3127. bool idMatX::Eigen_SolveSymmetricTriDiagonal( idVecX &eigenValues ) {
  3128. int i;
  3129. idVecX subd;
  3130. assert( numRows == numColumns );
  3131. subd.SetData( numRows, VECX_ALLOCA( numRows ) );
  3132. eigenValues.SetSize( numRows );
  3133. for ( i = 0; i < numRows-1; i++ ) {
  3134. eigenValues[i] = (*this)[i][i];
  3135. subd[i] = (*this)[i+1][i];
  3136. }
  3137. eigenValues[numRows-1] = (*this)[numRows-1][numRows-1];
  3138. Identity();
  3139. return QL( eigenValues, subd );
  3140. }
  3141. /*
  3142. ============
  3143. idMatX::Eigen_SolveSymmetric
  3144. Determine eigen values and eigen vectors for a symmetric matrix.
  3145. The eigen values are stored in 'eigenValues'.
  3146. Column i of the original matrix will store the eigen vector corresponding to the eigenValues[i].
  3147. The initial matrix has to be symmetric.
  3148. ============
  3149. */
  3150. bool idMatX::Eigen_SolveSymmetric( idVecX &eigenValues ) {
  3151. idVecX subd;
  3152. assert( numRows == numColumns );
  3153. subd.SetData( numRows, VECX_ALLOCA( numRows ) );
  3154. eigenValues.SetSize( numRows );
  3155. HouseholderReduction( eigenValues, subd );
  3156. return QL( eigenValues, subd );
  3157. }
  3158. /*
  3159. ============
  3160. idMatX::HessenbergReduction
  3161. Reduction to Hessenberg form.
  3162. ============
  3163. */
  3164. void idMatX::HessenbergReduction( idMatX &H ) {
  3165. int i, j, m;
  3166. int low = 0;
  3167. int high = numRows - 1;
  3168. float scale, f, g, h;
  3169. idVecX v;
  3170. v.SetData( numRows, VECX_ALLOCA( numRows ) );
  3171. for ( m = low + 1; m <= high - 1; m++ ) {
  3172. scale = 0.0f;
  3173. for ( i = m; i <= high; i++ ) {
  3174. scale = scale + idMath::Fabs( H[i][m-1] );
  3175. }
  3176. if ( scale != 0.0f ) {
  3177. // compute Householder transformation.
  3178. h = 0.0f;
  3179. for ( i = high; i >= m; i-- ) {
  3180. v[i] = H[i][m-1] / scale;
  3181. h += v[i] * v[i];
  3182. }
  3183. g = idMath::Sqrt( h );
  3184. if ( v[m] > 0.0f ) {
  3185. g = -g;
  3186. }
  3187. h = h - v[m] * g;
  3188. v[m] = v[m] - g;
  3189. // apply Householder similarity transformation
  3190. // H = (I-u*u'/h)*H*(I-u*u')/h)
  3191. for ( j = m; j < numRows; j++) {
  3192. f = 0.0f;
  3193. for ( i = high; i >= m; i-- ) {
  3194. f += v[i] * H[i][j];
  3195. }
  3196. f = f / h;
  3197. for ( i = m; i <= high; i++ ) {
  3198. H[i][j] -= f * v[i];
  3199. }
  3200. }
  3201. for ( i = 0; i <= high; i++ ) {
  3202. f = 0.0f;
  3203. for ( j = high; j >= m; j-- ) {
  3204. f += v[j] * H[i][j];
  3205. }
  3206. f = f / h;
  3207. for ( j = m; j <= high; j++ ) {
  3208. H[i][j] -= f * v[j];
  3209. }
  3210. }
  3211. v[m] = scale * v[m];
  3212. H[m][m-1] = scale * g;
  3213. }
  3214. }
  3215. // accumulate transformations
  3216. Identity();
  3217. for ( int m = high - 1; m >= low + 1; m-- ) {
  3218. if ( H[m][m-1] != 0.0f ) {
  3219. for ( i = m + 1; i <= high; i++ ) {
  3220. v[i] = H[i][m-1];
  3221. }
  3222. for ( j = m; j <= high; j++ ) {
  3223. g = 0.0f;
  3224. for ( i = m; i <= high; i++ ) {
  3225. g += v[i] * (*this)[i][j];
  3226. }
  3227. // float division to avoid possible underflow
  3228. g = ( g / v[m] ) / H[m][m-1];
  3229. for ( i = m; i <= high; i++ ) {
  3230. (*this)[i][j] += g * v[i];
  3231. }
  3232. }
  3233. }
  3234. }
  3235. }
  3236. /*
  3237. ============
  3238. idMatX::ComplexDivision
  3239. Complex scalar division.
  3240. ============
  3241. */
  3242. void idMatX::ComplexDivision( float xr, float xi, float yr, float yi, float &cdivr, float &cdivi ) {
  3243. float r, d;
  3244. if ( idMath::Fabs( yr ) > idMath::Fabs( yi ) ) {
  3245. r = yi / yr;
  3246. d = yr + r * yi;
  3247. cdivr = ( xr + r * xi ) / d;
  3248. cdivi = ( xi - r * xr ) / d;
  3249. } else {
  3250. r = yr / yi;
  3251. d = yi + r * yr;
  3252. cdivr = ( r * xr + xi ) / d;
  3253. cdivi = ( r * xi - xr ) / d;
  3254. }
  3255. }
  3256. /*
  3257. ============
  3258. idMatX::HessenbergToRealSchur
  3259. Reduction from Hessenberg to real Schur form.
  3260. ============
  3261. */
  3262. bool idMatX::HessenbergToRealSchur( idMatX &H, idVecX &realEigenValues, idVecX &imaginaryEigenValues ) {
  3263. int i, j, k;
  3264. int n = numRows - 1;
  3265. int low = 0;
  3266. int high = numRows - 1;
  3267. float eps = 2e-16f, exshift = 0.0f;
  3268. float p = 0.0f, q = 0.0f, r = 0.0f, s = 0.0f, z = 0.0f, t, w, x, y;
  3269. // store roots isolated by balanc and compute matrix norm
  3270. float norm = 0.0f;
  3271. for ( i = 0; i < numRows; i++ ) {
  3272. if ( i < low || i > high ) {
  3273. realEigenValues[i] = H[i][i];
  3274. imaginaryEigenValues[i] = 0.0f;
  3275. }
  3276. for ( j = Max( i - 1, 0 ); j < numRows; j++ ) {
  3277. norm = norm + idMath::Fabs( H[i][j] );
  3278. }
  3279. }
  3280. int iter = 0;
  3281. while( n >= low ) {
  3282. // look for single small sub-diagonal element
  3283. int l = n;
  3284. while ( l > low ) {
  3285. s = idMath::Fabs( H[l-1][l-1] ) + idMath::Fabs( H[l][l] );
  3286. if ( s == 0.0f ) {
  3287. s = norm;
  3288. }
  3289. if ( idMath::Fabs( H[l][l-1] ) < eps * s ) {
  3290. break;
  3291. }
  3292. l--;
  3293. }
  3294. // check for convergence
  3295. if ( l == n ) { // one root found
  3296. H[n][n] = H[n][n] + exshift;
  3297. realEigenValues[n] = H[n][n];
  3298. imaginaryEigenValues[n] = 0.0f;
  3299. n--;
  3300. iter = 0;
  3301. } else if ( l == n-1 ) { // two roots found
  3302. w = H[n][n-1] * H[n-1][n];
  3303. p = ( H[n-1][n-1] - H[n][n] ) / 2.0f;
  3304. q = p * p + w;
  3305. z = idMath::Sqrt( idMath::Fabs( q ) );
  3306. H[n][n] = H[n][n] + exshift;
  3307. H[n-1][n-1] = H[n-1][n-1] + exshift;
  3308. x = H[n][n];
  3309. if ( q >= 0.0f ) { // real pair
  3310. if ( p >= 0.0f ) {
  3311. z = p + z;
  3312. } else {
  3313. z = p - z;
  3314. }
  3315. realEigenValues[n-1] = x + z;
  3316. realEigenValues[n] = realEigenValues[n-1];
  3317. if ( z != 0.0f ) {
  3318. realEigenValues[n] = x - w / z;
  3319. }
  3320. imaginaryEigenValues[n-1] = 0.0f;
  3321. imaginaryEigenValues[n] = 0.0f;
  3322. x = H[n][n-1];
  3323. s = idMath::Fabs( x ) + idMath::Fabs( z );
  3324. p = x / s;
  3325. q = z / s;
  3326. r = idMath::Sqrt( p * p + q * q );
  3327. p = p / r;
  3328. q = q / r;
  3329. // modify row
  3330. for ( j = n-1; j < numRows; j++ ) {
  3331. z = H[n-1][j];
  3332. H[n-1][j] = q * z + p * H[n][j];
  3333. H[n][j] = q * H[n][j] - p * z;
  3334. }
  3335. // modify column
  3336. for ( i = 0; i <= n; i++ ) {
  3337. z = H[i][n-1];
  3338. H[i][n-1] = q * z + p * H[i][n];
  3339. H[i][n] = q * H[i][n] - p * z;
  3340. }
  3341. // accumulate transformations
  3342. for ( i = low; i <= high; i++ ) {
  3343. z = (*this)[i][n-1];
  3344. (*this)[i][n-1] = q * z + p * (*this)[i][n];
  3345. (*this)[i][n] = q * (*this)[i][n] - p * z;
  3346. }
  3347. } else { // complex pair
  3348. realEigenValues[n-1] = x + p;
  3349. realEigenValues[n] = x + p;
  3350. imaginaryEigenValues[n-1] = z;
  3351. imaginaryEigenValues[n] = -z;
  3352. }
  3353. n = n - 2;
  3354. iter = 0;
  3355. } else { // no convergence yet
  3356. // form shift
  3357. x = H[n][n];
  3358. y = 0.0f;
  3359. w = 0.0f;
  3360. if ( l < n ) {
  3361. y = H[n-1][n-1];
  3362. w = H[n][n-1] * H[n-1][n];
  3363. }
  3364. // Wilkinson's original ad hoc shift
  3365. if ( iter == 10 ) {
  3366. exshift += x;
  3367. for ( i = low; i <= n; i++ ) {
  3368. H[i][i] -= x;
  3369. }
  3370. s = idMath::Fabs( H[n][n-1] ) + idMath::Fabs( H[n-1][n-2] );
  3371. x = y = 0.75f * s;
  3372. w = -0.4375f * s * s;
  3373. }
  3374. // new ad hoc shift
  3375. if ( iter == 30 ) {
  3376. s = ( y - x ) / 2.0f;
  3377. s = s * s + w;
  3378. if ( s > 0 ) {
  3379. s = idMath::Sqrt( s );
  3380. if ( y < x ) {
  3381. s = -s;
  3382. }
  3383. s = x - w / ( ( y - x ) / 2.0f + s );
  3384. for ( i = low; i <= n; i++ ) {
  3385. H[i][i] -= s;
  3386. }
  3387. exshift += s;
  3388. x = y = w = 0.964f;
  3389. }
  3390. }
  3391. iter = iter + 1;
  3392. // look for two consecutive small sub-diagonal elements
  3393. int m;
  3394. for( m = n-2; m >= l; m-- ) {
  3395. z = H[m][m];
  3396. r = x - z;
  3397. s = y - z;
  3398. p = ( r * s - w ) / H[m+1][m] + H[m][m+1];
  3399. q = H[m+1][m+1] - z - r - s;
  3400. r = H[m+2][m+1];
  3401. s = idMath::Fabs( p ) + idMath::Fabs( q ) + idMath::Fabs( r );
  3402. p = p / s;
  3403. q = q / s;
  3404. r = r / s;
  3405. if ( m == l ) {
  3406. break;
  3407. }
  3408. if ( idMath::Fabs( H[m][m-1] ) * ( idMath::Fabs( q ) + idMath::Fabs( r ) ) <
  3409. eps * ( idMath::Fabs( p ) * ( idMath::Fabs( H[m-1][m-1] ) + idMath::Fabs( z ) + idMath::Fabs( H[m+1][m+1] ) ) ) ) {
  3410. break;
  3411. }
  3412. }
  3413. for ( i = m+2; i <= n; i++ ) {
  3414. H[i][i-2] = 0.0f;
  3415. if ( i > m+2 ) {
  3416. H[i][i-3] = 0.0f;
  3417. }
  3418. }
  3419. // double QR step involving rows l:n and columns m:n
  3420. for ( k = m; k <= n-1; k++ ) {
  3421. bool notlast = ( k != n-1 );
  3422. if ( k != m ) {
  3423. p = H[k][k-1];
  3424. q = H[k+1][k-1];
  3425. r = ( notlast ? H[k+2][k-1] : 0.0f );
  3426. x = idMath::Fabs( p ) + idMath::Fabs( q ) + idMath::Fabs( r );
  3427. if ( x != 0.0f ) {
  3428. p = p / x;
  3429. q = q / x;
  3430. r = r / x;
  3431. }
  3432. }
  3433. if ( x == 0.0f ) {
  3434. break;
  3435. }
  3436. s = idMath::Sqrt( p * p + q * q + r * r );
  3437. if ( p < 0.0f ) {
  3438. s = -s;
  3439. }
  3440. if ( s != 0.0f ) {
  3441. if ( k != m ) {
  3442. H[k][k-1] = -s * x;
  3443. } else if ( l != m ) {
  3444. H[k][k-1] = -H[k][k-1];
  3445. }
  3446. p = p + s;
  3447. x = p / s;
  3448. y = q / s;
  3449. z = r / s;
  3450. q = q / p;
  3451. r = r / p;
  3452. // modify row
  3453. for ( j = k; j < numRows; j++ ) {
  3454. p = H[k][j] + q * H[k+1][j];
  3455. if ( notlast ) {
  3456. p = p + r * H[k+2][j];
  3457. H[k+2][j] = H[k+2][j] - p * z;
  3458. }
  3459. H[k][j] = H[k][j] - p * x;
  3460. H[k+1][j] = H[k+1][j] - p * y;
  3461. }
  3462. // modify column
  3463. for ( i = 0; i <= Min( n, k + 3 ); i++ ) {
  3464. p = x * H[i][k] + y * H[i][k+1];
  3465. if ( notlast ) {
  3466. p = p + z * H[i][k+2];
  3467. H[i][k+2] = H[i][k+2] - p * r;
  3468. }
  3469. H[i][k] = H[i][k] - p;
  3470. H[i][k+1] = H[i][k+1] - p * q;
  3471. }
  3472. // accumulate transformations
  3473. for ( i = low; i <= high; i++ ) {
  3474. p = x * (*this)[i][k] + y * (*this)[i][k+1];
  3475. if ( notlast ) {
  3476. p = p + z * (*this)[i][k+2];
  3477. (*this)[i][k+2] = (*this)[i][k+2] - p * r;
  3478. }
  3479. (*this)[i][k] = (*this)[i][k] - p;
  3480. (*this)[i][k+1] = (*this)[i][k+1] - p * q;
  3481. }
  3482. }
  3483. }
  3484. }
  3485. }
  3486. // backsubstitute to find vectors of upper triangular form
  3487. if ( norm == 0.0f ) {
  3488. return false;
  3489. }
  3490. for ( n = numRows-1; n >= 0; n-- ) {
  3491. p = realEigenValues[n];
  3492. q = imaginaryEigenValues[n];
  3493. if ( q == 0.0f ) { // real vector
  3494. int l = n;
  3495. H[n][n] = 1.0f;
  3496. for ( i = n-1; i >= 0; i-- ) {
  3497. w = H[i][i] - p;
  3498. r = 0.0f;
  3499. for ( j = l; j <= n; j++ ) {
  3500. r = r + H[i][j] * H[j][n];
  3501. }
  3502. if ( imaginaryEigenValues[i] < 0.0f ) {
  3503. z = w;
  3504. s = r;
  3505. } else {
  3506. l = i;
  3507. if ( imaginaryEigenValues[i] == 0.0f ) {
  3508. if ( w != 0.0f ) {
  3509. H[i][n] = -r / w;
  3510. } else {
  3511. H[i][n] = -r / ( eps * norm );
  3512. }
  3513. } else { // solve real equations
  3514. x = H[i][i+1];
  3515. y = H[i+1][i];
  3516. q = ( realEigenValues[i] - p ) * ( realEigenValues[i] - p ) + imaginaryEigenValues[i] * imaginaryEigenValues[i];
  3517. t = ( x * s - z * r ) / q;
  3518. H[i][n] = t;
  3519. if ( idMath::Fabs(x) > idMath::Fabs( z ) ) {
  3520. H[i+1][n] = ( -r - w * t ) / x;
  3521. } else {
  3522. H[i+1][n] = ( -s - y * t ) / z;
  3523. }
  3524. }
  3525. // overflow control
  3526. t = idMath::Fabs(H[i][n]);
  3527. if ( ( eps * t ) * t > 1 ) {
  3528. for ( j = i; j <= n; j++ ) {
  3529. H[j][n] = H[j][n] / t;
  3530. }
  3531. }
  3532. }
  3533. }
  3534. } else if ( q < 0.0f ) { // complex vector
  3535. int l = n-1;
  3536. // last vector component imaginary so matrix is triangular
  3537. if ( idMath::Fabs( H[n][n-1] ) > idMath::Fabs( H[n-1][n] ) ) {
  3538. H[n-1][n-1] = q / H[n][n-1];
  3539. H[n-1][n] = -( H[n][n] - p ) / H[n][n-1];
  3540. } else {
  3541. ComplexDivision( 0.0f, -H[n-1][n], H[n-1][n-1]-p, q, H[n-1][n-1], H[n-1][n] );
  3542. }
  3543. H[n][n-1] = 0.0f;
  3544. H[n][n] = 1.0f;
  3545. for ( i = n-2; i >= 0; i-- ) {
  3546. float ra, sa, vr, vi;
  3547. ra = 0.0f;
  3548. sa = 0.0f;
  3549. for ( j = l; j <= n; j++ ) {
  3550. ra = ra + H[i][j] * H[j][n-1];
  3551. sa = sa + H[i][j] * H[j][n];
  3552. }
  3553. w = H[i][i] - p;
  3554. if ( imaginaryEigenValues[i] < 0.0f ) {
  3555. z = w;
  3556. r = ra;
  3557. s = sa;
  3558. } else {
  3559. l = i;
  3560. if ( imaginaryEigenValues[i] == 0.0f ) {
  3561. ComplexDivision( -ra, -sa, w, q, H[i][n-1], H[i][n] );
  3562. } else {
  3563. // solve complex equations
  3564. x = H[i][i+1];
  3565. y = H[i+1][i];
  3566. vr = ( realEigenValues[i] - p ) * ( realEigenValues[i] - p ) + imaginaryEigenValues[i] * imaginaryEigenValues[i] - q * q;
  3567. vi = ( realEigenValues[i] - p ) * 2.0f * q;
  3568. if ( vr == 0.0f && vi == 0.0f ) {
  3569. vr = eps * norm * ( idMath::Fabs( w ) + idMath::Fabs( q ) + idMath::Fabs( x ) + idMath::Fabs( y ) + idMath::Fabs( z ) );
  3570. }
  3571. ComplexDivision( x * r - z * ra + q * sa, x * s - z * sa - q * ra, vr, vi, H[i][n-1], H[i][n] );
  3572. if ( idMath::Fabs( x ) > ( idMath::Fabs( z ) + idMath::Fabs( q ) ) ) {
  3573. H[i+1][n-1] = ( -ra - w * H[i][n-1] + q * H[i][n] ) / x;
  3574. H[i+1][n] = ( -sa - w * H[i][n] - q * H[i][n-1] ) / x;
  3575. } else {
  3576. ComplexDivision( -r - y * H[i][n-1], -s - y * H[i][n], z, q, H[i+1][n-1], H[i+1][n] );
  3577. }
  3578. }
  3579. // overflow control
  3580. t = Max( idMath::Fabs( H[i][n-1] ), idMath::Fabs( H[i][n] ) );
  3581. if ( ( eps * t ) * t > 1 ) {
  3582. for ( j = i; j <= n; j++ ) {
  3583. H[j][n-1] = H[j][n-1] / t;
  3584. H[j][n] = H[j][n] / t;
  3585. }
  3586. }
  3587. }
  3588. }
  3589. }
  3590. }
  3591. // vectors of isolated roots
  3592. for ( i = 0; i < numRows; i++ ) {
  3593. if ( i < low || i > high ) {
  3594. for ( j = i; j < numRows; j++ ) {
  3595. (*this)[i][j] = H[i][j];
  3596. }
  3597. }
  3598. }
  3599. // back transformation to get eigenvectors of original matrix
  3600. for ( j = numRows - 1; j >= low; j-- ) {
  3601. for ( i = low; i <= high; i++ ) {
  3602. z = 0.0f;
  3603. for ( k = low; k <= Min( j, high ); k++ ) {
  3604. z = z + (*this)[i][k] * H[k][j];
  3605. }
  3606. (*this)[i][j] = z;
  3607. }
  3608. }
  3609. return true;
  3610. }
  3611. /*
  3612. ============
  3613. idMatX::Eigen_Solve
  3614. Determine eigen values and eigen vectors for a square matrix.
  3615. The eigen values are stored in 'realEigenValues' and 'imaginaryEigenValues'.
  3616. Column i of the original matrix will store the eigen vector corresponding to the realEigenValues[i] and imaginaryEigenValues[i].
  3617. ============
  3618. */
  3619. bool idMatX::Eigen_Solve( idVecX &realEigenValues, idVecX &imaginaryEigenValues ) {
  3620. idMatX H;
  3621. assert( numRows == numColumns );
  3622. realEigenValues.SetSize( numRows );
  3623. imaginaryEigenValues.SetSize( numRows );
  3624. H = *this;
  3625. // reduce to Hessenberg form
  3626. HessenbergReduction( H );
  3627. // reduce Hessenberg to real Schur form
  3628. return HessenbergToRealSchur( H, realEigenValues, imaginaryEigenValues );
  3629. }
  3630. /*
  3631. ============
  3632. idMatX::Eigen_SortIncreasing
  3633. ============
  3634. */
  3635. void idMatX::Eigen_SortIncreasing( idVecX &eigenValues ) {
  3636. for ( int i = 0, j = 0; i <= numRows - 2; i++ ) {
  3637. j = i;
  3638. float min = eigenValues[j];
  3639. for ( int k = i + 1; k < numRows; k++ ) {
  3640. if ( eigenValues[k] < min ) {
  3641. j = k;
  3642. min = eigenValues[j];
  3643. }
  3644. }
  3645. if ( j != i ) {
  3646. eigenValues.SwapElements( i, j );
  3647. SwapColumns( i, j );
  3648. }
  3649. }
  3650. }
  3651. /*
  3652. ============
  3653. idMatX::Eigen_SortDecreasing
  3654. ============
  3655. */
  3656. void idMatX::Eigen_SortDecreasing( idVecX &eigenValues ) {
  3657. for ( int i = 0, j = 0; i <= numRows - 2; i++ ) {
  3658. j = i;
  3659. float max = eigenValues[j];
  3660. for ( int k = i + 1; k < numRows; k++ ) {
  3661. if ( eigenValues[k] > max ) {
  3662. j = k;
  3663. max = eigenValues[j];
  3664. }
  3665. }
  3666. if ( j != i ) {
  3667. eigenValues.SwapElements( i, j );
  3668. SwapColumns( i, j );
  3669. }
  3670. }
  3671. }
  3672. /*
  3673. ============
  3674. idMatX::DeterminantGeneric
  3675. ============
  3676. */
  3677. float idMatX::DeterminantGeneric() const {
  3678. int *index;
  3679. float det;
  3680. idMatX tmp;
  3681. index = (int *) _alloca16( numRows * sizeof( int ) );
  3682. tmp.SetData( numRows, numColumns, MATX_ALLOCA( numRows * numColumns ) );
  3683. tmp = *this;
  3684. if ( !tmp.LU_Factor( index, &det ) ) {
  3685. return 0.0f;
  3686. }
  3687. return det;
  3688. }
  3689. /*
  3690. ============
  3691. idMatX::InverseSelfGeneric
  3692. ============
  3693. */
  3694. bool idMatX::InverseSelfGeneric() {
  3695. int i, j, *index;
  3696. idMatX tmp;
  3697. idVecX x, b;
  3698. index = (int *) _alloca16( numRows * sizeof( int ) );
  3699. tmp.SetData( numRows, numColumns, MATX_ALLOCA( numRows * numColumns ) );
  3700. tmp = *this;
  3701. if ( !tmp.LU_Factor( index ) ) {
  3702. return false;
  3703. }
  3704. x.SetData( numRows, VECX_ALLOCA( numRows ) );
  3705. b.SetData( numRows, VECX_ALLOCA( numRows ) );
  3706. b.Zero();
  3707. for ( i = 0; i < numRows; i++ ) {
  3708. b[i] = 1.0f;
  3709. tmp.LU_Solve( x, b, index );
  3710. for ( j = 0; j < numRows; j++ ) {
  3711. (*this)[j][i] = x[j];
  3712. }
  3713. b[i] = 0.0f;
  3714. }
  3715. return true;
  3716. }
  3717. /*
  3718. ============
  3719. idMatX::Test
  3720. ============
  3721. */
  3722. void idMatX::Test() {
  3723. idMatX original, m1, m2, m3, q1, q2, r1, r2;
  3724. idVecX v, w, u, c, d;
  3725. int offset, size, *index1, *index2;
  3726. size = 6;
  3727. original.Random( size, size, 0 );
  3728. original = original * original.Transpose();
  3729. index1 = (int *) _alloca16( ( size + 1 ) * sizeof( index1[0] ) );
  3730. index2 = (int *) _alloca16( ( size + 1 ) * sizeof( index2[0] ) );
  3731. /*
  3732. idMatX::LowerTriangularInverse
  3733. */
  3734. m1 = original;
  3735. m1.ClearUpperTriangle();
  3736. m2 = m1;
  3737. m2.InverseSelf();
  3738. m1.LowerTriangularInverse();
  3739. if ( !m1.Compare( m2, 1e-4f ) ) {
  3740. idLib::common->Warning( "idMatX::LowerTriangularInverse failed" );
  3741. }
  3742. /*
  3743. idMatX::UpperTriangularInverse
  3744. */
  3745. m1 = original;
  3746. m1.ClearLowerTriangle();
  3747. m2 = m1;
  3748. m2.InverseSelf();
  3749. m1.UpperTriangularInverse();
  3750. if ( !m1.Compare( m2, 1e-4f ) ) {
  3751. idLib::common->Warning( "idMatX::UpperTriangularInverse failed" );
  3752. }
  3753. /*
  3754. idMatX::Inverse_GaussJordan
  3755. */
  3756. m1 = original;
  3757. m1.Inverse_GaussJordan();
  3758. m1 *= original;
  3759. if ( !m1.IsIdentity( 1e-4f ) ) {
  3760. idLib::common->Warning( "idMatX::Inverse_GaussJordan failed" );
  3761. }
  3762. /*
  3763. idMatX::Inverse_UpdateRankOne
  3764. */
  3765. m1 = original;
  3766. m2 = original;
  3767. w.Random( size, 1 );
  3768. v.Random( size, 2 );
  3769. // invert m1
  3770. m1.Inverse_GaussJordan();
  3771. // modify and invert m2
  3772. m2.Update_RankOne( v, w, 1.0f );
  3773. if ( !m2.Inverse_GaussJordan() ) {
  3774. assert( 0 );
  3775. }
  3776. // update inverse of m1
  3777. m1.Inverse_UpdateRankOne( v, w, 1.0f );
  3778. if ( !m1.Compare( m2, 1e-4f ) ) {
  3779. idLib::common->Warning( "idMatX::Inverse_UpdateRankOne failed" );
  3780. }
  3781. /*
  3782. idMatX::Inverse_UpdateRowColumn
  3783. */
  3784. for ( offset = 0; offset < size; offset++ ) {
  3785. m1 = original;
  3786. m2 = original;
  3787. v.Random( size, 1 );
  3788. w.Random( size, 2 );
  3789. w[offset] = 0.0f;
  3790. // invert m1
  3791. m1.Inverse_GaussJordan();
  3792. // modify and invert m2
  3793. m2.Update_RowColumn( v, w, offset );
  3794. if ( !m2.Inverse_GaussJordan() ) {
  3795. assert( 0 );
  3796. }
  3797. // update inverse of m1
  3798. m1.Inverse_UpdateRowColumn( v, w, offset );
  3799. if ( !m1.Compare( m2, 1e-3f ) ) {
  3800. idLib::common->Warning( "idMatX::Inverse_UpdateRowColumn failed" );
  3801. }
  3802. }
  3803. /*
  3804. idMatX::Inverse_UpdateIncrement
  3805. */
  3806. m1 = original;
  3807. m2 = original;
  3808. v.Random( size + 1, 1 );
  3809. w.Random( size + 1, 2 );
  3810. w[size] = 0.0f;
  3811. // invert m1
  3812. m1.Inverse_GaussJordan();
  3813. // modify and invert m2
  3814. m2.Update_Increment( v, w );
  3815. if ( !m2.Inverse_GaussJordan() ) {
  3816. assert( 0 );
  3817. }
  3818. // update inverse of m1
  3819. m1.Inverse_UpdateIncrement( v, w );
  3820. if ( !m1.Compare( m2, 1e-4f ) ) {
  3821. idLib::common->Warning( "idMatX::Inverse_UpdateIncrement failed" );
  3822. }
  3823. /*
  3824. idMatX::Inverse_UpdateDecrement
  3825. */
  3826. for ( offset = 0; offset < size; offset++ ) {
  3827. m1 = original;
  3828. m2 = original;
  3829. v.SetSize( 6 );
  3830. w.SetSize( 6 );
  3831. for ( int i = 0; i < size; i++ ) {
  3832. v[i] = original[i][offset];
  3833. w[i] = original[offset][i];
  3834. }
  3835. // invert m1
  3836. m1.Inverse_GaussJordan();
  3837. // modify and invert m2
  3838. m2.Update_Decrement( offset );
  3839. if ( !m2.Inverse_GaussJordan() ) {
  3840. assert( 0 );
  3841. }
  3842. // update inverse of m1
  3843. m1.Inverse_UpdateDecrement( v, w, offset );
  3844. if ( !m1.Compare( m2, 1e-3f ) ) {
  3845. idLib::common->Warning( "idMatX::Inverse_UpdateDecrement failed" );
  3846. }
  3847. }
  3848. /*
  3849. idMatX::LU_Factor
  3850. */
  3851. m1 = original;
  3852. m1.LU_Factor( NULL ); // no pivoting
  3853. m1.LU_UnpackFactors( m2, m3 );
  3854. m1 = m2 * m3;
  3855. if ( !original.Compare( m1, 1e-4f ) ) {
  3856. idLib::common->Warning( "idMatX::LU_Factor failed" );
  3857. }
  3858. /*
  3859. idMatX::LU_UpdateRankOne
  3860. */
  3861. m1 = original;
  3862. m2 = original;
  3863. w.Random( size, 1 );
  3864. v.Random( size, 2 );
  3865. // factor m1
  3866. m1.LU_Factor( index1 );
  3867. // modify and factor m2
  3868. m2.Update_RankOne( v, w, 1.0f );
  3869. if ( !m2.LU_Factor( index2 ) ) {
  3870. assert( 0 );
  3871. }
  3872. m2.LU_MultiplyFactors( m3, index2 );
  3873. m2 = m3;
  3874. // update factored m1
  3875. m1.LU_UpdateRankOne( v, w, 1.0f, index1 );
  3876. m1.LU_MultiplyFactors( m3, index1 );
  3877. m1 = m3;
  3878. if ( !m1.Compare( m2, 1e-4f ) ) {
  3879. idLib::common->Warning( "idMatX::LU_UpdateRankOne failed" );
  3880. }
  3881. /*
  3882. idMatX::LU_UpdateRowColumn
  3883. */
  3884. for ( offset = 0; offset < size; offset++ ) {
  3885. m1 = original;
  3886. m2 = original;
  3887. v.Random( size, 1 );
  3888. w.Random( size, 2 );
  3889. w[offset] = 0.0f;
  3890. // factor m1
  3891. m1.LU_Factor( index1 );
  3892. // modify and factor m2
  3893. m2.Update_RowColumn( v, w, offset );
  3894. if ( !m2.LU_Factor( index2 ) ) {
  3895. assert( 0 );
  3896. }
  3897. m2.LU_MultiplyFactors( m3, index2 );
  3898. m2 = m3;
  3899. // update m1
  3900. m1.LU_UpdateRowColumn( v, w, offset, index1 );
  3901. m1.LU_MultiplyFactors( m3, index1 );
  3902. m1 = m3;
  3903. if ( !m1.Compare( m2, 1e-3f ) ) {
  3904. idLib::common->Warning( "idMatX::LU_UpdateRowColumn failed" );
  3905. }
  3906. }
  3907. /*
  3908. idMatX::LU_UpdateIncrement
  3909. */
  3910. m1 = original;
  3911. m2 = original;
  3912. v.Random( size + 1, 1 );
  3913. w.Random( size + 1, 2 );
  3914. w[size] = 0.0f;
  3915. // factor m1
  3916. m1.LU_Factor( index1 );
  3917. // modify and factor m2
  3918. m2.Update_Increment( v, w );
  3919. if ( !m2.LU_Factor( index2 ) ) {
  3920. assert( 0 );
  3921. }
  3922. m2.LU_MultiplyFactors( m3, index2 );
  3923. m2 = m3;
  3924. // update factored m1
  3925. m1.LU_UpdateIncrement( v, w, index1 );
  3926. m1.LU_MultiplyFactors( m3, index1 );
  3927. m1 = m3;
  3928. if ( !m1.Compare( m2, 1e-4f ) ) {
  3929. idLib::common->Warning( "idMatX::LU_UpdateIncrement failed" );
  3930. }
  3931. /*
  3932. idMatX::LU_UpdateDecrement
  3933. */
  3934. for ( offset = 0; offset < size; offset++ ) {
  3935. m1 = original;
  3936. m2 = original;
  3937. v.SetSize( 6 );
  3938. w.SetSize( 6 );
  3939. for ( int i = 0; i < size; i++ ) {
  3940. v[i] = original[i][offset];
  3941. w[i] = original[offset][i];
  3942. }
  3943. // factor m1
  3944. m1.LU_Factor( index1 );
  3945. // modify and factor m2
  3946. m2.Update_Decrement( offset );
  3947. if ( !m2.LU_Factor( index2 ) ) {
  3948. assert( 0 );
  3949. }
  3950. m2.LU_MultiplyFactors( m3, index2 );
  3951. m2 = m3;
  3952. u.SetSize( 6 );
  3953. for ( int i = 0; i < size; i++ ) {
  3954. u[i] = original[index1[offset]][i];
  3955. }
  3956. // update factors of m1
  3957. m1.LU_UpdateDecrement( v, w, u, offset, index1 );
  3958. m1.LU_MultiplyFactors( m3, index1 );
  3959. m1 = m3;
  3960. if ( !m1.Compare( m2, 1e-3f ) ) {
  3961. idLib::common->Warning( "idMatX::LU_UpdateDecrement failed" );
  3962. }
  3963. }
  3964. /*
  3965. idMatX::LU_Inverse
  3966. */
  3967. m2 = original;
  3968. m2.LU_Factor( NULL );
  3969. m2.LU_Inverse( m1, NULL );
  3970. m1 *= original;
  3971. if ( !m1.IsIdentity( 1e-4f ) ) {
  3972. idLib::common->Warning( "idMatX::LU_Inverse failed" );
  3973. }
  3974. /*
  3975. idMatX::QR_Factor
  3976. */
  3977. c.SetSize( size );
  3978. d.SetSize( size );
  3979. m1 = original;
  3980. m1.QR_Factor( c, d );
  3981. m1.QR_UnpackFactors( q1, r1, c, d );
  3982. m1 = q1 * r1;
  3983. if ( !original.Compare( m1, 1e-4f ) ) {
  3984. idLib::common->Warning( "idMatX::QR_Factor failed" );
  3985. }
  3986. /*
  3987. idMatX::QR_UpdateRankOne
  3988. */
  3989. c.SetSize( size );
  3990. d.SetSize( size );
  3991. m1 = original;
  3992. m2 = original;
  3993. w.Random( size, 0 );
  3994. v = w;
  3995. // factor m1
  3996. m1.QR_Factor( c, d );
  3997. m1.QR_UnpackFactors( q1, r1, c, d );
  3998. // modify and factor m2
  3999. m2.Update_RankOne( v, w, 1.0f );
  4000. if ( !m2.QR_Factor( c, d ) ) {
  4001. assert( 0 );
  4002. }
  4003. m2.QR_UnpackFactors( q2, r2, c, d );
  4004. m2 = q2 * r2;
  4005. // update factored m1
  4006. q1.QR_UpdateRankOne( r1, v, w, 1.0f );
  4007. m1 = q1 * r1;
  4008. if ( !m1.Compare( m2, 1e-4f ) ) {
  4009. idLib::common->Warning( "idMatX::QR_UpdateRankOne failed" );
  4010. }
  4011. /*
  4012. idMatX::QR_UpdateRowColumn
  4013. */
  4014. for ( offset = 0; offset < size; offset++ ) {
  4015. c.SetSize( size );
  4016. d.SetSize( size );
  4017. m1 = original;
  4018. m2 = original;
  4019. v.Random( size, 1 );
  4020. w.Random( size, 2 );
  4021. w[offset] = 0.0f;
  4022. // factor m1
  4023. m1.QR_Factor( c, d );
  4024. m1.QR_UnpackFactors( q1, r1, c, d );
  4025. // modify and factor m2
  4026. m2.Update_RowColumn( v, w, offset );
  4027. if ( !m2.QR_Factor( c, d ) ) {
  4028. assert( 0 );
  4029. }
  4030. m2.QR_UnpackFactors( q2, r2, c, d );
  4031. m2 = q2 * r2;
  4032. // update m1
  4033. q1.QR_UpdateRowColumn( r1, v, w, offset );
  4034. m1 = q1 * r1;
  4035. if ( !m1.Compare( m2, 1e-3f ) ) {
  4036. idLib::common->Warning( "idMatX::QR_UpdateRowColumn failed" );
  4037. }
  4038. }
  4039. /*
  4040. idMatX::QR_UpdateIncrement
  4041. */
  4042. c.SetSize( size+1 );
  4043. d.SetSize( size+1 );
  4044. m1 = original;
  4045. m2 = original;
  4046. v.Random( size + 1, 1 );
  4047. w.Random( size + 1, 2 );
  4048. w[size] = 0.0f;
  4049. // factor m1
  4050. m1.QR_Factor( c, d );
  4051. m1.QR_UnpackFactors( q1, r1, c, d );
  4052. // modify and factor m2
  4053. m2.Update_Increment( v, w );
  4054. if ( !m2.QR_Factor( c, d ) ) {
  4055. assert( 0 );
  4056. }
  4057. m2.QR_UnpackFactors( q2, r2, c, d );
  4058. m2 = q2 * r2;
  4059. // update factored m1
  4060. q1.QR_UpdateIncrement( r1, v, w );
  4061. m1 = q1 * r1;
  4062. if ( !m1.Compare( m2, 1e-4f ) ) {
  4063. idLib::common->Warning( "idMatX::QR_UpdateIncrement failed" );
  4064. }
  4065. /*
  4066. idMatX::QR_UpdateDecrement
  4067. */
  4068. for ( offset = 0; offset < size; offset++ ) {
  4069. c.SetSize( size+1 );
  4070. d.SetSize( size+1 );
  4071. m1 = original;
  4072. m2 = original;
  4073. v.SetSize( 6 );
  4074. w.SetSize( 6 );
  4075. for ( int i = 0; i < size; i++ ) {
  4076. v[i] = original[i][offset];
  4077. w[i] = original[offset][i];
  4078. }
  4079. // factor m1
  4080. m1.QR_Factor( c, d );
  4081. m1.QR_UnpackFactors( q1, r1, c, d );
  4082. // modify and factor m2
  4083. m2.Update_Decrement( offset );
  4084. if ( !m2.QR_Factor( c, d ) ) {
  4085. assert( 0 );
  4086. }
  4087. m2.QR_UnpackFactors( q2, r2, c, d );
  4088. m2 = q2 * r2;
  4089. // update factors of m1
  4090. q1.QR_UpdateDecrement( r1, v, w, offset );
  4091. m1 = q1 * r1;
  4092. if ( !m1.Compare( m2, 1e-3f ) ) {
  4093. idLib::common->Warning( "idMatX::QR_UpdateDecrement failed" );
  4094. }
  4095. }
  4096. /*
  4097. idMatX::QR_Inverse
  4098. */
  4099. m2 = original;
  4100. m2.QR_Factor( c, d );
  4101. m2.QR_Inverse( m1, c, d );
  4102. m1 *= original;
  4103. if ( !m1.IsIdentity( 1e-4f ) ) {
  4104. idLib::common->Warning( "idMatX::QR_Inverse failed" );
  4105. }
  4106. /*
  4107. idMatX::SVD_Factor
  4108. */
  4109. m1 = original;
  4110. m3.Zero( size, size );
  4111. w.Zero( size );
  4112. m1.SVD_Factor( w, m3 );
  4113. m2.Diag( w );
  4114. m3.TransposeSelf();
  4115. m1 = m1 * m2 * m3;
  4116. if ( !original.Compare( m1, 1e-4f ) ) {
  4117. idLib::common->Warning( "idMatX::SVD_Factor failed" );
  4118. }
  4119. /*
  4120. idMatX::SVD_Inverse
  4121. */
  4122. m2 = original;
  4123. m2.SVD_Factor( w, m3 );
  4124. m2.SVD_Inverse( m1, w, m3 );
  4125. m1 *= original;
  4126. if ( !m1.IsIdentity( 1e-4f ) ) {
  4127. idLib::common->Warning( "idMatX::SVD_Inverse failed" );
  4128. }
  4129. /*
  4130. idMatX::Cholesky_Factor
  4131. */
  4132. m1 = original;
  4133. m1.Cholesky_Factor();
  4134. m1.Cholesky_MultiplyFactors( m2 );
  4135. if ( !original.Compare( m2, 1e-4f ) ) {
  4136. idLib::common->Warning( "idMatX::Cholesky_Factor failed" );
  4137. }
  4138. /*
  4139. idMatX::Cholesky_UpdateRankOne
  4140. */
  4141. m1 = original;
  4142. m2 = original;
  4143. w.Random( size, 0 );
  4144. // factor m1
  4145. m1.Cholesky_Factor();
  4146. m1.ClearUpperTriangle();
  4147. // modify and factor m2
  4148. m2.Update_RankOneSymmetric( w, 1.0f );
  4149. if ( !m2.Cholesky_Factor() ) {
  4150. assert( 0 );
  4151. }
  4152. m2.ClearUpperTriangle();
  4153. // update factored m1
  4154. m1.Cholesky_UpdateRankOne( w, 1.0f, 0 );
  4155. if ( !m1.Compare( m2, 1e-4f ) ) {
  4156. idLib::common->Warning( "idMatX::Cholesky_UpdateRankOne failed" );
  4157. }
  4158. /*
  4159. idMatX::Cholesky_UpdateRowColumn
  4160. */
  4161. for ( offset = 0; offset < size; offset++ ) {
  4162. m1 = original;
  4163. m2 = original;
  4164. // factor m1
  4165. m1.Cholesky_Factor();
  4166. m1.ClearUpperTriangle();
  4167. int pdtable[] = { 1, 0, 1, 0, 0, 0 };
  4168. w.Random( size, pdtable[offset] );
  4169. w *= 0.1f;
  4170. // modify and factor m2
  4171. m2.Update_RowColumnSymmetric( w, offset );
  4172. if ( !m2.Cholesky_Factor() ) {
  4173. assert( 0 );
  4174. }
  4175. m2.ClearUpperTriangle();
  4176. // update m1
  4177. m1.Cholesky_UpdateRowColumn( w, offset );
  4178. if ( !m1.Compare( m2, 1e-3f ) ) {
  4179. idLib::common->Warning( "idMatX::Cholesky_UpdateRowColumn failed" );
  4180. }
  4181. }
  4182. /*
  4183. idMatX::Cholesky_UpdateIncrement
  4184. */
  4185. m1.Random( size + 1, size + 1, 0 );
  4186. m3 = m1 * m1.Transpose();
  4187. m1.SquareSubMatrix( m3, size );
  4188. m2 = m1;
  4189. w.SetSize( size + 1 );
  4190. for ( int i = 0; i < size + 1; i++ ) {
  4191. w[i] = m3[size][i];
  4192. }
  4193. // factor m1
  4194. m1.Cholesky_Factor();
  4195. // modify and factor m2
  4196. m2.Update_IncrementSymmetric( w );
  4197. if ( !m2.Cholesky_Factor() ) {
  4198. assert( 0 );
  4199. }
  4200. // update factored m1
  4201. m1.Cholesky_UpdateIncrement( w );
  4202. m1.ClearUpperTriangle();
  4203. m2.ClearUpperTriangle();
  4204. if ( !m1.Compare( m2, 1e-4f ) ) {
  4205. idLib::common->Warning( "idMatX::Cholesky_UpdateIncrement failed" );
  4206. }
  4207. /*
  4208. idMatX::Cholesky_UpdateDecrement
  4209. */
  4210. for ( offset = 0; offset < size; offset += size - 1 ) {
  4211. m1 = original;
  4212. m2 = original;
  4213. v.SetSize( 6 );
  4214. for ( int i = 0; i < size; i++ ) {
  4215. v[i] = original[i][offset];
  4216. }
  4217. // factor m1
  4218. m1.Cholesky_Factor();
  4219. // modify and factor m2
  4220. m2.Update_Decrement( offset );
  4221. if ( !m2.Cholesky_Factor() ) {
  4222. assert( 0 );
  4223. }
  4224. // update factors of m1
  4225. m1.Cholesky_UpdateDecrement( v, offset );
  4226. if ( !m1.Compare( m2, 1e-3f ) ) {
  4227. idLib::common->Warning( "idMatX::Cholesky_UpdateDecrement failed" );
  4228. }
  4229. }
  4230. /*
  4231. idMatX::Cholesky_Inverse
  4232. */
  4233. m2 = original;
  4234. m2.Cholesky_Factor();
  4235. m2.Cholesky_Inverse( m1 );
  4236. m1 *= original;
  4237. if ( !m1.IsIdentity( 1e-4f ) ) {
  4238. idLib::common->Warning( "idMatX::Cholesky_Inverse failed" );
  4239. }
  4240. /*
  4241. idMatX::LDLT_Factor
  4242. */
  4243. m1 = original;
  4244. m1.LDLT_Factor();
  4245. m1.LDLT_MultiplyFactors( m2 );
  4246. if ( !original.Compare( m2, 1e-4f ) ) {
  4247. idLib::common->Warning( "idMatX::LDLT_Factor failed" );
  4248. }
  4249. m1.LDLT_UnpackFactors( m2, m3 );
  4250. m2 = m2 * m3 * m2.Transpose();
  4251. if ( !original.Compare( m2, 1e-4f ) ) {
  4252. idLib::common->Warning( "idMatX::LDLT_Factor failed" );
  4253. }
  4254. /*
  4255. idMatX::LDLT_UpdateRankOne
  4256. */
  4257. m1 = original;
  4258. m2 = original;
  4259. w.Random( size, 0 );
  4260. // factor m1
  4261. m1.LDLT_Factor();
  4262. m1.ClearUpperTriangle();
  4263. // modify and factor m2
  4264. m2.Update_RankOneSymmetric( w, 1.0f );
  4265. if ( !m2.LDLT_Factor() ) {
  4266. assert( 0 );
  4267. }
  4268. m2.ClearUpperTriangle();
  4269. // update factored m1
  4270. m1.LDLT_UpdateRankOne( w, 1.0f, 0 );
  4271. if ( !m1.Compare( m2, 1e-4f ) ) {
  4272. idLib::common->Warning( "idMatX::LDLT_UpdateRankOne failed" );
  4273. }
  4274. /*
  4275. idMatX::LDLT_UpdateRowColumn
  4276. */
  4277. for ( offset = 0; offset < size; offset++ ) {
  4278. m1 = original;
  4279. m2 = original;
  4280. w.Random( size, 0 );
  4281. // factor m1
  4282. m1.LDLT_Factor();
  4283. m1.ClearUpperTriangle();
  4284. // modify and factor m2
  4285. m2.Update_RowColumnSymmetric( w, offset );
  4286. if ( !m2.LDLT_Factor() ) {
  4287. assert( 0 );
  4288. }
  4289. m2.ClearUpperTriangle();
  4290. // update m1
  4291. m1.LDLT_UpdateRowColumn( w, offset );
  4292. if ( !m1.Compare( m2, 1e-3f ) ) {
  4293. idLib::common->Warning( "idMatX::LDLT_UpdateRowColumn failed" );
  4294. }
  4295. }
  4296. /*
  4297. idMatX::LDLT_UpdateIncrement
  4298. */
  4299. m1.Random( size + 1, size + 1, 0 );
  4300. m3 = m1 * m1.Transpose();
  4301. m1.SquareSubMatrix( m3, size );
  4302. m2 = m1;
  4303. w.SetSize( size + 1 );
  4304. for ( int i = 0; i < size + 1; i++ ) {
  4305. w[i] = m3[size][i];
  4306. }
  4307. // factor m1
  4308. m1.LDLT_Factor();
  4309. // modify and factor m2
  4310. m2.Update_IncrementSymmetric( w );
  4311. if ( !m2.LDLT_Factor() ) {
  4312. assert( 0 );
  4313. }
  4314. // update factored m1
  4315. m1.LDLT_UpdateIncrement( w );
  4316. m1.ClearUpperTriangle();
  4317. m2.ClearUpperTriangle();
  4318. if ( !m1.Compare( m2, 1e-4f ) ) {
  4319. idLib::common->Warning( "idMatX::LDLT_UpdateIncrement failed" );
  4320. }
  4321. /*
  4322. idMatX::LDLT_UpdateDecrement
  4323. */
  4324. for ( offset = 0; offset < size; offset++ ) {
  4325. m1 = original;
  4326. m2 = original;
  4327. v.SetSize( 6 );
  4328. for ( int i = 0; i < size; i++ ) {
  4329. v[i] = original[i][offset];
  4330. }
  4331. // factor m1
  4332. m1.LDLT_Factor();
  4333. // modify and factor m2
  4334. m2.Update_Decrement( offset );
  4335. if ( !m2.LDLT_Factor() ) {
  4336. assert( 0 );
  4337. }
  4338. // update factors of m1
  4339. m1.LDLT_UpdateDecrement( v, offset );
  4340. if ( !m1.Compare( m2, 1e-3f ) ) {
  4341. idLib::common->Warning( "idMatX::LDLT_UpdateDecrement failed" );
  4342. }
  4343. }
  4344. /*
  4345. idMatX::LDLT_Inverse
  4346. */
  4347. m2 = original;
  4348. m2.LDLT_Factor();
  4349. m2.LDLT_Inverse( m1 );
  4350. m1 *= original;
  4351. if ( !m1.IsIdentity( 1e-4f ) ) {
  4352. idLib::common->Warning( "idMatX::LDLT_Inverse failed" );
  4353. }
  4354. /*
  4355. idMatX::Eigen_SolveSymmetricTriDiagonal
  4356. */
  4357. m3 = original;
  4358. m3.TriDiagonal_ClearTriangles();
  4359. m1 = m3;
  4360. v.SetSize( size );
  4361. m1.Eigen_SolveSymmetricTriDiagonal( v );
  4362. m3.TransposeMultiply( m2, m1 );
  4363. for ( int i = 0; i < size; i++ ) {
  4364. for ( int j = 0; j < size; j++ ) {
  4365. m1[i][j] *= v[j];
  4366. }
  4367. }
  4368. if ( !m1.Compare( m2, 1e-4f ) ) {
  4369. idLib::common->Warning( "idMatX::Eigen_SolveSymmetricTriDiagonal failed" );
  4370. }
  4371. /*
  4372. idMatX::Eigen_SolveSymmetric
  4373. */
  4374. m3 = original;
  4375. m1 = m3;
  4376. v.SetSize( size );
  4377. m1.Eigen_SolveSymmetric( v );
  4378. m3.TransposeMultiply( m2, m1 );
  4379. for ( int i = 0; i < size; i++ ) {
  4380. for ( int j = 0; j < size; j++ ) {
  4381. m1[i][j] *= v[j];
  4382. }
  4383. }
  4384. if ( !m1.Compare( m2, 1e-4f ) ) {
  4385. idLib::common->Warning( "idMatX::Eigen_SolveSymmetric failed" );
  4386. }
  4387. /*
  4388. idMatX::Eigen_Solve
  4389. */
  4390. m3 = original;
  4391. m1 = m3;
  4392. v.SetSize( size );
  4393. w.SetSize( size );
  4394. m1.Eigen_Solve( v, w );
  4395. m3.TransposeMultiply( m2, m1 );
  4396. for ( int i = 0; i < size; i++ ) {
  4397. for ( int j = 0; j < size; j++ ) {
  4398. m1[i][j] *= v[j];
  4399. }
  4400. }
  4401. if ( !m1.Compare( m2, 1e-4f ) ) {
  4402. idLib::common->Warning( "idMatX::Eigen_Solve failed" );
  4403. }
  4404. }