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