Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

robot/control/oldikor/UTILS/matrix.c

Go to the documentation of this file.
00001 /****************************************************************************
00002 *
00003 * File          : matrix.c
00004 * Author        : Ole Henry Dorum
00005 * Created       : January 28'th 1992
00006 * Purpose       : Perform matrix operations.
00007 * 
00008 *****************************************************************************/
00009 
00010 #include <UTILS/matrix.h>
00011 
00012 /****************************************************************************
00013  **                                                                        **
00014  **   Num Rec in C:    LU-decomp        &   LU-backsubstitution            **
00015  **                    SV-decomposition &   SVD-backsubstitution           **
00016  **                                                                        **
00017  ****************************************************************************/
00018 extern FILE* gcheck;     
00019 
00020 static float at,bt,ct;
00021 
00022               /**************************************************/
00023 
00024 
00025      /***************************************************/
00026      /* Return the null space of a matrix using svd.    */
00027      /***************************************************/
00028 void mat_null(a, n_rank, n, K2)
00029 MATRIX *a, *n;
00030 int    *n_rank;
00031 float  *K2;
00032 {
00033   MATRIX *a_sqr,
00034          *v,
00035          *S_temp;
00036   float **U, *S, **V,
00037         *vector(),
00038         **conv_2_nric_ptr();
00039   float s_min, s_max, temp;
00040   void free_vector(),
00041        free_ivector();
00042   int i, j, R, C, *order;
00043   int *ivector();
00044 
00045   R = a->rows;
00046   C = a->cols;
00047 
00048   if ((R==0) || (C==0)) {
00049       fprintf(stderr, "Can't calculate null-space of a 0x0 matrix.\n");
00050       return;
00051   }
00052 
00053   S_temp = mat_malloc(C+1,1);
00054   v      = mat_malloc(C,C);
00055   V      = conv_2_nric_ptr(v);
00056   S      = vector(1,C);
00057   order  = ivector(1,C);
00058      
00059 
00060   if (R < C)
00061      {
00062      a_sqr = mat_malloc(C,C);
00063      for (i=0; i<R; i++)
00064         for (j=0; j<C; j++)
00065            a_sqr->p[i][j]=a->p[i][j];
00066      for (i=R; i<C; i++)
00067         for (j=0; j<C; j++)
00068            a_sqr->p[i][j]=0.0;
00069      }
00070   else
00071      {
00072      a_sqr = mat_malloc(R,C);
00073      mat_cp(a, a_sqr);
00074      }
00075 
00076   U = conv_2_nric_ptr(a_sqr);
00077 
00078   svdcmp(U, C, C, S, V);
00079 
00080   for (i=1; i<(C+1); i++)
00081      {
00082      S_temp->p[i][0] = S[i];
00083      order[i] = i;
00084      }
00085   for (i=C; i>1; i--)
00086      for (j=i-1; j>=1; j--)
00087         if (fabs(S_temp->p[i][0])>fabs(S_temp->p[j][0]))
00088            {
00089            temp = S_temp->p[i][0];
00090            S_temp->p[i][0] = S_temp->p[j][0];
00091            S_temp->p[j][0] = temp;
00092            temp = order[i];
00093            order[i] = order[j];
00094            order[j] = temp;
00095            }
00096   if (R<=C)
00097      s_min = fabs(S_temp->p[R][0]);
00098   else
00099      s_min = fabs(S_temp->p[C][0]);
00100   s_max = fabs(S_temp->p[1][0]);
00101 
00102   *n_rank = 0;
00103   while (fabs(S_temp->p[C-*n_rank][0]) < SV_SMALL)
00104      {
00105      for (j=1; j<=C; j++)
00106         n->p[j-1][*n_rank]
00107           = V[j][order[C-*n_rank]];
00108      *n_rank = *n_rank + 1;
00109      }
00110  
00111   if ((fabs(s_min)>=SV_SMALL) && (fabs(s_min/s_max) < SV_SMALL))
00112      {
00113      for (j=1; j<=C; j++)
00114         n->p[j-1][*n_rank] = V[order[j]][C-*n_rank];
00115      *n_rank = *n_rank+1;
00116      }
00117 
00118   *K2 = s_max/s_min;
00119 
00120   mat_free(v);
00121   mat_free(a_sqr);
00122   mat_free(S_temp);
00123   free_vector(S,1,C);
00124   free_ivector(order,1,C);
00125   free(V);
00126   free(U);
00127 }
00128 
00129 
00130 
00131 void ludcmp(a,n,indx,d)
00132 int n,*indx;
00133 float **a,*d;
00134 {
00135         int i,imax,j,k;
00136         float big,dum,sum,temp;
00137         float *vv,*vector();
00138         void nrerror(),free_vector();
00139 
00140         vv=vector(1,n);
00141         *d=1.0;
00142         for (i=1;i<=n;i++) {
00143                 big=0.0;
00144                 for (j=1;j<=n;j++)
00145                         if ((temp=fabs(a[i][j])) > big) big=temp;
00146                 if (big == 0.0) nrerror("Singular matrix in routine LUDCMP");
00147                 vv[i]=1.0/big;
00148         }
00149         for (j=1;j<=n;j++) {
00150                 for (i=1;i<j;i++) {
00151                         sum=a[i][j];
00152                         for (k=1;k<i;k++) sum -= a[i][k]*a[k][j];
00153                         a[i][j]=sum;
00154                 }
00155                 big=0.0;
00156                 for (i=j;i<=n;i++) {
00157                         sum=a[i][j];
00158                         for (k=1;k<j;k++)
00159                                 sum -= a[i][k]*a[k][j];
00160                         a[i][j]=sum;
00161                         if ( (dum=vv[i]*fabs(sum)) >= big) {
00162                                 big=dum;
00163                                 imax=i;
00164                         }
00165                 }
00166                 if (j != imax) {
00167                         for (k=1;k<=n;k++) {
00168                                 dum=a[imax][k];
00169                                 a[imax][k]=a[j][k];
00170                                 a[j][k]=dum;
00171                         }
00172                         *d = -(*d);
00173                         vv[imax]=vv[j];
00174                 }
00175                 indx[j]=imax;
00176                 if (a[j][j] == 0.0) a[j][j]=TINY;
00177                 if (j != n) {
00178                         dum=1.0/(a[j][j]);
00179                         for (i=j+1;i<=n;i++) a[i][j] *= dum;
00180                 }
00181         }
00182         free_vector(vv,1,n);
00183 }
00184 
00185 
00186 void lubksb(a,n,indx,b)
00187 float **a,b[];
00188 int n,*indx;
00189 {
00190         int i,ii=0,ip,j;
00191         float sum;
00192 
00193         for (i=1;i<=n;i++) {
00194                 ip=indx[i];
00195                 sum=b[ip];
00196                 b[ip]=b[i];
00197                 if (ii)
00198                         for (j=ii;j<=i-1;j++) sum -= a[i][j]*b[j];
00199                 else if (sum) ii=i;
00200                 b[i]=sum;
00201         }
00202         for (i=n;i>=1;i--) {
00203                 sum=b[i];
00204                 for (j=i+1;j<=n;j++) sum -= a[i][j]*b[j];
00205                 b[i]=sum/a[i][i];
00206         }
00207 }
00208 
00209 
00210 void svbksb(u,w,v,m,n,b,x)
00211 float **u,w[],**v,b[],x[];
00212 int m,n;
00213 {
00214         int jj,j,i;
00215         float s,*tmp,*vector();
00216         void free_vector();
00217 
00218         tmp=vector(1,n);
00219         for (j=1;j<=n;j++) {
00220                 s=0.0;
00221                 if (w[j]) {
00222                         for (i=1;i<=m;i++) s += u[i][j]*b[i];
00223                         s /= w[j];
00224                 }
00225                 tmp[j]=s;
00226         }
00227         for (j=1;j<=n;j++) {
00228                 s=0.0;
00229                 for (jj=1;jj<=n;jj++) s += v[j][jj]*tmp[jj];
00230                 x[j]=s;
00231         }
00232         free_vector(tmp,1,n);
00233 }
00234 
00235 
00236 void svdcmp(a, m, n, w, v)
00237   float **a, *w, **v;
00238   int m, n;
00239 {
00240   int flag, i, its, j, jj, k, l, nm;
00241   float c, f, h, s, x, y, z;
00242   float anorm = 0.0, g = 0.0, scale = 0.0;
00243   float *rv1, *vector();
00244   void nrerror(), free_vector();
00245   if (m < n)
00246     nrerror("SVDCMP: You must augment A with extra zero rows");
00247   rv1 = vector(1, n);
00248   for (i = 1; i <= n; i++)
00249   {
00250     l = i + 1;
00251     rv1[i] = scale * g;
00252     g = s = scale = 0.0;
00253     if (i <= m)
00254     {
00255       for (k = i; k <= m; k++)
00256         scale += fabs(a[k][i]);
00257       if (scale)
00258       {
00259         for (k = i; k <= m; k++)
00260         {
00261           a[k][i] /= scale;
00262           s += a[k][i] * a[k][i];
00263         }
00264         f = a[i][i];
00265         g = -SIGN(sqrt(s), f);
00266         h = f * g - s;
00267         a[i][i] = f - g;
00268         if (i != n)
00269         {
00270           for (j = l; j <= n; j++)
00271           {
00272             for (s = 0.0, k = i; k <= m; k++)
00273               s += a[k][i] * a[k][j];
00274             f = s / h;
00275             for (k = i; k <= m; k++)
00276               a[k][j] += f * a[k][i];
00277           }
00278         }
00279         for (k = i; k <= m; k++)
00280           a[k][i] *= scale;
00281       }
00282     }
00283     w[i] = scale * g;
00284     g = s = scale = 0.0;
00285     if (i <= m && i != n)
00286     {
00287       for (k = l; k <= n; k++)
00288         scale += fabs(a[i][k]);
00289       if (scale)
00290       {
00291         for (k = l; k <= n; k++)
00292         {
00293           a[i][k] /= scale;
00294           s += a[i][k] * a[i][k];
00295         }
00296         f = a[i][l];
00297         g = -SIGN(sqrt(s), f);
00298         h = f * g - s;
00299         a[i][l] = f - g;
00300         for (k = l; k <= n; k++)
00301           rv1[k] = a[i][k] / h;
00302         if (i != m)
00303         {
00304           for (j = l; j <= m; j++)
00305           {
00306             for (s = 0.0, k = l; k <= n; k++)
00307               s += a[j][k] * a[i][k];
00308             for (k = l; k <= n; k++)
00309               a[j][k] += s * rv1[k];
00310           }
00311         }
00312         for (k = l; k <= n; k++)
00313           a[i][k] *= scale;
00314       }
00315     }
00316     anorm = MAX(anorm, (fabs(w[i]) + fabs(rv1[i])));
00317   }
00318   for (i = n; i >= 1; i--)
00319   {
00320     if (i < n)
00321     {
00322       if (g)
00323       {
00324         for (j = l; j <= n; j++)
00325           v[j][i] = (a[i][j] / a[i][l]) / g;
00326         for (j = l; j <= n; j++)
00327         {
00328           for (s = 0.0, k = l; k <= n; k++)
00329             s += a[i][k] * v[k][j];
00330           for (k = l; k <= n; k++)
00331             v[k][j] += s * v[k][i];
00332         }
00333       }
00334       for (j = l; j <= n; j++)
00335         v[i][j] = v[j][i] = 0.0;
00336     }
00337     v[i][i] = 1.0;
00338     g = rv1[i];
00339     l = i;
00340   }
00341   for (i = n; i >= 1; i--)
00342   {
00343     l = i + 1;
00344     g = w[i];
00345     if (i < n)
00346       for (j = l; j <= n; j++)
00347         a[i][j] = 0.0;
00348     if (g)
00349     {
00350       g = 1.0 / g;
00351       if (i != n)
00352       {
00353         for (j = l; j <= n; j++)
00354         {
00355           for (s = 0.0, k = l; k <= m; k++)
00356             s += a[k][i] * a[k][j];
00357           f = (s / a[i][i]) * g;
00358           for (k = i; k <= m; k++)
00359             a[k][j] += f * a[k][i];
00360         }
00361       }
00362       for (j = i; j <= m; j++)
00363         a[j][i] *= g;
00364     }
00365     else
00366     {
00367       for (j = i; j <= m; j++)
00368         a[j][i] = 0.0;
00369     }
00370     ++a[i][i];
00371   }
00372   for (k = n; k >= 1; k--)
00373   {
00374     for (its = 1; its <= 30; its++)
00375     {
00376       flag = 1;
00377       for (l = k; l >= 1; l--)
00378       {
00379         nm = l - 1;
00380         if (fabs(rv1[l]) + anorm == anorm)
00381         {
00382           flag = 0;
00383           break;
00384         }
00385         if (fabs(w[nm]) + anorm == anorm)
00386           break;
00387       }
00388       if (flag)
00389       {
00390         c = 0.0;
00391         s = 1.0;
00392         for (i = l; i <= k; i++)
00393         {
00394           f = s * rv1[i];
00395           if (fabs(f) + anorm != anorm)
00396           {
00397             g = w[i];
00398             h = PYTHAG(f, g);
00399             w[i] = h;
00400             h = 1.0 / h;
00401             c = g * h;
00402             s = (-f * h);
00403             for (j = 1; j <= m; j++)
00404             {
00405               y = a[j][nm];
00406               z = a[j][i];
00407               a[j][nm] = y * c + z * s;
00408               a[j][i] = z * c - y * s;
00409             }
00410           }
00411         }
00412       }
00413       z = w[k];
00414       if (l == k)
00415       {
00416         if (z < 0.0)
00417         {
00418           w[k] = -z;
00419           for (j = 1; j <= n; j++)
00420             v[j][k] = (-v[j][k]);
00421         }
00422         break;
00423       }
00424       if (its == 30)
00425         nrerror("No convergence in 30 SVDCMP iterations");
00426       x = w[l];
00427       nm = k - 1;
00428       y = w[nm];
00429       g = rv1[nm];
00430       h = rv1[k];
00431       f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
00432       g = PYTHAG(f, 1.0);
00433       f = ((x - z) * (x + z) + h * ((y / (f + SIGN(g, f))) - h)) / x;
00434       c = s = 1.0;
00435       for (j = l; j <= nm; j++)
00436       {
00437         i = j + 1;
00438         g = rv1[i];
00439         y = w[i];
00440         h = s * g;
00441         g = c * g;
00442         z = PYTHAG(f, h);
00443         rv1[j] = z;
00444         c = f / z;
00445         s = h / z;
00446         f = x * c + g * s;
00447         g = g * c - x * s;
00448         h = y * s;
00449         y = y * c;
00450         for (jj = 1; jj <= n; jj++)
00451         {
00452           x = v[jj][j];
00453           z = v[jj][i];
00454           v[jj][j] = x * c + z * s;
00455           v[jj][i] = z * c - x * s;
00456         }
00457         z = PYTHAG(f, h);
00458         w[j] = z;
00459         if (z)
00460         {
00461           z = 1.0 / z;
00462           c = f * z;
00463           s = h * z;
00464         }
00465         f = (c * g) + (s * y);
00466         x = (c * y) - (s * g);
00467         for (jj = 1; jj <= m; jj++)
00468         {
00469           y = a[jj][j];
00470           z = a[jj][i];
00471           a[jj][j] = y * c + z * s;
00472           a[jj][i] = z * c - y * s;
00473         }
00474       }
00475       rv1[l] = 0.0;
00476       rv1[k] = f;
00477       w[k] = x;
00478     }
00479   }
00480   free_vector(rv1, 1, n);
00481 }
00482 
00483 
00484 #undef SIGN
00485 #undef PYTHAG
00486 #undef TINY
00487 
00488 /****************************************************************************/
00489 
00490 
00491 MATRIX *mat_malloc(rows, cols)
00492 int rows, cols;
00493 {
00494   int    i;
00495   float  *mat, **row;
00496   MATRIX *matrix;
00497 
00498   /* Allocate space for structure, elements and pointers.
00499    *
00500    * Note, that the allocated number of row pointers is MAX(row, cols)
00501    * because it facilitates transposing rectangular matrices.
00502    */
00503  if ((rows > 0) && (cols > 0)) {
00504    mat = (float * ) malloc(rows * cols * sizeof(float));
00505    row = (float **) malloc((MAX(rows, cols)) * sizeof(float *));
00506  }
00507  else {
00508    mat = (float * ) malloc(sizeof(float));
00509    row = (float **) malloc(sizeof(float *));
00510    row[0]=mat;
00511  }
00512    matrix = (MATRIX *) malloc( sizeof( MATRIX ) );
00513 
00514   if(!mat || !row || !matrix)
00515     {
00516  /*     IKerrror(18, FATAL);*/
00517       fprintf(stderr, "Matrix allocation failed\n");
00518       return(NULL);
00519     }
00520 
00521   matrix->p = row;
00522   matrix->rows = rows;
00523   matrix->cols = cols;
00524 
00525   /* The Nth element of the array row points to the 1st element 
00526    * on the Nth row. Thus, **m = *m[0] = m[0][0]
00527    *
00528    * Calculate the addresses of the pointers pointing to the 
00529    * rows of the matrix
00530    */
00531 
00532   for(i = 0; i < rows; i++)
00533   {
00534     row[i] = mat; 
00535     mat += cols;
00536   }
00537 
00538   return(matrix);
00539 }
00540 
00541 
00542 
00543 void mat_free(m)
00544 MATRIX *m;
00545 {
00546   free( (char *) *m->p);
00547   free( (char *)  m->p);
00548   free( (char *)  m);
00549 }
00550 
00551 
00552 void mat_pr(a)
00553 MATRIX *a;
00554 {
00555   int i, j;
00556 
00557   printf("\n");
00558   for (i = 0; i < a->rows; i++)
00559   {
00560     for (j = 0; j < a->cols; j++)
00561       {
00562         if (fabs(a->p[i][j]) >= PrintIfBiggerThan)
00563           printf("\t% .8f", a->p[i][j]);
00564         else
00565           printf("\t  - ");
00566       }
00567     printf("\n");
00568   }
00569   printf("\n");
00570 }
00571 
00572 
00573 void mat_prf(a)
00574 MATRIX *a;
00575 {
00576   int i, j;
00577 
00578   printf("\n");
00579   for (i = 0; i < a->rows; i++)
00580   {
00581     for (j = 0; j < a->cols; j++)
00582     {
00583       printf("\t% f", a->p[i][j]);
00584       }
00585     printf("\n");
00586   }
00587   printf("\n");
00588 }
00589 
00590 
00591 
00592 /* The inverted matrix will still reside in a */
00593 void mat_LU_inv(a)
00594 MATRIX *a;
00595 {
00596   MATRIX *y;
00597   float  **A, **Y, d, *col;
00598   int    N, i, j, *indx;
00599   float  **conv_2_nric_ptr();
00600 
00601   N = a->rows;
00602 
00603   /* Allocate space for y matrix to hold result, column vector col,
00604    * and indx array.
00605    */
00606   y    = mat_malloc(a->rows, a->cols);
00607   col  = vector(1, N);
00608   indx = (int *) malloc(N * sizeof(int));
00609 
00610   /* Create pointers to a and y conforming with Num-Rec-in-C format.
00611    * A and Y is from [1..N][1..N]
00612    */
00613   A = conv_2_nric_ptr(a);
00614   Y = conv_2_nric_ptr(y);
00615 
00616   /* LU decompose A
00617    */
00618   ludcmp(A, N, indx, &d);
00619 
00620   /* Find inverse by columns. (There is no better way to do it.)
00621    */
00622   for (j = 1; j <= N; j++)
00623     {
00624       for (i = 1; i <= N; i++)
00625         col[i] = 0.0;
00626 
00627       col[j] = 1.0;
00628       lubksb(A, N, indx, col);
00629 
00630       for (i = 1; i <= N; i++)
00631         Y[i][j] = col[i];
00632     }
00633 
00634   /* Inverted matrix is now in y. Copy y into a and free matrix y
00635    */
00636   mat_cp(y, a);
00637 
00638   mat_free(y);
00639   free_vector(col, 1, N);
00640   free( (char *) indx);
00641   free( (char *) A);
00642   free( (char *) Y);
00643 }
00644 
00645 
00646 /* The pseudoinverted matrix will still reside in a. In the case of a
00647  * square matrix, the result will actually be the inverted matrix. If
00648  * the matrix is rectangular, the pseudoinverse will have the correct 
00649  * dimension.
00650  */
00651 void mat_pseudoinv(a)
00652 MATRIX *a;
00653 {
00654   MATRIX *q2, *z, *tmp;
00655   float  **A, **Q2, *Z;
00656   float  z_min, z_max;
00657   int    M, N, i, j;
00658   float  **conv_2_nric_ptr();
00659 
00660   M = a->rows; N = a->cols;
00661 
00662   /* Allocate space for q2 matrix, vector Z[1..N], z and tmp
00663    */
00664   q2 = mat_malloc(N, N);
00665   z  = mat_malloc(N, N);
00666   Z  = vector(1, N);
00667 
00668   /* Create pointers to a and q2 conforming with Num-Rec-in-C format.
00669    */
00670   A  = conv_2_nric_ptr(a);
00671   Q2 = conv_2_nric_ptr(q2);
00672 
00673   /* Compute A[1..M][1..N]`s singular value decomposition (SVD): A = Q1*Z*Q2_tra
00674    *
00675    * Q1  will replace A, and the diagonal value of singular values Z is output
00676    * as a vector Z[1..N]. The matrix Q2 (not the transpose Q2_tra) is output 
00677    * as Q2[1..N][1..N]. M must be greater than or equal to N; If it is smaller, 
00678    * then A should be filled up to square with zero rows.
00679    */
00680   svdcmp(A, M, N, Z, Q2);
00681 
00682   /* (Singular values = squareroot of the eigenvalues), find maximum.
00683    */
00684   z_max = 0.0;
00685   for (i = 1; i <= N; i++) if (Z[i] > z_max) z_max = Z[i];
00686 
00687   /* Set threshold value of the minimum singular value allowed 
00688    * to be nonzero.
00689    */
00690   z_min = z_max*SVD_THRESHOLD;
00691 
00692   /* Invert while copying from the Z vector into the z+ matrix, and weed out 
00693    * the too small singular values.
00694    */
00695   for (i = 0; i < N; i++)
00696     for (j = 0; j < N; j++)
00697       z->p[i][j] = ((i == j) && Z[i+1] > z_min) ? 1.0/Z[i+1] : 0.0; 
00698      /* z->p[i][j] = 1.0/Z[i+1];*/
00699 
00700 
00701   /*                               
00702    * A_pseudoinv = Q2 * Z_pseudoinv * Q1_tra
00703    *
00704    * Returned matrix A from svdcmp() is actually Q1, therefore:
00705    */
00706 
00707 /* 
00708   printf("Testing the inverse:\n");
00709   q1t = mat_tra2(a);
00710   qq = mat_mul2(a,q1t);
00711   printf("Q1t*q1 = \n");
00712   mat_pr(qq);
00713   mat_free(qq);
00714   mat_free(q1t);
00715 */
00716 
00717 
00718   mat_tra(a);              /* Transpose Q1 to Q1_tra                          */
00719   tmp = mat_mul2(z, a);    /* tmp = Z_pseudoinv * Q1_tra                      */
00720   mat_mul(q2, tmp, a);     /* A_pseudoinv = Q2 * tmp = Q2 * Z_pseudo * Q1_tra */
00721 
00722 /*
00723   q2t = mat_tra2(q2);
00724   qq2 = mat_mul2(q2,q2t);
00725   printf("Q2t*Q2 = \n");
00726   mat_pr(qq2);
00727   mat_free(qq2);
00728   mat_free(q2t);
00729 */
00730 
00731 
00732 
00733   mat_free(q2);
00734   mat_free(z);
00735   mat_free(tmp);
00736   free_vector(Z, 1, N);
00737   free( (char *) A);
00738   free( (char *) Q2);
00739 
00740 }
00741 
00742 
00743 /* The pseudoinverted matrix will still reside in a. In the case of a
00744  * square matrix, the result will actually be the inverted matrix. If
00745  * the matrix is rectangular, the pseudoinverse will have the correct 
00746  * dimension.
00747  */
00748 
00749 
00750 double mat_det(a)
00751 MATRIX *a;
00752 {
00753   MATRIX *q2, *cp;
00754   float  **A, **Q2, *Z;
00755   int    M, N, i, j;
00756   float  **conv_2_nric_ptr();
00757   double det;
00758 
00759   M = a->rows; N = a->cols;
00760 
00761   /* Allocate space for q2 matrix, vector Z[1..N], z and tmp */
00762   cp = mat_cp2(a);
00763   q2 = mat_malloc(N, N);
00764   Z  = vector(1, N);
00765 
00766   /* Create pointers to a and q2 conforming with Num-Rec-in-C format.
00767    */
00768   A  = conv_2_nric_ptr(cp);
00769   Q2 = conv_2_nric_ptr(q2);
00770 
00771   /* Compute A[1..M][1..N]`s singular value decomposition (SVD): A = Q1*Z*Q2_tra
00772    *
00773    * Q1 will replace A, and the diagonal value of singular values Z is output
00774    * as a vector Z[1..N]. The matrix Q2 (not the transpose Q2_tra) is output 
00775    * as Q2[1..N][1..N]. M must be greater than or equal to N; If it is smaller, 
00776    * then A should be filled up to square with zero rows.
00777    */
00778   svdcmp(A, M, N, Z, Q2);
00779 
00780   /* (Singular values = squareroot of the eigenvalues of AtA), find maximum. */
00781     
00782   for(det=1.0,i=1;i<=N;i++)
00783        det *= (double) Z[i];
00784 
00785   mat_free(q2);
00786   mat_free(cp);
00787   free( (char *) A);
00788   free( (char *) Q2);
00789   free_vector(Z, 1, N);
00790 
00791   return(det);
00792 }
00793 
00794 
00795 double mat_eigen(a)
00796 MATRIX *a;
00797 {
00798   MATRIX *q2;
00799   float  **A, **Q2, *Z;
00800   float  z_min, z_max;
00801   int    M, N, i, j;
00802   float  **conv_2_nric_ptr();
00803 
00804   M = a->rows; N = a->cols;
00805 
00806   /* Allocate space for q2 matrix, vector Z[1..N]
00807    */
00808   q2 = mat_malloc(N, N);
00809   Z  = vector(1, N);
00810 
00811   /* Create pointers to a and q2 conforming with Num-Rec-in-C format.
00812    */
00813   A  = conv_2_nric_ptr(a);
00814   Q2 = conv_2_nric_ptr(q2);
00815 
00816   /* Compute A[1..M][1..N]`s singular value decomposition (SVD): A = Q1*Z*Q2_tra
00817    *
00818    * Q1  will replace A, and the diagonal value of singular values Z is output
00819    * as a vector Z[1..N]. The matrix Q2 (not the transpose Q2_tra) is output 
00820    * as Q2[1..N][1..N]. M must be greater than or equal to N; If it is smaller, 
00821    * then A should be filled up to square with zero rows.
00822    */
00823   svdcmp(A, M, N, Z, Q2);
00824 
00825   /* (Singular values = squareroot of the eigenvalues), find maximum.
00826    */
00827   z_max = 0.0;
00828   for (i = 1; i <= N; i++) if (Z[i] > z_max) z_max = Z[i];
00829 
00830   mat_free(q2);
00831   free_vector(Z, 1, N);
00832   free( (char *) A);
00833   free( (char *) Q2);
00834 
00835   return(z_max);
00836 }
00837 
00838 
00839 
00840 
00841 /* The 'c' matrix must already be declared float of size: arows x bcols.
00842  */
00843 void mat_mul(a, b, c)
00844 MATRIX *a, *b, *c;
00845 {
00846   int i, j, k;
00847 
00848   for (k = 0; k < b->cols; k++)
00849     for (i = 0; i < a->rows; i++)
00850     {
00851       c->p[i][k] = 0;
00852       for (j = 0; j < a->cols; j++)
00853         c->p[i][k] += a->p[i][j]*b->p[j][k];
00854     }
00855 }
00856 
00857 
00858 /* The function will automatically create the result matrix of correct
00859  * dimension. The pointer to this matrix structure is returned.
00860  */
00861 MATRIX *mat_mul2(a, b)
00862 MATRIX *a, *b;
00863 {
00864   MATRIX *c;
00865 
00866   c = mat_malloc(a->rows, b->cols);
00867 
00868   mat_mul(a, b, c);
00869 
00870   return(c);
00871 }
00872 
00873 
00874 /* The 'c' matrix must already be declared float of size: arows x bcols.
00875  *
00876  * c = a + b;
00877  */
00878 void mat_add(a, b, c)
00879 MATRIX *a, *b, *c;
00880 {
00881   float *p, *q, *r;
00882   int   i;
00883 
00884   p = *a->p; q = *b->p; r = *c->p;
00885 
00886   for (i = a->rows*a->cols; i--;)
00887     *r++ = *p++ + *q++; 
00888 }
00889 
00890 
00891 /* The function will automatically create the result matrix of correct
00892  * dimension. The pointer to this matrix structure is returned.
00893  *
00894  * c = a + b;
00895  */
00896 MATRIX *mat_add2(a, b)
00897 MATRIX *a, *b;
00898 {
00899   MATRIX *c;
00900 
00901   c = mat_malloc(a->rows, a->cols);
00902 
00903   mat_add(a, b, c);
00904 
00905   return(c);
00906 }
00907 
00908 
00909 /* The 'c' matrix must already be declared float of size: arows x acols.
00910  *
00911  * c = a - b;
00912  */
00913 void mat_sub(a, b, c)
00914 MATRIX *a, *b, *c;
00915 {
00916   float *p, *q, *r;
00917   int   i;
00918 
00919   p = *a->p; q = *b->p; r = *c->p;
00920 
00921   for (i = a->rows*a->cols; i--;)
00922     *r++ = *p++ - *q++; 
00923 }
00924 
00925 
00926 
00927 /* The function will automatically create the result matrix of correct
00928  * dimension. The pointer to this matrix structure is returned.
00929  *
00930  * c = a - b;
00931  */
00932 MATRIX *mat_sub2(a, b)
00933 MATRIX *a, *b;
00934 {
00935   MATRIX *c;
00936 
00937   c = mat_malloc(a->rows, a->cols);
00938 
00939   mat_sub(a, b, c);
00940 
00941   return(c);
00942 }
00943 
00944 
00945 
00946 /* The matrix 'a' is scaled by the factor 'c'
00947  */
00948 void mat_sca(a, c)
00949 MATRIX *a;
00950 float  c;
00951 {
00952   float *p;
00953   int   i;
00954 
00955   p = *a->p;
00956 
00957   for (i = a->rows*a->cols; i--;)
00958     *p++ *= c; 
00959 }
00960 
00961 
00962 
00963 /* The transposed matrix still resides in 'a' after transposition
00964  */
00965 void mat_tra(a)
00966 MATRIX *a;
00967 {
00968   int   i, j, temp;
00969   float *p;
00970 
00971   if (a->rows == a->cols)              /* Square matrix */
00972   {
00973     for (i = a->rows-1; i--;)
00974       for (j = a->cols-1; j > i; j--)
00975         SWAP(a->p[i][j], a->p[j][i]);
00976   }
00977   else                                 /* Rectangular matrix */
00978   {
00979     temp = a->rows; 
00980     a->rows = a->cols; 
00981     a->cols = temp;
00982 
00983     /* Recompute pointers to the new rows of the matrix
00984      */
00985     p = *a->p;
00986     for(i = 0; i < a->rows; i++)
00987     {
00988       a->p[i] = p; 
00989       p += a->cols;
00990     }
00991 
00992     /* No need to swap elements if the matrix has only one row or column.
00993      */
00994     if (!((a->rows == 1) || (a->cols == 1)))
00995     {
00996       MATRIX *m;
00997 
00998       /*...otherwise put elements in temporary matrix and
00999        * copy from it into the columns of the transposed matrix.
01000        */
01001       m = mat_malloc(a->rows, a->cols);
01002       mat_cp(a,m);
01003       p = *m->p;
01004 
01005       for (j = 0; j < a->cols; j++)
01006         for (i = 0; i < a->rows; i++)
01007           a->p[i][j] = *p++;
01008 
01009       mat_free(m);
01010     }    
01011   }
01012 }
01013 
01014 
01015 /* The function will automatically create the result matrix of correct
01016  * dimension which will be the transpose of A. The pointer to this matrix 
01017  * structure is returned.
01018  */
01019 MATRIX *mat_tra2(A)
01020 MATRIX *A;
01021 {
01022   int   i, j;
01023   MATRIX *At;
01024 
01025   At = mat_malloc(A->cols, A->rows);
01026 
01027   for (i = A->rows-1; i--;)
01028     for (j = A->cols-1; j > i; j--)
01029       At->p[i][j] = A->p[j][i];
01030 
01031   return(At);
01032 }
01033 
01034 
01035 /* The copied matrix 'cpy' must already be declared float of 
01036  * same size as 'a'.
01037  */
01038 void mat_cp(a, cpy)
01039 MATRIX *a, *cpy;
01040 {
01041   float *p, *q;
01042   int   i;
01043 
01044   p = *a->p; q = *cpy->p;
01045 
01046   for (i = a->rows*a->cols; i--;)
01047     *q++ = *p++; 
01048 }
01049 
01050 
01051 
01052 /* The function will automatically create the result matrix of correct
01053  * dimension . The pointer to this matrix structure is returned.
01054  */
01055 MATRIX *mat_cp2(a)
01056 MATRIX *a;
01057 {
01058   int   i;
01059   float *p, *q;
01060   MATRIX *cpy;
01061 
01062   cpy = mat_malloc(a->rows, a->cols);
01063 
01064   mat_cp(a, cpy);
01065 
01066   return(cpy);
01067 }
01068 
01069 
01070 
01071 /* Returns an pointer which points to an array of pointers to matrix row 
01072  * elements in a way so that the matrix a->p[0..n][0..m] can be accessed
01073  * from [1..n-1][1..m-1] which is required by the Numerical Rec. i C.
01074  */
01075 float **conv_2_nric_ptr(a)
01076 MATRIX *a;
01077 {
01078   float **new_ptr_2_row;
01079   int   i;
01080 
01081   /* Allocate space for an array of OFFSET pointers.
01082    */
01083   new_ptr_2_row = (float **) malloc((a->rows + 1) * sizeof(float *));
01084 
01085   /* The array of pointers to row must be offset by -1
01086    */
01087   for (i = 0; i < a->rows; i++)
01088     new_ptr_2_row[i+1] = a->p[i] - 1;
01089 
01090   /* To not have element[0][] dangling, let it point to a->p[0][0].
01091    */
01092   new_ptr_2_row[0] = a->p[0];
01093 
01094   return( new_ptr_2_row );
01095 }
01096 
01097 
01098 
01099 /* Free pointer pointing to the matrix in Numerical-Rec.-in-C-format
01100  */
01101 void free_nric_ptr(p)
01102 float **p;
01103 {
01104   free( (char *)  p);
01105 }
01106 
01107 
01108 
01109 /* Returns vector dot product of the two vectors: row 0 of matrix a and b.
01110  */
01111 float mat_vec_dot(a, ar, b, br)
01112 MATRIX *a, *b;
01113 int ar, br;
01114 {
01115   int i;
01116   float d = 0;
01117 
01118   for (i = 0; i < a->cols; i++) 
01119     d += a->p[ar][i] * b->p[br][i];
01120 
01121   return( d );
01122 }
01123 
01124 
01125 
01126 /* Returns vector cross product of the two vectors: row ra, rb of matrix a and b.
01127  * Result vector matrix c must be of size [1][m] or [n][m].
01128  */
01129 void mat_vec_cross(a, ar, b, br, c)
01130 MATRIX *a, *b, *c;
01131 int ar, br;
01132 {
01133   c->p[0][0] = a->p[ar][1] * b->p[br][2] - a->p[ar][2] * b->p[br][1];
01134   c->p[0][1] = a->p[ar][2] * b->p[br][0] - a->p[ar][0] * b->p[br][2];
01135   c->p[0][2] = a->p[ar][0] * b->p[br][1] - a->p[ar][1] * b->p[br][0];
01136 }
01137 
01138 
01139 
01140 /* returns length (absolute value) of the vector: row r of matrix a.
01141  */
01142 float mat_vec_abs(a, r)
01143 MATRIX *a;
01144 int r;
01145 {
01146   int i;
01147   float d = 0;
01148 
01149   for (i = 0; i < a->cols; i++) 
01150     d += a->p[r][i] * a->p[r][i];
01151 
01152   return( sqrt(d) );
01153 }

Generated on Thu Jul 29 15:56:35 2004 for OpenSim by doxygen 1.3.6