Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/newmat/newmat7.cpp @ 4595

Last change on this file since 4595 was 4565, checked in by patrick, 19 years ago

orxonox/trunk: added the newmat library to the project. needs some translation in directory, temp under util/newmat. is needed by the collision detection engine to perform lin alg operations such as eigenvector decomposition. perhaps we will make our own library to do that later.

File size: 31.0 KB
Line 
1//$$ newmat7.cpp     Invert, solve, binary operations
2
3// Copyright (C) 1991,2,3,4: R B Davies
4
5#include "include.h"
6
7#include "newmat.h"
8#include "newmatrc.h"
9
10#ifdef use_namespace
11namespace NEWMAT {
12#endif
13
14
15#ifdef DO_REPORT
16#define REPORT { static ExeCounter ExeCount(__LINE__,7); ++ExeCount; }
17#else
18#define REPORT {}
19#endif
20
21
22//***************************** solve routines ******************************/
23
24GeneralMatrix* GeneralMatrix::MakeSolver()
25{
26   REPORT
27   GeneralMatrix* gm = new CroutMatrix(*this);
28   MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
29}
30
31GeneralMatrix* Matrix::MakeSolver()
32{
33   REPORT
34   GeneralMatrix* gm = new CroutMatrix(*this);
35   MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
36}
37
38void CroutMatrix::Solver(MatrixColX& mcout, const MatrixColX& mcin)
39{
40   REPORT
41   int i = mcin.skip; Real* el = mcin.data-i; Real* el1 = el;
42   while (i--) *el++ = 0.0;
43   el += mcin.storage; i = nrows - mcin.skip - mcin.storage;
44   while (i--) *el++ = 0.0;
45   lubksb(el1, mcout.skip);
46}
47
48
49// Do we need check for entirely zero output?
50
51void UpperTriangularMatrix::Solver(MatrixColX& mcout,
52   const MatrixColX& mcin)
53{
54   REPORT
55   int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
56   while (i-- > 0) *elx++ = 0.0;
57   int nr = mcin.skip+mcin.storage;
58   elx = mcin.data+mcin.storage; Real* el = elx;
59   int j = mcout.skip+mcout.storage-nr; int nc = ncols-nr; i = nr-mcout.skip;
60   while (j-- > 0) *elx++ = 0.0;
61   Real* Ael = store + (nr*(2*ncols-nr+1))/2; j = 0;
62   while (i-- > 0)
63   {
64      elx = el; Real sum = 0.0; int jx = j++; Ael -= nc;
65      while (jx--) sum += *(--Ael) * *(--elx);
66      elx--; *elx = (*elx - sum) / *(--Ael);
67   }
68}
69
70void LowerTriangularMatrix::Solver(MatrixColX& mcout,
71   const MatrixColX& mcin)
72{
73   REPORT
74   int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
75   while (i-- > 0) *elx++ = 0.0;
76   int nc = mcin.skip; i = nc+mcin.storage; elx = mcin.data+mcin.storage;
77   int nr = mcout.skip+mcout.storage; int j = nr-i; i = nr-nc;
78   while (j-- > 0) *elx++ = 0.0;
79   Real* el = mcin.data; Real* Ael = store + (nc*(nc+1))/2; j = 0;
80   while (i-- > 0)
81   {
82      elx = el; Real sum = 0.0; int jx = j++; Ael += nc;
83      while (jx--) sum += *Ael++ * *elx++;
84      *elx = (*elx - sum) / *Ael++;
85   }
86}
87
88//******************* carry out binary operations *************************/
89
90static GeneralMatrix*
91   GeneralMult(GeneralMatrix*,GeneralMatrix*,MultipliedMatrix*,MatrixType);
92static GeneralMatrix*
93   GeneralSolv(GeneralMatrix*,GeneralMatrix*,BaseMatrix*,MatrixType);
94static GeneralMatrix*
95   GeneralSolvI(GeneralMatrix*,BaseMatrix*,MatrixType);
96static GeneralMatrix*
97   GeneralKP(GeneralMatrix*,GeneralMatrix*,KPMatrix*,MatrixType);
98
99GeneralMatrix* MultipliedMatrix::Evaluate(MatrixType mt)
100{
101   REPORT
102   gm2 = ((BaseMatrix*&)bm2)->Evaluate();
103   gm2 = gm2->Evaluate(gm2->Type().MultRHS());     // no symmetric on RHS
104   gm1=((BaseMatrix*&)bm1)->Evaluate();
105#ifdef TEMPS_DESTROYED_QUICKLY
106   GeneralMatrix* gmx;
107   Try { gmx = GeneralMult(gm1, gm2, this, mt); }
108   CatchAll { delete this; ReThrow; }
109   delete this; return gmx;
110#else
111   return GeneralMult(gm1, gm2, this, mt);
112#endif
113}
114
115GeneralMatrix* SolvedMatrix::Evaluate(MatrixType mt)
116{
117   REPORT
118   gm1=((BaseMatrix*&)bm1)->Evaluate();
119   gm2=((BaseMatrix*&)bm2)->Evaluate();
120#ifdef TEMPS_DESTROYED_QUICKLY
121   GeneralMatrix* gmx;
122   Try { gmx = GeneralSolv(gm1,gm2,this,mt); }
123   CatchAll { delete this; ReThrow; }
124   delete this; return gmx;
125#else
126   return GeneralSolv(gm1,gm2,this,mt);
127#endif
128}
129
130GeneralMatrix* KPMatrix::Evaluate(MatrixType mt)
131{
132   REPORT
133   gm1=((BaseMatrix*&)bm1)->Evaluate();
134   gm2=((BaseMatrix*&)bm2)->Evaluate();
135#ifdef TEMPS_DESTROYED_QUICKLY
136   GeneralMatrix* gmx;
137   Try { gmx = GeneralKP(gm1,gm2,this,mt); }
138   CatchAll { delete this; ReThrow; }
139   delete this; return gmx;
140#else
141   return GeneralKP(gm1,gm2,this,mt);
142#endif
143}
144
145// routines for adding or subtracting matrices of identical storage structure
146
147static void Add(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
148{
149   REPORT
150   Real* s1=gm1->Store(); Real* s2=gm2->Store();
151   Real* s=gm->Store(); int i=gm->Storage() >> 2;
152   while (i--)
153   {
154       *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++;
155       *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++;
156   }
157   i=gm->Storage() & 3; while (i--) *s++ = *s1++ + *s2++;
158}
159
160static void Add(GeneralMatrix* gm, GeneralMatrix* gm2)
161{
162   REPORT
163   Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
164   while (i--)
165   { *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; }
166   i=gm->Storage() & 3; while (i--) *s++ += *s2++;
167}
168
169static void Subtract(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
170{
171   REPORT
172   Real* s1=gm1->Store(); Real* s2=gm2->Store();
173   Real* s=gm->Store(); int i=gm->Storage() >> 2;
174   while (i--)
175   {
176       *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++;
177       *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++;
178   }
179   i=gm->Storage() & 3; while (i--) *s++ = *s1++ - *s2++;
180}
181
182static void Subtract(GeneralMatrix* gm, GeneralMatrix* gm2)
183{
184   REPORT
185   Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
186   while (i--)
187   { *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; }
188   i=gm->Storage() & 3; while (i--) *s++ -= *s2++;
189}
190
191static void ReverseSubtract(GeneralMatrix* gm, GeneralMatrix* gm2)
192{
193   REPORT
194   Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
195   while (i--)
196   {
197      *s = *s2++ - *s; s++; *s = *s2++ - *s; s++;
198      *s = *s2++ - *s; s++; *s = *s2++ - *s; s++;
199   }
200   i=gm->Storage() & 3; while (i--) { *s = *s2++ - *s; s++; }
201}
202
203static void SP(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
204{
205   REPORT
206   Real* s1=gm1->Store(); Real* s2=gm2->Store();
207   Real* s=gm->Store(); int i=gm->Storage() >> 2;
208   while (i--)
209   {
210       *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++;
211       *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++;
212   }
213   i=gm->Storage() & 3; while (i--) *s++ = *s1++ * *s2++;
214}
215
216static void SP(GeneralMatrix* gm, GeneralMatrix* gm2)
217{
218   REPORT
219   Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
220   while (i--)
221   { *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; }
222   i=gm->Storage() & 3; while (i--) *s++ *= *s2++;
223}
224
225// routines for adding or subtracting matrices of different storage structure
226
227static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
228{
229   REPORT
230   int nr = gm->Nrows();
231   MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
232   MatrixRow mr(gm, StoreOnExit+DirectPart);
233   while (nr--) { mr.Add(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
234}
235
236static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm2)
237// Add into first argument
238{
239   REPORT
240   int nr = gm->Nrows();
241   MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart);
242   MatrixRow mr2(gm2, LoadOnEntry);
243   while (nr--) { mr.Add(mr2); mr.Next(); mr2.Next(); }
244}
245
246static void SubtractDS
247   (GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
248{
249   REPORT
250   int nr = gm->Nrows();
251   MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
252   MatrixRow mr(gm, StoreOnExit+DirectPart);
253   while (nr--) { mr.Sub(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
254}
255
256static void SubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2)
257{
258   REPORT
259   int nr = gm->Nrows();
260   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart);
261   MatrixRow mr2(gm2, LoadOnEntry);
262   while (nr--) { mr.Sub(mr2); mr.Next(); mr2.Next(); }
263}
264
265static void ReverseSubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2)
266{
267   REPORT
268   int nr = gm->Nrows();
269   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart);
270   MatrixRow mr2(gm2, LoadOnEntry);
271   while (nr--) { mr.RevSub(mr2); mr2.Next(); mr.Next(); }
272}
273
274static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
275{
276   REPORT
277   int nr = gm->Nrows();
278   MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
279   MatrixRow mr(gm, StoreOnExit+DirectPart);
280   while (nr--) { mr.Multiply(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
281}
282
283static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm2)
284// SP into first argument
285{
286   REPORT
287   int nr = gm->Nrows();
288   MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart);
289   MatrixRow mr2(gm2, LoadOnEntry);
290   while (nr--) { mr.Multiply(mr2); mr.Next(); mr2.Next(); }
291}
292
293static GeneralMatrix* GeneralMult1(GeneralMatrix* gm1, GeneralMatrix* gm2,
294   MultipliedMatrix* mm, MatrixType mtx)
295{
296   REPORT
297   Tracer tr("GeneralMult1");
298   int nr=gm1->Nrows(); int nc=gm2->Ncols();
299   if (gm1->Ncols() !=gm2->Nrows())
300      Throw(IncompatibleDimensionsException(*gm1, *gm2));
301   GeneralMatrix* gmx = mtx.New(nr,nc,mm);
302
303   MatrixCol mcx(gmx, StoreOnExit+DirectPart);
304   MatrixCol mc2(gm2, LoadOnEntry);
305   while (nc--)
306   {
307      MatrixRow mr1(gm1, LoadOnEntry, mcx.Skip());
308      Real* el = mcx.Data();                         // pointer to an element
309      int n = mcx.Storage();
310      while (n--) { *(el++) = DotProd(mr1,mc2); mr1.Next(); }
311      mc2.Next(); mcx.Next();
312   }
313   gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
314}
315
316static GeneralMatrix* GeneralMult2(GeneralMatrix* gm1, GeneralMatrix* gm2,
317   MultipliedMatrix* mm, MatrixType mtx)
318{
319   // version that accesses by row only - not good for thin matrices
320   // or column vectors in right hand term.
321   REPORT
322   Tracer tr("GeneralMult2");
323   int nr=gm1->Nrows(); int nc=gm2->Ncols();
324   if (gm1->Ncols() !=gm2->Nrows())
325      Throw(IncompatibleDimensionsException(*gm1, *gm2));
326   GeneralMatrix* gmx = mtx.New(nr,nc,mm);
327
328   MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart);
329   MatrixRow mr1(gm1, LoadOnEntry);
330   while (nr--)
331   {
332      MatrixRow mr2(gm2, LoadOnEntry, mr1.Skip());
333      Real* el = mr1.Data();                         // pointer to an element
334      int n = mr1.Storage();
335      mrx.Zero();
336      while (n--) { mrx.AddScaled(mr2, *el++); mr2.Next(); }
337      mr1.Next(); mrx.Next();
338   }
339   gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
340}
341
342static GeneralMatrix* mmMult(GeneralMatrix* gm1, GeneralMatrix* gm2)
343{
344   // matrix multiplication for type Matrix only
345   REPORT
346   Tracer tr("MatrixMult");
347
348   int nr=gm1->Nrows(); int ncr=gm1->Ncols(); int nc=gm2->Ncols();
349   if (ncr != gm2->Nrows()) Throw(IncompatibleDimensionsException(*gm1,*gm2));
350
351   Matrix* gm = new Matrix(nr,nc); MatrixErrorNoSpace(gm);
352
353   Real* s1=gm1->Store(); Real* s2=gm2->Store(); Real* s=gm->Store();
354
355   if (ncr)
356   {
357      while (nr--)
358      {
359         Real* s2x = s2; int j = ncr;
360         Real* sx = s; Real f = *s1++; int k = nc;
361         while (k--) *sx++ = f * *s2x++;
362         while (--j)
363            { sx = s; f = *s1++; k = nc; while (k--) *sx++ += f * *s2x++; }
364         s = sx;
365      }
366   }
367   else *gm = 0.0;
368
369   gm->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gm;
370}
371
372static GeneralMatrix* GeneralMult(GeneralMatrix* gm1, GeneralMatrix* gm2,
373   MultipliedMatrix* mm, MatrixType mtx)
374{
375   if ( Rectangular(gm1->Type(), gm2->Type(), mtx))
376   {
377      REPORT
378      return mmMult(gm1, gm2);
379   }
380   else
381   {
382      REPORT
383      Compare(gm1->Type() * gm2->Type(),mtx);
384      int nr = gm2->Nrows(); int nc = gm2->Ncols();
385      if (nc <= 5 && nr > nc) { REPORT return GeneralMult1(gm1, gm2, mm, mtx); }
386      else { REPORT return GeneralMult2(gm1, gm2, mm, mtx); }
387   }
388}
389
390static GeneralMatrix* GeneralKP(GeneralMatrix* gm1, GeneralMatrix* gm2,
391   KPMatrix* kp, MatrixType mtx)
392{
393   REPORT
394   Tracer tr("GeneralKP");
395   int nr1 = gm1->Nrows(); int nc1 = gm1->Ncols();
396   int nr2 = gm2->Nrows(); int nc2 = gm2->Ncols();
397   Compare((gm1->Type()).KP(gm2->Type()),mtx);
398   GeneralMatrix* gmx = mtx.New(nr1*nr2, nc1*nc2, kp);
399   MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart);
400   MatrixRow mr1(gm1, LoadOnEntry);
401   for (int i = 1; i <= nr1; ++i)
402   {
403      MatrixRow mr2(gm2, LoadOnEntry);
404      for (int j = 1; j <= nr2; ++j)
405         { mrx.KP(mr1,mr2); mr2.Next(); mrx.Next(); }
406      mr1.Next();
407   }
408   gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
409}
410
411static GeneralMatrix* GeneralSolv(GeneralMatrix* gm1, GeneralMatrix* gm2,
412   BaseMatrix* sm, MatrixType mtx)
413{
414   REPORT
415   Tracer tr("GeneralSolv");
416   Compare(gm1->Type().i() * gm2->Type(),mtx);
417   int nr = gm1->Nrows();
418   if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1));
419   int nc = gm2->Ncols();
420   if (gm1->Ncols() != gm2->Nrows())
421      Throw(IncompatibleDimensionsException(*gm1, *gm2));
422   GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx);
423   Real* r = new Real [nr]; MatrixErrorNoSpace(r);
424   MONITOR_REAL_NEW("Make   (GenSolv)",nr,r)
425   GeneralMatrix* gms = gm1->MakeSolver();
426   Try
427   {
428
429      MatrixColX mcx(gmx, r, StoreOnExit+DirectPart);   // copy to and from r
430         // this must be inside Try so mcx is destroyed before gmx
431      MatrixColX mc2(gm2, r, LoadOnEntry);
432      while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); }
433   }
434   CatchAll
435   {
436      if (gms) gms->tDelete();
437      delete gmx;                   // <--------------------
438      gm2->tDelete();
439      MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
440                          // ATandT version 2.1 gives an internal error
441      delete [] r;
442      ReThrow;
443   }
444   gms->tDelete(); gmx->ReleaseAndDelete(); gm2->tDelete();
445   MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
446                          // ATandT version 2.1 gives an internal error
447   delete [] r;
448   return gmx;
449}
450
451// version for inverses - gm2 is identity
452static GeneralMatrix* GeneralSolvI(GeneralMatrix* gm1, BaseMatrix* sm,
453   MatrixType mtx)
454{
455   REPORT
456   Tracer tr("GeneralSolvI");
457   Compare(gm1->Type().i(),mtx);
458   int nr = gm1->Nrows();
459   if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1));
460   int nc = nr;
461   // DiagonalMatrix I(nr); I = 1;
462   IdentityMatrix I(nr);
463   GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx);
464   Real* r = new Real [nr]; MatrixErrorNoSpace(r);
465   MONITOR_REAL_NEW("Make   (GenSolvI)",nr,r)
466   GeneralMatrix* gms = gm1->MakeSolver();
467   Try
468   {
469
470      MatrixColX mcx(gmx, r, StoreOnExit+DirectPart);   // copy to and from r
471         // this must be inside Try so mcx is destroyed before gmx
472      MatrixColX mc2(&I, r, LoadOnEntry);
473      while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); }
474   }
475   CatchAll
476   {
477      if (gms) gms->tDelete();
478      delete gmx;
479      MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r)
480                          // ATandT version 2.1 gives an internal error
481      delete [] r;
482      ReThrow;
483   }
484   gms->tDelete(); gmx->ReleaseAndDelete();
485   MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r)
486                          // ATandT version 2.1 gives an internal error
487   delete [] r;
488   return gmx;
489}
490
491GeneralMatrix* InvertedMatrix::Evaluate(MatrixType mtx)
492{
493   // Matrix Inversion - use solve routines
494   Tracer tr("InvertedMatrix::Evaluate");
495   REPORT
496   gm=((BaseMatrix*&)bm)->Evaluate();
497#ifdef TEMPS_DESTROYED_QUICKLY
498        GeneralMatrix* gmx;
499        Try { gmx = GeneralSolvI(gm,this,mtx); }
500   CatchAll { delete this; ReThrow; }
501   delete this; return gmx;
502#else
503   return GeneralSolvI(gm,this,mtx);
504#endif
505}
506
507//*************************** New versions ************************
508
509GeneralMatrix* AddedMatrix::Evaluate(MatrixType mtd)
510{
511   REPORT
512   Tracer tr("AddedMatrix::Evaluate");
513   gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
514   int nr=gm1->Nrows(); int nc=gm1->Ncols();
515   if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
516   {
517      Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
518      CatchAll
519      {
520         gm1->tDelete(); gm2->tDelete();
521#ifdef TEMPS_DESTROYED_QUICKLY
522         delete this;
523#endif
524         ReThrow;
525      }
526   }
527   MatrixType mt1 = gm1->Type(), mt2 = gm2->Type(); MatrixType mts = mt1 + mt2;
528   if (!mtd) { REPORT mtd = mts; }
529   else if (!(mtd.DataLossOK || mtd >= mts))
530   {
531      REPORT
532      gm1->tDelete(); gm2->tDelete();
533#ifdef TEMPS_DESTROYED_QUICKLY
534      delete this;
535#endif
536      Throw(ProgramException("Illegal Conversion", mts, mtd));
537   }
538   GeneralMatrix* gmx;
539   bool c1 = (mtd == mt1), c2 = (mtd == mt2);
540   if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
541   {
542      if (gm1->reuse()) { REPORT Add(gm1,gm2); gm2->tDelete(); gmx = gm1; }
543      else if (gm2->reuse()) { REPORT Add(gm2,gm1); gmx = gm2; }
544      else
545      {
546         REPORT
547         // what if new throws an exception
548         Try { gmx = mt1.New(nr,nc,this); }
549         CatchAll
550         {
551#ifdef TEMPS_DESTROYED_QUICKLY
552            delete this;
553#endif
554            ReThrow;
555         }
556         gmx->ReleaseAndDelete(); Add(gmx,gm1,gm2);
557      }
558   }
559   else
560   {
561      if (c1 && c2)
562      {
563         short SAO = gm1->SimpleAddOK(gm2);
564         if (SAO & 1) { REPORT c1 = false; }
565         if (SAO & 2) { REPORT c2 = false; }
566      }
567      if (c1 && gm1->reuse() )               // must have type test first
568         { REPORT AddDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
569      else if (c2 && gm2->reuse() )
570         { REPORT AddDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; }
571      else
572      {
573         REPORT
574         Try { gmx = mtd.New(nr,nc,this); }
575         CatchAll
576         {
577            if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
578#ifdef TEMPS_DESTROYED_QUICKLY
579            delete this;
580#endif
581            ReThrow;
582         }
583         AddDS(gmx,gm1,gm2);
584         if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
585         gmx->ReleaseAndDelete();
586      }
587   }
588#ifdef TEMPS_DESTROYED_QUICKLY
589   delete this;
590#endif
591   return gmx;
592}
593
594GeneralMatrix* SubtractedMatrix::Evaluate(MatrixType mtd)
595{
596   REPORT
597   Tracer tr("SubtractedMatrix::Evaluate");
598   gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
599   int nr=gm1->Nrows(); int nc=gm1->Ncols();
600   if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
601   {
602      Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
603      CatchAll
604      {
605         gm1->tDelete(); gm2->tDelete();
606#ifdef TEMPS_DESTROYED_QUICKLY
607         delete this;
608#endif
609         ReThrow;
610      }
611   }
612   MatrixType mt1 = gm1->Type(), mt2 = gm2->Type(); MatrixType mts = mt1 + mt2;
613   if (!mtd) { REPORT mtd = mts; }
614   else if (!(mtd.DataLossOK || mtd >= mts))
615   {
616      gm1->tDelete(); gm2->tDelete();
617#ifdef TEMPS_DESTROYED_QUICKLY
618      delete this;
619#endif
620      Throw(ProgramException("Illegal Conversion", mts, mtd));
621   }
622   GeneralMatrix* gmx;
623   bool c1 = (mtd == mt1), c2 = (mtd == mt2);
624   if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
625   {
626      if (gm1->reuse()) { REPORT Subtract(gm1,gm2); gm2->tDelete(); gmx = gm1; }
627      else if (gm2->reuse()) { REPORT ReverseSubtract(gm2,gm1); gmx = gm2; }
628      else
629      {
630         REPORT
631         Try { gmx = mt1.New(nr,nc,this); }
632         CatchAll
633         {
634#ifdef TEMPS_DESTROYED_QUICKLY
635            delete this;
636#endif
637            ReThrow;
638         }
639         gmx->ReleaseAndDelete(); Subtract(gmx,gm1,gm2);
640      }
641   }
642   else
643   {
644      if (c1 && c2)
645      {
646         short SAO = gm1->SimpleAddOK(gm2);
647         if (SAO & 1) { REPORT c1 = false; }
648         if (SAO & 2) { REPORT c2 = false; }
649      }
650      if (c1 && gm1->reuse() )               // must have type test first
651         { REPORT SubtractDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
652      else if (c2 && gm2->reuse() )
653      {
654         REPORT ReverseSubtractDS(gm2,gm1);
655         if (!c1) gm1->tDelete(); gmx = gm2;
656      }
657      else
658      {
659         REPORT
660         // what if New throws and exception
661         Try { gmx = mtd.New(nr,nc,this); }
662         CatchAll
663         {
664            if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
665#ifdef TEMPS_DESTROYED_QUICKLY
666            delete this;
667#endif
668            ReThrow;
669         }
670         SubtractDS(gmx,gm1,gm2);
671         if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
672         gmx->ReleaseAndDelete();
673      }
674   }
675#ifdef TEMPS_DESTROYED_QUICKLY
676   delete this;
677#endif
678   return gmx;
679}
680
681GeneralMatrix* SPMatrix::Evaluate(MatrixType mtd)
682{
683   REPORT
684   Tracer tr("SPMatrix::Evaluate");
685   gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
686   int nr=gm1->Nrows(); int nc=gm1->Ncols();
687   if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
688   {
689      Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
690      CatchAll
691      {
692         gm1->tDelete(); gm2->tDelete();
693#ifdef TEMPS_DESTROYED_QUICKLY
694         delete this;
695#endif
696         ReThrow;
697      }
698   }
699   MatrixType mt1 = gm1->Type(), mt2 = gm2->Type();
700   MatrixType mts = mt1.SP(mt2);
701   if (!mtd) { REPORT mtd = mts; }
702   else if (!(mtd.DataLossOK || mtd >= mts))
703   {
704      gm1->tDelete(); gm2->tDelete();
705#ifdef TEMPS_DESTROYED_QUICKLY
706      delete this;
707#endif
708      Throw(ProgramException("Illegal Conversion", mts, mtd));
709   }
710   GeneralMatrix* gmx;
711   bool c1 = (mtd == mt1), c2 = (mtd == mt2);
712   if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
713   {
714      if (gm1->reuse()) { REPORT SP(gm1,gm2); gm2->tDelete(); gmx = gm1; }
715      else if (gm2->reuse()) { REPORT SP(gm2,gm1); gmx = gm2; }
716      else
717      {
718         REPORT
719         Try { gmx = mt1.New(nr,nc,this); }
720         CatchAll
721         {
722#ifdef TEMPS_DESTROYED_QUICKLY
723            delete this;
724#endif
725            ReThrow;
726         }
727         gmx->ReleaseAndDelete(); SP(gmx,gm1,gm2);
728      }
729   }
730   else
731   {
732      if (c1 && c2)
733      {
734         short SAO = gm1->SimpleAddOK(gm2);
735         if (SAO & 1) { REPORT c2 = false; }    // c1 and c2 swapped
736         if (SAO & 2) { REPORT c1 = false; }
737      }
738      if (c1 && gm1->reuse() )               // must have type test first
739         { REPORT SPDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
740      else if (c2 && gm2->reuse() )
741         { REPORT SPDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; }
742      else
743      {
744         REPORT
745         // what if New throws and exception
746         Try { gmx = mtd.New(nr,nc,this); }
747         CatchAll
748         {
749            if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
750#ifdef TEMPS_DESTROYED_QUICKLY
751            delete this;
752#endif
753            ReThrow;
754         }
755         SPDS(gmx,gm1,gm2);
756         if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
757         gmx->ReleaseAndDelete();
758      }
759   }
760#ifdef TEMPS_DESTROYED_QUICKLY
761   delete this;
762#endif
763   return gmx;
764}
765
766
767
768//*************************** norm functions ****************************/
769
770Real BaseMatrix::Norm1() const
771{
772   // maximum of sum of absolute values of a column
773   REPORT
774   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
775   int nc = gm->Ncols(); Real value = 0.0;
776   MatrixCol mc(gm, LoadOnEntry);
777   while (nc--)
778      { Real v = mc.SumAbsoluteValue(); if (value < v) value = v; mc.Next(); }
779   gm->tDelete(); return value;
780}
781
782Real BaseMatrix::NormInfinity() const
783{
784   // maximum of sum of absolute values of a row
785   REPORT
786   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
787   int nr = gm->Nrows(); Real value = 0.0;
788   MatrixRow mr(gm, LoadOnEntry);
789   while (nr--)
790      { Real v = mr.SumAbsoluteValue(); if (value < v) value = v; mr.Next(); }
791   gm->tDelete(); return value;
792}
793
794//********************** Concatenation and stacking *************************/
795
796GeneralMatrix* ConcatenatedMatrix::Evaluate(MatrixType mtx)
797{
798   REPORT
799   Tracer tr("Concatenate");
800#ifdef TEMPS_DESTROYED_QUICKLY
801      Try
802      {
803         gm2 = ((BaseMatrix*&)bm2)->Evaluate();
804         gm1 = ((BaseMatrix*&)bm1)->Evaluate();
805         Compare(gm1->Type() | gm2->Type(),mtx);
806         int nr=gm1->Nrows(); int nc = gm1->Ncols() + gm2->Ncols();
807         if (nr != gm2->Nrows())
808            Throw(IncompatibleDimensionsException(*gm1, *gm2));
809         GeneralMatrix* gmx = mtx.New(nr,nc,this);
810         MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
811         MatrixRow mr(gmx, StoreOnExit+DirectPart);
812         while (nr--) { mr.ConCat(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
813         gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); delete this;
814         return gmx;
815      }
816      CatchAll  { delete this; ReThrow; }
817#ifndef UseExceptions
818      return 0;
819#endif
820#else
821      gm2 = ((BaseMatrix*&)bm2)->Evaluate();
822      gm1 = ((BaseMatrix*&)bm1)->Evaluate();
823      Compare(gm1->Type() | gm2->Type(),mtx);
824      int nr=gm1->Nrows(); int nc = gm1->Ncols() + gm2->Ncols();
825      if (nr != gm2->Nrows())
826         Throw(IncompatibleDimensionsException(*gm1, *gm2));
827      GeneralMatrix* gmx = mtx.New(nr,nc,this);
828      MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
829      MatrixRow mr(gmx, StoreOnExit+DirectPart);
830      while (nr--) { mr.ConCat(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
831      gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
832#endif
833}
834
835GeneralMatrix* StackedMatrix::Evaluate(MatrixType mtx)
836{
837   REPORT
838   Tracer tr("Stack");
839#ifdef TEMPS_DESTROYED_QUICKLY
840      Try
841      {
842         gm2 = ((BaseMatrix*&)bm2)->Evaluate();
843         gm1 = ((BaseMatrix*&)bm1)->Evaluate();
844         Compare(gm1->Type() & gm2->Type(),mtx);
845         int nc=gm1->Ncols();
846         int nr1 = gm1->Nrows(); int nr2 = gm2->Nrows();
847         if (nc != gm2->Ncols())
848            Throw(IncompatibleDimensionsException(*gm1, *gm2));
849         GeneralMatrix* gmx = mtx.New(nr1+nr2,nc,this);
850         MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
851         MatrixRow mr(gmx, StoreOnExit+DirectPart);
852         while (nr1--) { mr.Copy(mr1); mr1.Next(); mr.Next(); }
853         while (nr2--) { mr.Copy(mr2); mr2.Next(); mr.Next(); }
854         gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); delete this;
855         return gmx;
856      }
857      CatchAll  { delete this; ReThrow; }
858#ifndef UseExceptions
859      return 0;
860#endif
861#else
862      gm2 = ((BaseMatrix*&)bm2)->Evaluate();
863      gm1 = ((BaseMatrix*&)bm1)->Evaluate();
864      Compare(gm1->Type() & gm2->Type(),mtx);
865      int nc=gm1->Ncols();
866      int nr1 = gm1->Nrows(); int nr2 = gm2->Nrows();
867      if (nc != gm2->Ncols())
868         Throw(IncompatibleDimensionsException(*gm1, *gm2));
869      GeneralMatrix* gmx = mtx.New(nr1+nr2,nc,this);
870      MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
871      MatrixRow mr(gmx, StoreOnExit+DirectPart);
872      while (nr1--) { mr.Copy(mr1); mr1.Next(); mr.Next(); }
873      while (nr2--) { mr.Copy(mr2); mr2.Next(); mr.Next(); }
874      gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
875#endif
876}
877
878// ************************* equality of matrices ******************** //
879
880static bool RealEqual(Real* s1, Real* s2, int n)
881{
882   int i = n >> 2;
883   while (i--)
884   {
885      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
886      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
887   }
888   i = n & 3; while (i--) if (*s1++ != *s2++) return false;
889   return true;
890}
891
892static bool intEqual(int* s1, int* s2, int n)
893{
894   int i = n >> 2;
895   while (i--)
896   {
897      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
898      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
899   }
900   i = n & 3; while (i--) if (*s1++ != *s2++) return false;
901   return true;
902}
903
904
905bool operator==(const BaseMatrix& A, const BaseMatrix& B)
906{
907   Tracer tr("BaseMatrix ==");
908   REPORT
909   GeneralMatrix* gmA = ((BaseMatrix&)A).Evaluate();
910   GeneralMatrix* gmB = ((BaseMatrix&)B).Evaluate();
911
912   if (gmA == gmB)                            // same matrix
913      { REPORT gmA->tDelete(); return true; }
914
915   if ( gmA->Nrows() != gmB->Nrows() || gmA->Ncols() != gmB->Ncols() )
916                                              // different dimensions
917      { REPORT gmA->tDelete(); gmB->tDelete(); return false; }
918
919   // check for CroutMatrix or BandLUMatrix
920   MatrixType AType = gmA->Type(); MatrixType BType = gmB->Type();
921   if (AType.CannotConvert() || BType.CannotConvert() )
922   {
923      REPORT
924      bool bx = gmA->IsEqual(*gmB);
925      gmA->tDelete(); gmB->tDelete();
926      return bx;
927   }
928
929   // is matrix storage the same
930   // will need to modify if further matrix structures are introduced
931   if (AType == BType && gmA->BandWidth() == gmB->BandWidth())
932   {                                          // compare store
933      REPORT
934      bool bx = RealEqual(gmA->Store(),gmB->Store(),gmA->Storage());
935      gmA->tDelete(); gmB->tDelete();
936      return bx;
937   }
938
939   // matrix storage different - just subtract
940   REPORT  return IsZero(*gmA-*gmB);
941}
942
943bool operator==(const GeneralMatrix& A, const GeneralMatrix& B)
944{
945   Tracer tr("GeneralMatrix ==");
946   // May or may not call tDeletes
947   REPORT
948
949   if (&A == &B)                              // same matrix
950      { REPORT return true; }
951
952   if ( A.Nrows() != B.Nrows() || A.Ncols() != B.Ncols() )
953      { REPORT return false; }                // different dimensions
954
955   // check for CroutMatrix or BandLUMatrix
956   MatrixType AType = A.Type(); MatrixType BType = B.Type();
957   if (AType.CannotConvert() || BType.CannotConvert() )
958      { REPORT  return A.IsEqual(B); }
959
960   // is matrix storage the same
961   // will need to modify if further matrix structures are introduced
962   if (AType == BType && A.BandWidth() == B.BandWidth())
963      { REPORT return RealEqual(A.Store(),B.Store(),A.Storage()); }
964
965   // matrix storage different - just subtract
966   REPORT  return IsZero(A-B);
967}
968
969bool GeneralMatrix::IsZero() const
970{
971   REPORT
972   Real* s=store; int i = storage >> 2;
973   while (i--)
974   {
975      if (*s++) return false; if (*s++) return false;
976      if (*s++) return false; if (*s++) return false;
977   }
978   i = storage & 3; while (i--) if (*s++) return false;
979   return true;
980}
981
982bool IsZero(const BaseMatrix& A)
983{
984   Tracer tr("BaseMatrix::IsZero");
985   REPORT
986   GeneralMatrix* gm1 = 0; bool bx;
987   Try { gm1=((BaseMatrix&)A).Evaluate(); bx = gm1->IsZero(); }
988   CatchAll { if (gm1) gm1->tDelete(); ReThrow; }
989   gm1->tDelete();
990   return bx;
991}
992
993// IsEqual functions - insist matrices are of same type
994// as well as equal values to be equal
995
996bool GeneralMatrix::IsEqual(const GeneralMatrix& A) const
997{
998   Tracer tr("GeneralMatrix IsEqual");
999   if (A.Type() != Type())                       // not same types
1000      { REPORT return false; }
1001   if (&A == this)                               // same matrix
1002      { REPORT  return true; }
1003   if (A.nrows != nrows || A.ncols != ncols)
1004                                                 // different dimensions
1005   { REPORT return false; }
1006   // is matrix storage the same - compare store
1007   REPORT
1008   return RealEqual(A.store,store,storage);
1009}
1010
1011bool CroutMatrix::IsEqual(const GeneralMatrix& A) const
1012{
1013   Tracer tr("CroutMatrix IsEqual");
1014   if (A.Type() != Type())                       // not same types
1015      { REPORT return false; }
1016   if (&A == this)                               // same matrix
1017      { REPORT  return true; }
1018   if (A.nrows != nrows || A.ncols != ncols)
1019                                                 // different dimensions
1020   { REPORT return false; }
1021   // is matrix storage the same - compare store
1022   REPORT
1023   return RealEqual(A.store,store,storage)
1024      && intEqual(((CroutMatrix&)A).indx, indx, nrows);
1025}
1026
1027
1028bool BandLUMatrix::IsEqual(const GeneralMatrix& A) const
1029{
1030   Tracer tr("BandLUMatrix IsEqual");
1031   if (A.Type() != Type())                       // not same types
1032      { REPORT  return false; }
1033   if (&A == this)                               // same matrix
1034      { REPORT  return true; }
1035   if ( A.Nrows() != nrows || A.Ncols() != ncols
1036      || ((BandLUMatrix&)A).m1 != m1 || ((BandLUMatrix&)A).m2 != m2 )
1037                                                 // different dimensions
1038   { REPORT  return false; }
1039
1040   // matrix storage the same - compare store
1041   REPORT
1042   return RealEqual(A.Store(),store,storage)
1043      && RealEqual(((BandLUMatrix&)A).store2,store2,storage2)
1044      && intEqual(((BandLUMatrix&)A).indx, indx, nrows);
1045}
1046
1047
1048#ifdef use_namespace
1049}
1050#endif
1051
1052
Note: See TracBrowser for help on using the repository browser.