matrix.cc

Go to the documentation of this file.
00001 #include "matrix.h"
00002 
00003 #define DBL_EPSILON 2.22045e-16
00004 
00005 double *V_Zero (double *v, const int n)
00006 {
00007   for (int i = 0; i < n; i++) {
00008     v[i] = 0.0;
00009   }
00010   return v;
00011 }
00012 
00013 double *V_Unit (double *v, const int n, const int k)
00014 {
00015   for (int i = 0; i < n; i++) {
00016     v[i] = 0.0;
00017   }
00018   v[k] = 1.0;
00019   return v;
00020 }
00021 
00022 void V_Print (const double *v, const int n)
00023 {
00024   // Print vector v
00025   for (int i = 0; i < n; i++) {
00026     std::cout << v[i];
00027   }
00028   std::cout << std::endl;
00029   return;
00030 }
00031 
00032 void V_Print (const double *v, const double *w, const int n)
00033 {
00034   // Print vector v and w
00035   for (int i = 0; i < n; i++) {
00036     std::cout << v[i] << " | " << w[i];
00037   }
00038   std::cout << std::endl;
00039   return;
00040 }
00041 
00042 
00043 
00044 /*------------------------------------------------------------------------*//*!
00045 
00046  \fn double UNorm (const double *A, int n, const int m)
00047 
00048  \brief Calculates the least upper bound norm
00049 
00050 *//*-------------------------------------------------------------------------*/
00051 double UNorm (const double *A, int n, const int m)
00052 {
00053   int counter;
00054   double help, Max = 0.0;
00055   const double *B = A;
00056   while (n--) {
00057     counter = m;
00058     while (counter--) {
00059       B = A + n + counter;
00060       if (Max < (help = fabs (*(B))))
00061        Max = help;
00062       }
00063   }
00064   return Max;
00065 }
00066 
00067 
00068 
00069 /*------------------------------------------------------------------------*//*!
00070 
00071  \fn double *M_Cholesky (double *B, double *q, const int n)
00072 
00073  \brief Calculates the Cholesky decomposition of the positive-definite matrix B
00074 
00075 *//*-------------------------------------------------------------------------*/
00076 double *M_Cholesky (double *B, double *q, const int n)
00077 {
00078   int i, j, k;
00079   double sum, min;
00080   double *C = B;
00081   double A[n][n];
00082   double p[n],*pp;
00083 
00084   for(i=0;i<n;i++){
00085     for(j=0;j<n;j++){
00086       A[i][j]=*C;
00087       C++;
00088     }
00089   }
00090 
00091   min = UNorm (B, n, n)  * n * DBL_EPSILON;
00092   for( i = 0; i < n; i++ ) {
00093     for( j = i; j < n; j++ ) {
00094       sum = A[i][j];
00095       for( k = i-1; k >= 0; k-- )
00096        sum -= A[i][k] * A[j][k];
00097       if( i == j ) {
00098        if( sum < min ) {
00099          return 0;
00100        }
00101        p[i] = sqrt(sum);
00102       } else
00103        A[j][i] = sum/p[i];
00104     }
00105   }
00106   C = B;
00107   pp=q;
00108   for(i=0;i<n;i++){
00109     *p = p[i];
00110     pp++;
00111     for(j=0;j<n;j++){
00112       *C = A[i][j];
00113       C++;
00114     }
00115   }
00116   C = B;
00117   pp = q;
00118   return B;
00119 }
00120 
00121 
00122 
00123 /*------------------------------------------------------------------------*//*!
00124 
00125  \fn void RowMult(const double a, double *A, const double b, const double *B, const int n)
00126 
00127  \brief Calculates a*A + b*B, where both A and B are rows of length n, returns as A
00128 
00129 *//*-------------------------------------------------------------------------*/
00130 void RowMult (const double a, double *A, const double b, const double *B, const int n)
00131 {
00132   for (int i = 0; i < n; i++)
00133     A[i] = a*A[i] + b*B[i];
00134 
00135   return;
00136 }
00137 
00138 
00139 
00140 /*------------------------------------------------------------------------*//*!
00141 
00142  \fn void M_Print (const double *A, const int n)
00143 
00144  \brief Print matrix A of dimension [n,n] to cout
00145 
00146 *//*-------------------------------------------------------------------------*/
00147 void M_Print (const double *A, const int n)
00148 {
00149   // Print matrix A
00150   for (int i = 0; i < n; i++) {
00151     std::cout << "[";
00152     for (int j = 0; j < n; j++) {
00153       std::cout << A[i*n+j] << ' ';
00154     }
00155     std::cout << ']' << std::endl;
00156   }
00157   std::cout << std::endl;
00158 
00159   return;
00160 }
00161 
00162 
00163 
00164 /*------------------------------------------------------------------------*//*!
00165 
00166  \fn void M_Print (const double *A, const double *B, const int n)
00167 
00168  \brief Print matrices A and B of dimension [n,n] to cout
00169 
00170 *//*-------------------------------------------------------------------------*/
00171 void M_Print (const double *A, const double *B, const int n)
00172 {
00173   // Print matrices A and B
00174   for (int i = 0; i < n; i++) {
00175     std::cout << "[";
00176     for (int j = 0; j < n; j++) {
00177       std::cout << A[i*n+j] << ' ';
00178     }
00179     std::cout << '|' ;
00180     for (int j = 0; j < n; j++) {
00181       std::cout << B[i*n+j] << ' ';
00182     }
00183     std::cout << ']' << std::endl;
00184   }
00185   std::cout << std::endl;
00186 
00187   return;
00188 }
00189 
00190 
00191 
00192 /*------------------------------------------------------------------------*//*!
00193 
00194  \fn double *M_Unit (double *A, const int n)
00195 
00196  \brief Creates unit matrix A
00197 
00198 *//*-------------------------------------------------------------------------*/
00199 double *M_Unit (double *A, const int n)
00200 {
00201   for (int i = 0; i < n; i++) {
00202     for (int j = 0; j < n; j++) {
00203       A[i*n+j] = 0;
00204     }
00205     A[i*n+i] = 1;
00206   }
00207 
00208   return A;
00209 }
00210 
00211 
00212 
00213 /*------------------------------------------------------------------------*//*!
00214 
00215  \fn double *M_Zero (double *A, const int n)
00216 
00217  \brief Creates zero matrix A
00218 
00219 *//*-------------------------------------------------------------------------*/
00220 double *M_Zero (double *A, const int n)
00221 {
00222   for (int i = 0; i < n; i++) {
00223     for (int j = 0; j < n; j++) {
00224       A[i*n+j] = 0;
00225     }
00226   }
00227 
00228   return A;
00229 }
00230 
00231 
00232 
00233 /*------------------------------------------------------------------------*//*!
00234 
00235  \fn double *M_Invert (double *Ap, double *Bp, const int n)
00236 
00237  \brief Matrix inversion of Ap will be stored in Bp
00238 
00239 *//*-------------------------------------------------------------------------*/
00240 double* M_Invert (double *Ap, double *Bp, const int n)
00241 {
00242   double *row1, *row2;
00243   double a, b;
00244 
00245   // Initialize B to unit matrix (wdc: assumed n = 4 here)
00246   M_Unit (Bp, n);
00247 
00248   // Print matrices Ap and Bp
00249   //M_Print (Ap, Bp, n);
00250 
00251   // This will not be generalized for nxn matrices.
00252   // (wdc: TODO  faster algs could be useful later)
00253   if (n == 2) {
00254     double det = (Ap[0] * Ap[3]) - (Ap[1] * Ap[2]);
00255     Bp[0] =  Ap[0] / det;
00256     Bp[1] = -Ap[1] / det;
00257     Bp[2] = -Ap[2] / det;
00258     Bp[3] =  Ap[3] / det;
00259   }
00260 
00261   if (n == 4) {
00262     // Calculate inverse matrix using row-reduce method.
00263     // (No safety for singular matrices!)
00264 
00265     // get A10 to An0 to be zero.
00266     for (int i = 1; i < n; i++) {
00267       a = -(Ap[0]);
00268       b = Ap[i*n];
00269       row1 = &(Ap[i*n]);
00270       row2 = &(Ap[0]);
00271       RowMult(a, row1, b, row2, 4);
00272       row1 = &(Bp[i*n]);
00273       row2 = &(Bp[0]);
00274       RowMult(a, row1, b, row2, 4);
00275     }
00276 
00277     // get A21 and A31 to be zero
00278     for (int i = 2; i < n; i++) {
00279       a = -(Ap[5]);
00280       b = Ap[i*n+1];
00281       row1 = &(Ap[i*n]);
00282       row2 = &(Ap[4]);
00283       RowMult(a, row1, b, row2, 4);
00284       row1 = &(Bp[i*n]);
00285       row2 = &(Bp[4]);
00286       RowMult(a, row1, b, row2, 4);
00287     }
00288 
00289     // get A32 to be zero
00290     a = -(Ap[10]);
00291     b = Ap[14];
00292     row1 = &(Ap[12]);
00293     row2 = &(Ap[8]);
00294     RowMult(a, row1, b, row2, 4);
00295     row1 = &(Bp[12]);
00296     row2 = &(Bp[8]);
00297     RowMult(a, row1, b, row2, 4);
00298 
00299     // Now the matrix is upper right triangular.
00300 
00301     // row reduce the 4th row
00302     a = 1/(Ap[15]);
00303     row1 = &(Ap[12]);
00304     RowMult(a, row1, 0, row2, 4);
00305     row1 = &(Bp[12]);
00306     RowMult(a, row1, 0, row2, 4);
00307 
00308     // get A03 to A23 to be zero
00309     for (int i = 0; i < n-1; i++) {
00310       a = -(Ap[15]);
00311       b = Ap[i*n+3];
00312       row1 = &(Ap[i*n]);
00313       row2 = &(Ap[12]);
00314       RowMult(a, row1, b, row2, 4);
00315       row1 = &(Bp[i*n]);
00316       row2 = &(Bp[12]);
00317       RowMult(a, row1, b, row2, 4);
00318     }
00319 
00320     // row reduce the 3rd row
00321     a = 1/(Ap[10]);
00322     row1 = &(Ap[8]);
00323     RowMult(a, row1, 0, row2, 4);
00324     row1 = &(Bp[8]);
00325     RowMult(a, row1, 0, row2, 4);
00326 
00327     // get A02 and A12 to be zero
00328     for (int i = 0; i < 2; i++) {
00329       a = -(Ap[10]);
00330       b = Ap[i*n+2];
00331       row1 = &(Ap[i*n]);
00332       row2 = &(Ap[8]);
00333       RowMult(a, row1, b, row2, 4);
00334       row1 = &(Bp[i*n]);
00335       row2 = &(Bp[8]);
00336       RowMult(a, row1, b, row2, 4);
00337     }
00338 
00339     // row reduce the 2nd row
00340     a = 1/(Ap[5]);
00341     row1 = &(Ap[4]);
00342     RowMult(a, row1, 0, row2, n);
00343     row1 = &(Bp[4]);
00344     RowMult(a, row1, 0, row2, n);
00345 
00346     // get A01 to be zero
00347     a = -(Ap[5]);
00348     b = Ap[1];
00349     row1 = &(Ap[0]);
00350     row2 = &(Ap[4]);
00351     RowMult(a, row1, b, row2, n);
00352     row1 = &(Bp[0]);
00353     row2 = &(Bp[4]);
00354     RowMult(a, row1, b, row2, n);
00355 
00356     // row reduce 1st row
00357     a = 1/(Ap[0]);
00358     row1 = &(Ap[0]);
00359     RowMult(a, row1, 0, row2, n);
00360     row1 = &(Bp[0]);
00361     RowMult(a, row1, 0, row2, n);
00362   }
00363 
00364   return Bp;
00365 }
00366 
00367 
00368 
00369 /*------------------------------------------------------------------------*//*!
00370 
00371  \fn double *M_InvertPos (double *B, const int n)
00372 
00373  \brief Calculates a*A + b*B, where both A and B are rows of length n
00374 
00375 *//*-------------------------------------------------------------------------*/
00376 double *M_InvertPos (double *B, const int n)
00377 {
00378   double sum;
00379   double p[n];
00380   double q[n];
00381   double inv[n][n];
00382   double *pp = NULL;
00383   double A[n][n],*C;
00384 
00385   // First we find the cholesky decomposition of B
00386   if (M_Cholesky(B, pp, n)) {
00387 
00388     C = B;
00389     for (int i = 0; i < n; i++) {
00390       p[i] = *q;
00391       for (int j = 0; j < n; j++ ) {
00392         A[i][j] = *C;
00393         C++;
00394       }
00395     }
00396 
00397     for (int i = 0; i < n; i++) {
00398       A[i][i] = 1.0 / p[i];
00399       for (int j = i+1; j < n; j++) {
00400   sum = 0;
00401   for (int k = i; k < j; k++)
00402     sum -= A[j][k] * A[k][i];
00403   A[j][i] = sum / p[j];
00404       }
00405     }
00406 
00407     for (int i = 0; i < n; i++) {
00408       for (int j = i; j < n; j++) {
00409   sum = 0;
00410   for (int k = j; k < n; k++)
00411     sum += A[k][i] * A[k][j];
00412   inv[i][j] = inv[j][i] = sum;
00413       }
00414     }
00415 
00416     C = B;
00417     for (int i = 0; i < n; i++) {
00418       for (int j = 0; j < n; j++) {
00419   *C = inv[i][j];
00420         C++;
00421       }
00422     }
00423 
00424   } else {
00425     B = 0;
00426     std::cout << "Cholesky decomposition failed!" << std::endl;
00427   }
00428 
00429   C = B;
00430 
00431   return B;
00432 }
00433 
00434 
00435 
00436 /*------------------------------------------------------------------------*//*!
00437 
00438  \fn double *M_A_times_b (double *y, const double *A, const int n, const int m, const double *b)
00439 
00440  \brief Calculates y[n] = A[n,m] * b[m], with dimensions indicated
00441 
00442 *//*-------------------------------------------------------------------------*/
00443 double *M_A_times_b (double *y, const double *A, const int n, const int m, const double *b)
00444 {
00445   for (int i = 0; i < n; i++) {
00446     y[i] = 0;
00447     for (int j = 0; j < m; j++) {
00448       y[i] += A[i*n+j] * b[j];
00449     }
00450   }
00451   return y;
00452 }

Generated on 29 Jan 2017 for QwAnalysis by  doxygen 1.6.1