QwAnalysis
matrix.cc
Go to the documentation of this file.
1 #include "matrix.h"
2 
3 #define DBL_EPSILON 2.22045e-16
4 
5 double *V_Zero (double *v, const int n)
6 {
7  for (int i = 0; i < n; i++) {
8  v[i] = 0.0;
9  }
10  return v;
11 }
12 
13 double *V_Unit (double *v, const int n, const int k)
14 {
15  for (int i = 0; i < n; i++) {
16  v[i] = 0.0;
17  }
18  v[k] = 1.0;
19  return v;
20 }
21 
22 void V_Print (const double *v, const int n)
23 {
24  // Print vector v
25  for (int i = 0; i < n; i++) {
26  std::cout << v[i];
27  }
28  std::cout << std::endl;
29  return;
30 }
31 
32 void V_Print (const double *v, const double *w, const int n)
33 {
34  // Print vector v and w
35  for (int i = 0; i < n; i++) {
36  std::cout << v[i] << " | " << w[i];
37  }
38  std::cout << std::endl;
39  return;
40 }
41 
42 
43 
44 /*------------------------------------------------------------------------*//*!
45 
46  \fn double UNorm (const double *A, int n, const int m)
47 
48  \brief Calculates the least upper bound norm
49 
50 *//*-------------------------------------------------------------------------*/
51 double UNorm (const double *A, int n, const int m)
52 {
53  int counter;
54  double help, Max = 0.0;
55  const double *B = A;
56  while (n--) {
57  counter = m;
58  while (counter--) {
59  B = A + n + counter;
60  if (Max < (help = fabs (*(B))))
61  Max = help;
62  }
63  }
64  return Max;
65 }
66 
67 
68 
69 /*------------------------------------------------------------------------*//*!
70 
71  \fn double *M_Cholesky (double *B, double *q, const int n)
72 
73  \brief Calculates the Cholesky decomposition of the positive-definite matrix B
74 
75 *//*-------------------------------------------------------------------------*/
76 double *M_Cholesky (double *B, double *q, const int n)
77 {
78  int i, j, k;
79  double sum, min;
80  double *C = B;
81  double A[n][n];
82  double p[n],*pp;
83 
84  for(i=0;i<n;i++){
85  for(j=0;j<n;j++){
86  A[i][j]=*C;
87  C++;
88  }
89  }
90 
91  min = UNorm (B, n, n) * n * DBL_EPSILON;
92  for( i = 0; i < n; i++ ) {
93  for( j = i; j < n; j++ ) {
94  sum = A[i][j];
95  for( k = i-1; k >= 0; k-- )
96  sum -= A[i][k] * A[j][k];
97  if( i == j ) {
98  if( sum < min ) {
99  return 0;
100  }
101  p[i] = sqrt(sum);
102  } else
103  A[j][i] = sum/p[i];
104  }
105  }
106  C = B;
107  pp=q;
108  for(i=0;i<n;i++){
109  *p = p[i];
110  pp++;
111  for(j=0;j<n;j++){
112  *C = A[i][j];
113  C++;
114  }
115  }
116  C = B;
117  pp = q;
118  return B;
119 }
120 
121 
122 
123 /*------------------------------------------------------------------------*//*!
124 
125  \fn void RowMult(const double a, double *A, const double b, const double *B, const int n)
126 
127  \brief Calculates a*A + b*B, where both A and B are rows of length n, returns as A
128 
129 *//*-------------------------------------------------------------------------*/
130 void RowMult (const double a, double *A, const double b, const double *B, const int n)
131 {
132  for (int i = 0; i < n; i++)
133  A[i] = a*A[i] + b*B[i];
134 
135  return;
136 }
137 
138 
139 
140 /*------------------------------------------------------------------------*//*!
141 
142  \fn void M_Print (const double *A, const int n)
143 
144  \brief Print matrix A of dimension [n,n] to cout
145 
146 *//*-------------------------------------------------------------------------*/
147 void M_Print (const double *A, const int n)
148 {
149  // Print matrix A
150  for (int i = 0; i < n; i++) {
151  std::cout << "[";
152  for (int j = 0; j < n; j++) {
153  std::cout << A[i*n+j] << ' ';
154  }
155  std::cout << ']' << std::endl;
156  }
157  std::cout << std::endl;
158 
159  return;
160 }
161 
162 
163 
164 /*------------------------------------------------------------------------*//*!
165 
166  \fn void M_Print (const double *A, const double *B, const int n)
167 
168  \brief Print matrices A and B of dimension [n,n] to cout
169 
170 *//*-------------------------------------------------------------------------*/
171 void M_Print (const double *A, const double *B, const int n)
172 {
173  // Print matrices A and B
174  for (int i = 0; i < n; i++) {
175  std::cout << "[";
176  for (int j = 0; j < n; j++) {
177  std::cout << A[i*n+j] << ' ';
178  }
179  std::cout << '|' ;
180  for (int j = 0; j < n; j++) {
181  std::cout << B[i*n+j] << ' ';
182  }
183  std::cout << ']' << std::endl;
184  }
185  std::cout << std::endl;
186 
187  return;
188 }
189 
190 
191 
192 /*------------------------------------------------------------------------*//*!
193 
194  \fn double *M_Unit (double *A, const int n)
195 
196  \brief Creates unit matrix A
197 
198 *//*-------------------------------------------------------------------------*/
199 double *M_Unit (double *A, const int n)
200 {
201  for (int i = 0; i < n; i++) {
202  for (int j = 0; j < n; j++) {
203  A[i*n+j] = 0;
204  }
205  A[i*n+i] = 1;
206  }
207 
208  return A;
209 }
210 
211 
212 
213 /*------------------------------------------------------------------------*//*!
214 
215  \fn double *M_Zero (double *A, const int n)
216 
217  \brief Creates zero matrix A
218 
219 *//*-------------------------------------------------------------------------*/
220 double *M_Zero (double *A, const int n)
221 {
222  for (int i = 0; i < n; i++) {
223  for (int j = 0; j < n; j++) {
224  A[i*n+j] = 0;
225  }
226  }
227 
228  return A;
229 }
230 
231 
232 
233 /*------------------------------------------------------------------------*//*!
234 
235  \fn double *M_Invert (double *Ap, double *Bp, const int n)
236 
237  \brief Matrix inversion of Ap will be stored in Bp
238 
239 *//*-------------------------------------------------------------------------*/
240 double* M_Invert (double *Ap, double *Bp, const int n)
241 {
242  double *row1, *row2;
243  double a, b;
244 
245  // Initialize B to unit matrix (wdc: assumed n = 4 here)
246  M_Unit (Bp, n);
247 
248  // Print matrices Ap and Bp
249  //M_Print (Ap, Bp, n);
250 
251  // This will not be generalized for nxn matrices.
252  // (wdc: TODO faster algs could be useful later)
253  if (n == 2) {
254  double det = (Ap[0] * Ap[3]) - (Ap[1] * Ap[2]);
255  Bp[0] = Ap[0] / det;
256  Bp[1] = -Ap[1] / det;
257  Bp[2] = -Ap[2] / det;
258  Bp[3] = Ap[3] / det;
259  }
260 
261  if (n == 4) {
262  // Calculate inverse matrix using row-reduce method.
263  // (No safety for singular matrices!)
264 
265  // get A10 to An0 to be zero.
266  for (int i = 1; i < n; i++) {
267  a = -(Ap[0]);
268  b = Ap[i*n];
269  row1 = &(Ap[i*n]);
270  row2 = &(Ap[0]);
271  RowMult(a, row1, b, row2, 4);
272  row1 = &(Bp[i*n]);
273  row2 = &(Bp[0]);
274  RowMult(a, row1, b, row2, 4);
275  }
276 
277  // get A21 and A31 to be zero
278  for (int i = 2; i < n; i++) {
279  a = -(Ap[5]);
280  b = Ap[i*n+1];
281  row1 = &(Ap[i*n]);
282  row2 = &(Ap[4]);
283  RowMult(a, row1, b, row2, 4);
284  row1 = &(Bp[i*n]);
285  row2 = &(Bp[4]);
286  RowMult(a, row1, b, row2, 4);
287  }
288 
289  // get A32 to be zero
290  a = -(Ap[10]);
291  b = Ap[14];
292  row1 = &(Ap[12]);
293  row2 = &(Ap[8]);
294  RowMult(a, row1, b, row2, 4);
295  row1 = &(Bp[12]);
296  row2 = &(Bp[8]);
297  RowMult(a, row1, b, row2, 4);
298 
299  // Now the matrix is upper right triangular.
300 
301  // row reduce the 4th row
302  a = 1/(Ap[15]);
303  row1 = &(Ap[12]);
304  RowMult(a, row1, 0, row2, 4);
305  row1 = &(Bp[12]);
306  RowMult(a, row1, 0, row2, 4);
307 
308  // get A03 to A23 to be zero
309  for (int i = 0; i < n-1; i++) {
310  a = -(Ap[15]);
311  b = Ap[i*n+3];
312  row1 = &(Ap[i*n]);
313  row2 = &(Ap[12]);
314  RowMult(a, row1, b, row2, 4);
315  row1 = &(Bp[i*n]);
316  row2 = &(Bp[12]);
317  RowMult(a, row1, b, row2, 4);
318  }
319 
320  // row reduce the 3rd row
321  a = 1/(Ap[10]);
322  row1 = &(Ap[8]);
323  RowMult(a, row1, 0, row2, 4);
324  row1 = &(Bp[8]);
325  RowMult(a, row1, 0, row2, 4);
326 
327  // get A02 and A12 to be zero
328  for (int i = 0; i < 2; i++) {
329  a = -(Ap[10]);
330  b = Ap[i*n+2];
331  row1 = &(Ap[i*n]);
332  row2 = &(Ap[8]);
333  RowMult(a, row1, b, row2, 4);
334  row1 = &(Bp[i*n]);
335  row2 = &(Bp[8]);
336  RowMult(a, row1, b, row2, 4);
337  }
338 
339  // row reduce the 2nd row
340  a = 1/(Ap[5]);
341  row1 = &(Ap[4]);
342  RowMult(a, row1, 0, row2, n);
343  row1 = &(Bp[4]);
344  RowMult(a, row1, 0, row2, n);
345 
346  // get A01 to be zero
347  a = -(Ap[5]);
348  b = Ap[1];
349  row1 = &(Ap[0]);
350  row2 = &(Ap[4]);
351  RowMult(a, row1, b, row2, n);
352  row1 = &(Bp[0]);
353  row2 = &(Bp[4]);
354  RowMult(a, row1, b, row2, n);
355 
356  // row reduce 1st row
357  a = 1/(Ap[0]);
358  row1 = &(Ap[0]);
359  RowMult(a, row1, 0, row2, n);
360  row1 = &(Bp[0]);
361  RowMult(a, row1, 0, row2, n);
362  }
363 
364  return Bp;
365 }
366 
367 
368 
369 /*------------------------------------------------------------------------*//*!
370 
371  \fn double *M_InvertPos (double *B, const int n)
372 
373  \brief Calculates a*A + b*B, where both A and B are rows of length n
374 
375 *//*-------------------------------------------------------------------------*/
376 double *M_InvertPos (double *B, const int n)
377 {
378  double sum;
379  double p[n];
380  double q[n];
381  double inv[n][n];
382  double *pp = NULL;
383  double A[n][n],*C;
384 
385  // First we find the cholesky decomposition of B
386  if (M_Cholesky(B, pp, n)) {
387 
388  C = B;
389  for (int i = 0; i < n; i++) {
390  p[i] = *q;
391  for (int j = 0; j < n; j++ ) {
392  A[i][j] = *C;
393  C++;
394  }
395  }
396 
397  for (int i = 0; i < n; i++) {
398  A[i][i] = 1.0 / p[i];
399  for (int j = i+1; j < n; j++) {
400  sum = 0;
401  for (int k = i; k < j; k++)
402  sum -= A[j][k] * A[k][i];
403  A[j][i] = sum / p[j];
404  }
405  }
406 
407  for (int i = 0; i < n; i++) {
408  for (int j = i; j < n; j++) {
409  sum = 0;
410  for (int k = j; k < n; k++)
411  sum += A[k][i] * A[k][j];
412  inv[i][j] = inv[j][i] = sum;
413  }
414  }
415 
416  C = B;
417  for (int i = 0; i < n; i++) {
418  for (int j = 0; j < n; j++) {
419  *C = inv[i][j];
420  C++;
421  }
422  }
423 
424  } else {
425  B = 0;
426  std::cout << "Cholesky decomposition failed!" << std::endl;
427  }
428 
429  C = B;
430 
431  return B;
432 }
433 
434 
435 
436 /*------------------------------------------------------------------------*//*!
437 
438  \fn double *M_A_times_b (double *y, const double *A, const int n, const int m, const double *b)
439 
440  \brief Calculates y[n] = A[n,m] * b[m], with dimensions indicated
441 
442 *//*-------------------------------------------------------------------------*/
443 double *M_A_times_b (double *y, const double *A, const int n, const int m, const double *b)
444 {
445  for (int i = 0; i < n; i++) {
446  y[i] = 0;
447  for (int j = 0; j < m; j++) {
448  y[i] += A[i*n+j] * b[j];
449  }
450  }
451  return y;
452 }
#define DBL_EPSILON
Definition: matrix.cc:3
double * M_Invert(double *Ap, double *Bp, const int n)
Matrix inversion of Ap will be stored in Bp.
Definition: matrix.cc:240
static const double m
Definition: QwUnits.h:63
double * V_Zero(double *v, const int n)
Definition: matrix.cc:5
double * M_Cholesky(double *B, double *q, const int n)
Calculates the Cholesky decomposition of the positive-definite matrix B.
Definition: matrix.cc:76
double * M_InvertPos(double *B, const int n)
Calculates a*A + b*B, where both A and B are rows of length n.
Definition: matrix.cc:376
double * V_Unit(double *v, const int n, int k)
Definition: matrix.cc:13
double UNorm(const double *A, int n, const int m)
Calculates the least upper bound norm.
Definition: matrix.cc:51
void RowMult(const double a, double *A, const double b, const double *B, const int n)
Calculates a*A + b*B, where both A and B are rows of length n, returns as A.
Definition: matrix.cc:130
void M_Print(const double *A, const int n)
Print matrix A of dimension [n,n] to cout.
Definition: matrix.cc:147
double * M_A_times_b(double *y, const double *A, const int n, const int m, const double *b)
Calculates y[n] = A[n,m] * b[m], with dimensions indicated.
Definition: matrix.cc:443
static const double min
Definition: QwUnits.h:76
double * M_Zero(double *A, const int n)
Creates zero matrix A.
Definition: matrix.cc:220
void V_Print(const double *v, const int n)
Definition: matrix.cc:22
double * M_Unit(double *A, const int n)
Creates unit matrix A.
Definition: matrix.cc:199