openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
FMatrix.cc
Go to the documentation of this file.
1 #include "FMatrix.h"
2 
3 
11 {
12  for ( int i = 0; i < mxNRows; i++ )
13  free( Ent[i] );
14  free(Ent);
15  if (decomposed) {
16  free(base1);
17  free(++(indx));
18  }
19 }
20 
27 void
29 {
30  for (int i = 0; i < mxNRows; i++ )
31  memset( Ent[i], 0, mxNCols * sizeof(Real) );
32  decomposed = false;
33 }
34 
35 
47 FMatrix&
49 {
50  // make sure B is large enough to accomodate A
51  if ((mxNRows < A.NRows) || (mxNCols < A.NCols))
52  A.resize(NRows, NCols);
53 
54  A.NCols = NCols;
55  A.NRows = NRows;
56  A.lsize = lsize;
57 
58  for (int i = 0; i < NRows; i++)
59  memcpy(Ent[i], A.Ent[i], sizeof(Ent[i][0])*NCols);
60  return *this;
61 }
62 
63 
72 void
73 FMatrix::resize( int nr, int nc )
74 {
75  if ( nr > mxNRows || nc > mxNCols )
76  {
77  Ent = (Real **)realloc(Ent,nr*sizeof(Real*));
78  for( int i=0; i<nc; i++ )
79  Ent[i] = (Real*)realloc(Ent[i], nc*sizeof(Real));
80  }
81  NRows = nr;
82  NCols = nc;
83  if( decomposed ) {
84  free( base1 );
85  free( ++indx );
86  base1 = NULL;
87  indx = NULL;
88  }
89  Zero();
90 }
91 
92 
94 {
95  if (A->NCols != B->NRows || C->NRows != A->NRows || C-> NCols != B->NCols ||
96  !A->NCols || !A->NRows || !B->NCols)
97  {
98  fprintf(stderr, "\nDimension compatibility error in %s()\n", __func__);
99  fprintf(stderr, "A->NRows=%d; A->NCols=%d\n"
100  "B->NRows=%d; B->NCols=%d\n"
101  "C->NRows=%d; C->NCols=%d\n\n",
102  A->NRows, A->NCols, B->NRows, B->NCols, C->NRows, C->NCols);
103  exit (1);
104  }
105 
106  for (int i = 0; i < A->NRows; i++)
107  {
108  for (int j = 0; j < B->NCols; j++)
109  {
110  C->Ent[i][j] = A->Ent[i][0] * B->Ent[0][j];
111  for (int k = 1; k < A->NCols; k++)
112  {
113  C->Ent[i][j] += A->Ent[i][k] * B->Ent[k][j];
114  }
115  }
116  }
117 }
118 
120 {
121  if (A->NCols != B->NRows || !A->NCols || !A->NRows || !B->NCols)
122  {
123  fprintf(stderr, "\nDimension compatibility error in %s()\n", __func__);
124  fprintf(stderr, "A->NRows=%d; A->NCols=%d\n"
125  "B->NRows=%d; B->NCols=%d\n",
126  A->NRows, A->NCols, B->NRows, B->NCols);
127  exit (1);
128  }
129 
130  for (int i = 0; i < A->NRows; i++)
131  {
132  for (int j = 0; j < B->NCols; j++)
133  {
134  C[A->NRows * i + j] = A->Ent[i][0] * B->Ent[0][j];
135  for (int k = 1; k < A->NCols; k++)
136  {
137  C[A->NRows * i + j] += A->Ent[i][k] * B->Ent[k][j];
138  }
139  }
140  }
141 }
142 
144 {
145  if (A->NRows != B->NRows || C->NRows != A->NCols || C-> NCols != B->NCols ||
146  !A->NRows || !A->NCols || !B->NCols)
147  {
148  fprintf(stderr, "\nDimension compatibility error in %s()\n", __func__);
149  fprintf(stderr, "A->NRows=%d; A->NCols=%d\n"
150  "B->NRows=%d; B->NCols=%d\n"
151  "C->NRows=%d; C->NCols=%d\n\n",
152  A->NCols, A->NRows, B->NRows, B->NCols, C->NRows, C->NCols);
153  exit (1);
154  }
155 
156  for (int i = 0; i < A->NCols; i++)
157  {
158  for (int j = 0; j < B->NCols; j++)
159  {
160  C->Ent[i][j] = A->Ent[0][i] * B->Ent[0][j];
161  for (int k = 1; k < A->NRows; k++)
162  {
163  C->Ent[i][j] += A->Ent[k][i] * B->Ent[k][j];
164  }
165  }
166  }
167 }
168 
170 {
171  if (A->NCols != B->NCols || C->NRows != A->NRows || C-> NCols != B->NRows ||
172  !A->NCols || !A->NRows || !B->NRows)
173  {
174  fprintf(stderr, "\nDimension compatibility error in %s()\n", __func__);
175  fprintf(stderr, "A->NRows=%d; A->NCols=%d\n"
176  "B->NCols=%d; B->NRows=%d\n"
177  "C->NRows=%d; C->NCols=%d\n\n",
178  A->NRows, A->NCols, B->NCols, B->NRows, C->NRows, C->NCols);
179  exit (1);
180  }
181 
182  for (int i = 0; i < A->NRows; i++)
183  {
184  for (int j = 0; j < B->NRows; j++)
185  {
186  C->Ent[i][j] = A->Ent[i][0] * B->Ent[j][0];
187  for (int k = 1; k < A->NCols; k++)
188  {
189  C->Ent[i][j] += A->Ent[i][k] * B->Ent[j][k];
190  }
191  }
192  }
193 }
194 
197 {
198  if ( A->NCols != B->NCols || A->NRows != B->NRows || C->NRows != A->NRows || C->NCols != A->NCols)
199  {
200  fprintf(stderr, "\nDimension compatibility error in %s()\n", __func__);
201  fprintf(stderr, "A->NRows=%d; A->NCols=%d\n"
202  "B->NRows=%d; B->NCols=%d\n"
203  "C->NRows=%d; C->NCols=%d\n\n",
204  A->NRows, A->NCols, B->NRows, B->NCols, C->NRows, C->NCols);
205  exit (1);
206  }
207 
208  for (int i = 0; i < A->NRows; i++)
209  {
210  for (int j = 0; j < B->NCols; j++)
211  {
212  C->Ent[i][j] = A->Ent[i][j] + B->Ent[i][j];
213  }
214  }
215 }
216 
217 
218 
226 void
228 {
229  for (int i = 0; i < A->NRows; i++)
230  for (int j = 0; j < A->NCols; j++)
231  A->Ent[i][j] *= a;
232 }
233 
236 {
237 
238  Real det = 0;
239 
240  if (M->NRows != M->NCols)
241  {
242  fprintf(stderr, "\nError in %s(); M.NRows != M.NCols\n", __func__ );
243  exit(1);
244  }
245 
246  switch (M->NRows)
247  {
248  case 2:
249  det = M->Ent[0][0] * M->Ent[1][1] - M->Ent[0][1] * M->Ent[1][0];
250  break;
251  case 3:
252  for (int i = 0; i < M->NRows; i++)
253  {
254  Real temp = M->Ent[1][(1 + i) % M->NRows] * M->Ent[2][(2 + i) % M->NRows];
255  temp -= M->Ent[2][(1 + i) % M->NRows] * M->Ent[1][(2 + i) % M->NRows];
256  det += temp * M->Ent[0][i];
257  }
258  break;
259  case 4:
260  {
261  FMatrix tempM(M->NRows - 1, M->NCols - 1);
262  for (int i = 0; i < M->NRows; i++)
263  {
264  int j, m;
265  for ( j = 0, m = 0; j < M->NRows; j++, m++)
266  {
267  if (j == i) j++;
268  int n = 0;
269  for (int k = 1; k < M->NCols; k++, n++)
270  {
271  if (m < tempM.NRows)
272  {
273  tempM.Ent[m][n] = M->Ent[j][k];
274  }
275  }
276  }
277  det += (i % 2 ? -1.0 : 1.0) * M->Ent[i][0] * FMatrix_Det(&tempM);
278  }
279  }
280  break;
281  default:
282  fprintf(stderr, "\nError in Det routine; M.NRows must = 2,3, or 4...\n"
283  "The 4 case should be general enough for all matrices\n"
284  "of size>4 but should be checked; M.NRows=%d\n", M->NRows);
285  exit (1);
286  }
287  return det;
288 }
289 
290 
293 {
294 
295  Real trace = 0;
296 
297  if (M->NRows != M->NCols)
298  {
299  fprintf(stderr, "\nError in %s(); M.NRows != M.NCols\n", __func__ );
300  exit(1);
301  }
302 
303  for (int i = 0; i < M->NRows; i++)
304  trace += M->Ent[i][i];
305 
306  return trace;
307 }
308 
309 
319 void
321 {
322  if ( NCols != NRows )
323  {
324  fprintf( stderr, "%s(): Unable to decompose nonsquare matrix\n", __func__ );
325  exit(1);
326  }
327  if ( base1 == NULL )
328  {
329  base1 = (Real**) malloc((1 + mxNRows) * sizeof(Real*));
330  for ( int i = 0; i < mxNRows; i++ )
331  base1[i + 1] = Ent[i] - 1;
332  indx = (int *)malloc(mxNRows * sizeof(int));
333  indx--;
334  }
335  Real d;
336  decomposed = ludcmp( base1, NRows, indx, &d );
337  if( !decomposed )
338  return;
339  for ( int i = 0; i < NRows; i++ )
340  Ent[i] = base1[i + 1] + 1; // LU decomposition swaps rows
341  decomposed = true;
342 }
343 
344 
354 void
356 {
357  if ( !decomposed )
358  {
359  fprintf( stderr, "%s(): Trying to solve undecomposed matrix\n", __func__ );
360  exit(1);
361  }
362  lubksb( base1 , NRows, indx, rhs - 1 );
363 }
364 
365 
375 FMatrix *
377 {
378  FMatrix *A_inv = new FMatrix( NRows, NRows );
379 
380  Real *soln = (Real *)malloc(sizeof(Real) * NRows);
381 
382  LUD();
383  for ( int i = 0; i <NRows; i++ )
384  {
385  for ( int j = 0; j < NRows; j++ )
386  soln[j] = j == i;
387  LUsolve( soln );
388  for ( int j = 0; j < NRows; j++ )
389  A_inv->Ent[j][i] = soln[j];
390  }
391  free(soln);
392 
393  return A_inv;
394 }
395 
396 
406 FMatrix *
408 {
409  // Buffer original matrix A
410  FMatrix A_(mxNRows, mxNCols);
411  A_ = *this;
412  FMatrix *A_inv = new FMatrix( NRows, NRows );
413 
414  Real *soln = (Real *)malloc(sizeof(Real) * NRows);
415 
416  A_.LUD( );
417  for ( int i = 0; i < A_.NRows; i++ )
418  {
419  for ( int j = 0; j < A_.NRows; j++ )
420  soln[j] = j == i;
421  A_.LUsolve( soln );
422  for ( int j = 0; j < A_.NRows; j++ )
423  A_inv->Ent[j][i] = soln[j];
424  }
425 
426  free(soln);
427 
428  return A_inv;
429 }
430 
431 
442 FMatrix *
444 {
445  FMatrix *A_t;
446  if (!ip )
447  {
448  A_t = new FMatrix( NCols, NRows );
449  for ( int i = 0; i < NRows; i++ )
450  for ( int j = 0; j < NCols; j++ )
451  A_t->Ent[j][i] = Ent[i][j];
452  return A_t;
453  }
454  else
455  {
456  // in-place
457  for ( int i = 0; i < NRows; i++ )
458  {
459  for ( int j = i + 1; j < NRows; j++ )
460  {
461  Real tmp = Ent[j][i];
462  Ent[j][i] = Ent[i][j];
463  Ent[i][j] = tmp;
464  }
465  }
466  return this;
467  }
468 }
469 
478 FMatrix *FM_Rotate(FMatrix *R, double angle, int ax)
479 {
480  double sin_th = sin(angle);
481  double cos_th = cos(angle);
482 
483  static const int p[3][2] = { {1, 2},
484  {0, 2},
485  {0, 1}
486  };
487  const int *a = p[ax];
488  R->Zero();
489 
490 
491  R->Ent[a[0]][a[0]] = cos_th;
492  R->Ent[a[0]][a[1]] = sin_th;
493  R->Ent[a[1]][a[0]] = -sin_th;
494  R->Ent[a[1]][a[1]] = cos_th;
495  R->Ent[ax][ax] = 1.;
496 
497  return R;
498 }
499 
508 Real* FM_X_Vec( FMatrix *A, Real *b, Real *c )
509 {
510  if ( !c ) c = (Real*) calloc(A->NRows, sizeof(Real));
511 
512  for ( int i = 0; i < A->NRows; i++ )
513  {
514  c[i] = A->Ent[i][0] * b[0];
515  for ( int j = 1; j < A->NCols; j++ )
516  c[i] += A->Ent[i][j] * b[j];
517  }
518  return c;
519 }
520 
521 
522 void FM_Times_Vec(Real dx, FMatrix *B, Real*C, Real *result)
523 {
524  const int BRows = B->NRows;
525  const int BCols = B->NCols;
526  if (BCols == 6)
527  {
528 
529  // read C in register variables since it will stay constant for the whole computation
530  Real c1 = C[0], c2 = C[1], c3 = C[2], c4 = C[3], c5 = C[4], c6 = C[5];
531 
532  for (int k = 0; k < BRows; k++)
533  result[k] += (c1 * B->Ent[k][0] + c2 * B->Ent[k][1] + c3 * B->Ent[k][2] + c4 * B->Ent[k][3] + c5 * B->Ent[k][4] + c6 * B->Ent[k][5]) * dx;
534  }
535  else // general algorithm
536  {
537  for (int k = 0; k < BRows; k++)
538  for (int j = 0; j < BCols; j++)
539  result[k] += B->Ent[k][j] * C[j] * dx;
540  }
541 }
542 
543 void B_C_BTrans(Real dx, FMatrix *B, Real *C, FMatrix *result)
544 {
545  const int BRows = B->NRows;
546  const int BCols = B->NCols;
547 
548  const int RRows = result->NRows;
549  const int RCols = result->NCols;
550 
551  // C and result have to be quadratic
552  if ( RRows != RCols || RRows != BRows || !BRows || !BCols)
553  {
554  fprintf(stderr, "\nDimension compatibility error in %s()\n", __func__);
555  fprintf(stderr, "B->NRows=%d; B->NCols=%d\n"
556  "result->NRows=%d; result->NCols=%d\n\n",
557  BRows, BCols, RRows, RCols);
558  exit (1);
559  }
560 
561  if (BCols == 6)
562  {
563 
564  // read C in register variables since it will stay constant for the whole computation
565  Real c11 = C[0], c12 = C[1], c13 = C[2], c14 = C[3], c15 = C[4], c16 = C[5];
566  Real c21 = C[6], c22 = C[7], c23 = C[8], c24 = C[9], c25 = C[10], c26 = C[11];
567  Real c31 = C[12], c32 = C[13], c33 = C[14], c34 = C[15], c35 = C[16], c36 = C[17];
568  Real c41 = C[18], c42 = C[19], c43 = C[20], c44 = C[21], c45 = C[22], c46 = C[23];
569  Real c51 = C[24], c52 = C[25], c53 = C[26], c54 = C[27], c55 = C[28], c56 = C[29];
570  Real c61 = C[30], c62 = C[31], c63 = C[32], c64 = C[33], c65 = C[34], c66 = C[35];
571 
572 
573  for (int i = 0; i < BRows; i++)
574  {
575 
576  // read a row of B
577  Real b1 = B->Ent[i][0], b2 = B->Ent[i][1], b3 = B->Ent[i][2], b4 = B->Ent[i][3], b5 = B->Ent[i][4], b6 = B->Ent[i][5];
578 
579  // compute C times BT_col (== B_row)
580  Real v1 = c11 * b1 + c21 * b2 + c31 * b3 + c41 * b4 + c51 * b5 + c61 * b6;
581  Real v2 = c12 * b1 + c22 * b2 + c32 * b3 + c42 * b4 + c52 * b5 + c62 * b6;
582  Real v3 = c13 * b1 + c23 * b2 + c33 * b3 + c43 * b4 + c53 * b5 + c63 * b6;
583  Real v4 = c14 * b1 + c24 * b2 + c34 * b3 + c44 * b4 + c54 * b5 + c64 * b6;
584  Real v5 = c15 * b1 + c25 * b2 + c35 * b3 + c45 * b4 + c55 * b5 + c65 * b6;
585  Real v6 = c16 * b1 + c26 * b2 + c36 * b3 + c46 * b4 + c56 * b5 + c66 * b6;
586 
587  // compute R_col = B_row * v (= C times BT_col)
588  for (int k = 0; k < BRows; k++)
589  result->Ent[i][k] += (v1 * B->Ent[k][0] + v2 * B->Ent[k][1] + v3 * B->Ent[k][2] + v4 * B->Ent[k][3] + v5 * B->Ent[k][4] + v6 * B->Ent[k][5]) * dx;
590 
591  }
592 
593  }
594  else // general algorithm
595  {
596  Real * tmp = (Real*)calloc(BCols, sizeof(Real));
597  Real scalar_temp;
598 
599  for (int i = 0; i < BRows; i++)
600  {
601 
602  memset(tmp, 0., BCols * sizeof(Real));
603 
604  // compute B_row C
605  for (int j1 = 0; j1 < BCols; j1++)
606  for (int j2 = 0; j2 < BCols; j2++)
607  tmp[j2] += B->Ent[i][j1] * C[BCols * j1 + j2];
608 
609  // compute (B_row C) BT_col
610  for (int k = 0; k < BRows; k++)
611  {
612  scalar_temp = 0.;
613  for (int j = 0; j < BCols; j++)
614  scalar_temp += tmp[j] * B->Ent[k][j];
615 
616  result->Ent[i][k] += scalar_temp * dx;
617  }
618  }
619  free(tmp);
620  }
621 }
622 
623 
625 {
626  for (int i = 0; i < A->NRows; i++)
627  {
628  for ( int j = 0; j < A->NCols; j++)
629  printf( "%12.8f\t", A->Ent[i][j] );
630  printf("\n");
631  }
632  printf("\n");
633 }
double Real
Definition: DataTypes.h:14
void FM_Times_Scalar(FMatrix *A, Real a)
Definition: FMatrix.cc:227
Real FMatrix_Det(FMatrix *M)
Definition: FMatrix.cc:235
void B_C_BTrans(Real dx, FMatrix *B, Real *C, FMatrix *result)
Definition: FMatrix.cc:543
void Print_FMatrix(FMatrix *A)
Definition: FMatrix.cc:624
void FM_Plus_FM(FMatrix *A, FMatrix *B, FMatrix *C)
Definition: FMatrix.cc:196
void FM_Times_FMinArray(FMatrix *A, FMatrix *B, Real *C)
Definition: FMatrix.cc:119
Real FMatrix_Trace(FMatrix *M)
Definition: FMatrix.cc:292
void FM_Times_Vec(Real dx, FMatrix *B, Real *C, Real *result)
Definition: FMatrix.cc:522
FMatrix * FM_Rotate(FMatrix *R, double angle, int ax)
Definition: FMatrix.cc:478
void TransFM_Times_FM(FMatrix *A, FMatrix *B, FMatrix *C)
Definition: FMatrix.cc:143
Real * FM_X_Vec(FMatrix *A, Real *b, Real *c)
Definition: FMatrix.cc:508
void FM_Times_FM(FMatrix *A, FMatrix *B, FMatrix *C)
Definition: FMatrix.cc:93
void FM_Times_TransFM(FMatrix *A, FMatrix *B, FMatrix *C)
Definition: FMatrix.cc:169
int mxNCols
max. number of cols
Definition: FMatrix.h:22
int NCols
actual number of cols
Definition: FMatrix.h:24
bool decomposed
true if decomposed
Definition: FMatrix.h:28
Real ** Ent
matrix entries
Definition: FMatrix.h:27
int lsize
local size
Definition: FMatrix.h:26
int * indx
indices for decomposition
Definition: FMatrix.h:29
~FMatrix()
Definition: FMatrix.cc:10
int mxNRows
max. number of rows
Definition: FMatrix.h:23
void resize(int, int)
Definition: FMatrix.cc:73
FMatrix & operator=(FMatrix &)
Definition: FMatrix.cc:48
Real ** base1
base1 version of matrix
Definition: FMatrix.h:30
FMatrix(T, T)
FMatrix * Inv()
Definition: FMatrix.cc:376
void LUD()
Definition: FMatrix.cc:320
FMatrix * Transpose(bool)
Definition: FMatrix.cc:443
void LUsolve(Real *)
Definition: FMatrix.cc:355
int NRows
actual number of rows
Definition: FMatrix.h:25
FMatrix * Invert()
Definition: FMatrix.cc:407
void Zero()
Definition: FMatrix.cc:28
bool ludcmp(Real **a, size_t n, int *indx, Real *d)
Definition: ludec.cc:22
void lubksb(Real **a, size_t n, int *indx, Real *b)
Definition: ludec.cc:101
V angle(const vec3< V > &v1, const vec3< V > &v2)
Definition: vect.h:120