Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/network/src/lib/collision_detection/lin_alg.h @ 5730

Last change on this file since 5730 was 5647, checked in by patrick, 19 years ago

network: modiefied the unit test to enable diffrent modes, extended the NetworkStream constructors interface and NetworkManager interface

File size: 15.9 KB
Line 
1/*!
2 * @file lin_alg.h
3  *  Definition of some important linear algebra formulas
4
5    compute the eigenpairs (eigenvalues and eigenvectors) of a real symmetric matrix "A" by the Jacobi method
6 */
7
8
9/**
10 *  function that calculates the eigenvectors from a given symmertical 3x3 Matrix
11 * @arg A: Matrix
12 * @arg D: Eigenvectors
13 */
14void eigenVectors(float** matrix, float **vectors)
15{
16  /* map variables to other names, so they can be processed more easely */
17  float a = matrix[0][0];
18  float b = matrix[0][1];
19  float c = matrix[0][2];
20  float d = matrix[1][1];
21  float e = matrix[1][2];
22  float f = matrix[2][2];
23 
24  /* first eigenvector */
25  vectors[0][0] = -1/c * (f - /*Root*/ (c*c*d - 2*b*c + a*e*e + b*b*f - a*d*f - 
26                  b*b - c*c + a*d - e*e + a*f ));
27}
28
29
30
31/************************************************************
32* This subroutine computes all eigenvalues and eigenvectors *
33* of a real symmetric square matrix A(N,N). On output, ele- *
34* ments of A above the diagonal are destroyed. D(N) returns *
35* the eigenvalues of matrix A. V(N,N) contains, on output,  *
36* the eigenvectors of A by columns. THe normalization to    *
37* unity is made by main program before printing results.    *
38* NROT returns the number of Jacobi matrix rotations which  *
39* were required.                                            *
40* --------------------------------------------------------- *
41* Ref.:"NUMERICAL RECIPES IN FORTRAN, Cambridge University  *
42*       Press, 1986, chap. 11, pages 346-348".              *
43*                                                           *
44*                         C++ version by J-P Moreau, Paris. *
45************************************************************/
46void JacobI(float **A, float *D, float **V, int *NROT) {
47
48int N = 3;
49
50float  *B, *Z;
51double  c=0.0f, g=0.0f, h=0.0f, s=0.0f, sm=0.0f, t=0.0f, tau=0.0f, theta=0.0f, tresh=0.0f;
52int     i = 0, j = 0, ip = 0, iq = 0;
53
54  //allocate vectors B, Z
55  B = new float[N];
56  Z = new float[N];
57
58  // initialize V to identity matrix
59  for( ip = 0; ip < N; ip++) {
60    for( iq = 0; iq < N; iq++)
61      V[ip][iq] = 0.0f;
62    V[ip][ip] = 1.0f;
63  }
64  // initialize B,D to the diagonal of A
65  for( ip = 0; ip < N; ip++) {
66    B[ip] = A[ip][ip];
67    D[ip] = B[ip];
68    Z[ip] = 0.0f;
69  }
70
71  *NROT = 0;
72  // make maximaly 50 iterations
73  for( i = 1; i <= 50; i++) {
74    sm = 0.0f;
75
76    // sum off-diagonal elements
77    for( ip = 0; ip < N - 1; ip++)
78      for( iq = ip + 1; iq < N; iq++)
79        sm += fabs(A[ip][iq]);
80
81    // is it already a diagonal matrix?
82    if( sm == 0)
83    {
84      delete[] B;
85      delete[] Z;
86      return;
87    }
88    // just adjust this on the first 3 sweeps
89    if( i < 4)
90      tresh = 0.2 * sm / (N * N) ;
91    else
92      tresh = 0.0f;
93
94    for( ip = 0; ip < (N-1); ip++) {
95      for( iq = ip + 1; iq < N; iq++) {
96
97        g = 100.0f * fabs(A[ip][iq]);
98        // after 4 sweeps, skip the rotation if the off-diagonal element is small
99        if( (i > 4) && ( fabs(D[ip]) + g == fabs(D[ip]) ) && ( fabs(D[iq]) + g == fabs(D[iq]) ) )
100          A[ip][iq] = 0.0f;
101        else if( fabs(A[ip][iq]) > tresh) {
102          h = D[iq] - D[ip];
103          if (fabs(h) + g == fabs(h))
104            t = A[ip][iq] / h;
105          else {
106            theta = 0.5f * h / A[ip][iq];
107            t = 1.0f / (fabs(theta) + sqrt(1.0f + theta * theta));
108            if( theta < 0.0f)
109              t = -t;
110          }
111          c = 1.0f / sqrt(1.0f + t * t);
112          s = t * c;
113          tau = s / (1.0f + c);
114          h = t * A[ip][iq];
115          Z[ip] -= h;
116          Z[iq] += h;
117          D[ip] -= h;
118          D[iq] += h;
119          A[ip][iq] = 0.0f;
120
121          for( j = 0; j < (ip - 1); j++) {
122            g = A[j][ip];
123            h = A[j][iq];
124            A[j][ip] = g - s * (h + g * tau);
125            A[j][iq] = h + s * (g - h * tau);
126          }
127          for( j = (ip + 1); j < (iq - 1); j++) {
128            g = A[ip][j];
129            h = A[j][iq];
130            A[ip][j] = g - s * (h + g * tau);
131            A[j][iq] = h + s * (g - h * tau);
132          }
133          for( j = (iq + 1); j < N; j++) {
134            g = A[ip][j];
135            h = A[iq][j];
136            A[ip][j] = g - s * (h + g * tau);
137            A[iq][j] = h + s * (g - h * tau);
138          }
139          for( j = 0; j < N; j++) {
140            g = V[j][ip];
141            h = V[j][iq];
142            V[j][ip] = g - s * (h + g * tau);
143            V[j][iq] = h + s * (g - h * tau);
144          }
145          *NROT += 1;
146        } //end ((i.gt.4)...else if
147      } // main iq loop
148    } // main ip loop
149    for( ip = 0; ip < N; ip++) {
150      B[ip] += Z[ip];
151      D[ip] = B[ip];
152      Z[ip] = 0.0f;
153    }
154  } //end of main i loop
155  delete[] B;
156  delete[] Z;
157  return;  //too many iterations
158}
159
160
161
162
163
164#include "abstract_model.h"
165
166#include <stdio.h>
167#include <math.h>
168
169#define NDIM 3
170
171
172typedef float MatrixX[3][3];
173
174//
175// class "EVJacobi" for computing the eigenpairs
176// (members)
177//   ndim  int    ...  dimension
178//       "ndim" must satisfy 1 < ndim < NDIM
179//   ("NDIM" is given above).
180//   a     double [NDIM][NDIM] ...  matrix A
181//   aa    double ...  the square root of
182//                  (1/2) x (the sum of the off-diagonal elements squared)
183//   ev    double [NDIM] ...  eigenvalues
184//   evec  double [NDIM][NDIM] ... eigenvectors
185//       evec[i][k], i=1,2,...,ndim are the elements of the eigenvector
186//       corresponding to the k-th eigenvalue ev[k]
187//   vec   double [NDIM][NDIM] ... the 2-dimensional array where the matrix elements are stored
188//   lSort     int      ...
189//       If lSort = 1, sort the eigenvalues d(i) in the descending order, i.e.,
190//                       ev[1] >= ev[2] >= ... >= ev[ndim], and
191//       if lSort = 0, in the ascending order, i.e.,
192//                       ev[1] <= ev[2] <= ... <= ev[ndim].
193//   lMatSize  int      ...  If 1 < ndim < NDIM, lMatSize = 1
194//                            otherwise, lMatSize = 0
195//   p     int [NDIM]    ...  index vector for sorting the eigenvalues
196// (public member functions)
197//   setMatrix          void ...  give the matrix A
198//   getEigenValue      void ...  get the eigenvalues
199//   getEigenVector     void ...  get the eigenvectors
200//   sortEigenpair      void ...  sort the eigenpairs
201// (private member functions)
202//   ComputeEigenpair   void ...  compute the eigenpairs
203//   matrixUpdate       void ...  each step of the Jacobi method, i.e.,
204//                          update of the matrix A by Givens' transform.
205//   getP               void ...  get the index vector p, i.e., sort the eigenvalues.
206//   printMatrix        void ...  print the elements of the matrix A.
207//
208
209class EVJacobi
210{
211  public:
212    void setMatrix(int, double [][NDIM], int, int);
213    void getEigenValue(double []);
214    void getEigenVector(double [][NDIM]);
215    void sortEigenpair(int);
216
217  private:
218    void ComputeEigenpair(int);
219    void matrixUpdate();
220    void getP();
221    void printMatrix();
222
223  private:
224    double a[NDIM][NDIM], aa, ev[NDIM], evec[NDIM][NDIM], vec[NDIM][NDIM];
225    int ndim, lSort, p[NDIM], lMatSize;
226};
227
228//------------public member function of the class "EVJacobi"------------------------------
229//
230// give the dimension "ndim" and the matrix "A" and compute the eigenpairs
231// (input)
232// ndim0    int      ... dimension
233// a0     double[][NDIM]  matrix A
234// lSort0  int      ... lSort
235//       If lSort = 1, sort the eigenvalues d(i) in the descending order, i.e.,
236//                       ev[1] >= ev[2] >= ... >= ev[ndim], and
237//       if lSort = 0, in the ascending order, i.e.,
238//                       ev[1] <= ev[2] <= ... <= ev[ndim].
239// l_print  int      ...
240//       If l_print = 1, print the matrices during the iterations.
241//
242void EVJacobi::setMatrix(int ndim0, double a0[][NDIM], int lSort0, int l_print)
243{
244  ndim = ndim0;
245  if (ndim < NDIM && ndim > 1)
246  {
247    lMatSize = 1;
248    lSort = lSort0;
249    for (int i=1; i<=ndim; ++i)
250      for (int j=1; j<=ndim; ++j)
251        a[i][j] = a0[i][j];
252    //
253    aa = 0.0;
254    for (int i=1; i<=ndim; ++i)
255      for (int j=1; j<=i-1; ++j)
256        aa += a[i][j]*a[i][j];
257    aa = sqrt(aa);
258    //
259    ComputeEigenpair(l_print);
260    getP();
261  }
262  else
263  {
264    lMatSize = 0;
265    printf("ndim = %d\n", ndim);
266    printf("ndim must satisfy 1 < ndim < NDIM=%d\n", NDIM);
267  }
268}
269//
270// get the eigenvalues
271// (input)
272// ev0[NDIM] double ...  the array where the eigenvalues are written
273void EVJacobi::getEigenValue(double ev0[])
274{
275  for (int k=1; k<=ndim; ++k) ev0[k] = ev[p[k]];
276}
277//
278// get the eigenvectors
279// (input)
280// evec0[NDIM][NDIM] double ...  the two-dimensional array
281//   where the eigenvectors are written in such a way that
282//   evec0[k][i], i=1,2,...,ndim are the elements of the eigenvector
283//   corresponding to the k-th eigenvalue ev0[k]
284//
285void EVJacobi::getEigenVector(double evec0[][NDIM])
286{
287  for (int k=1; k<=ndim; ++k)
288    for (int i=1; i<=ndim; ++i)
289      evec0[k][i] = evec[p[k]][i];
290}
291//
292// sort the eigenpairs
293// (input)
294// lSort0  int
295//   If lSort0 = 1, the eigenvalues are sorted in the descending order, i.e.,
296//      ev0[1] >= ev0[2] >= ... >= ev0[ndim]
297//   and if lSort0 = 0, in the ascending order, i.e.,
298//      ev0[1] <= ev0[2] <= ... <= ev0[ndim]
299//
300void EVJacobi::sortEigenpair(int lSort0)
301{
302  lSort = lSort0;
303  getP();
304}
305//-------private member function of the class "EVJacobi"-----
306//
307// compute the eigenpairs
308// (input)
309// l_print  int
310//    If l_print = 1, print the matrices during the iterations.
311//
312void EVJacobi::ComputeEigenpair(int l_print)
313{
314  if (lMatSize==1)
315  {
316    if (l_print==1)
317    {
318      printf("step %d\n", 0);
319      printMatrix();
320      printf("\n");
321    }
322    //
323    double eps = 1.0e-15, epsa = eps * aa;
324    int kend = 1000, l_conv = 0;
325    //
326    for (int i=1; i<=ndim; ++i)
327      for (int j=1; j<=ndim; ++j)
328        vec[i][j] = 0.0;
329    for (int i=1; i<=ndim; ++i)
330      vec[i][i] = 1.0;
331    //
332    for (int k=1; k<=kend; ++k)
333    {
334      matrixUpdate();
335      double a1 = 0.0;
336      for (int i=1; i<=ndim; ++i)
337        for (int j=1; j<=i-1; ++j)
338          a1 += a[i][j] * a[i][j];
339      a1 = sqrt(a1);
340      if (a1 < epsa)
341      {
342        if (l_print==1)
343        {
344          printf("converged at step %d\n", k);
345          printMatrix();
346          printf("\n");
347        }
348        l_conv = 1;
349        break;
350      }
351      if (l_print==1)
352        if (k%10==0)
353      {
354        printf("step %d\n", k);
355        printMatrix();
356        printf("\n");
357      }
358    }
359    //
360    if (l_conv == 0) printf("Jacobi method not converged.\n");
361    for (int k=1; k<=ndim; ++k)
362    {
363      ev[k] = a[k][k];
364      for (int i=1; i<=ndim; ++i) evec[k][i] = vec[i][k];
365    }
366  }
367}
368//
369void EVJacobi::printMatrix()
370{
371  for (int i=1; i<=ndim; ++i)
372  {
373    for (int j=1; j<=ndim; ++j) printf("%8.1e ",a[i][j]);
374    printf("\n");
375  }
376}
377//
378void EVJacobi::matrixUpdate()
379{
380  double a_new[NDIM][NDIM], vec_new[NDIM][NDIM];
381  //
382  int p=2, q=1;
383  double amax = fabs(a[p][q]);
384  for (int i=3; i<=ndim; ++i)
385    for (int j=1; j<=i-1; ++j)
386      if (fabs(a[i][j]) > amax)
387  {
388    p = i;
389    q = j;
390    amax = fabs(a[i][j]);
391  }
392  //
393        // Givens' rotation by Rutishauser's rule
394  //
395  double z, t, c, s, u;
396  z = (a[q][q]  - a[p][p]) / (2.0 * a[p][q]);
397  t = fabs(z) + sqrt(1.0 + z*z);
398  if (z < 0.0) t = - t;
399  t = 1.0 / t;
400  c = 1.0 / sqrt(1.0 + t*t);
401  s = c * t;
402  u = s / (1.0 + c);
403  //
404  for (int i=1; i<=ndim; ++i)
405    for (int j=1; j<=ndim; ++j)
406      a_new[i][j] = a[i][j];
407  //
408  a_new[p][p] = a[p][p] - t * a[p][q];
409  a_new[q][q] = a[q][q] + t * a[p][q];
410  a_new[p][q] = 0.0;
411  a_new[q][p] = 0.0;
412  for (int j=1; j<=ndim; ++j)
413    if (j!=p && j!=q)
414  {
415    a_new[p][j] = a[p][j] - s * (a[q][j] + u * a[p][j]);
416    a_new[j][p] = a_new[p][j];
417    a_new[q][j] = a[q][j] + s * (a[p][j] - u * a[q][j]);
418    a_new[j][q] = a_new[q][j];
419  }
420  //
421  for (int i=1; i<=ndim; ++i)
422  {
423    vec_new[i][p] = vec[i][p] * c - vec[i][q] * s;
424    vec_new[i][q] = vec[i][p] * s + vec[i][q] * c;
425    for (int j=1; j<=ndim; ++j)
426      if (j!=p && j!=q) vec_new[i][j] = vec[i][j];
427  }
428  //
429  for (int i=1; i<=ndim; ++i)
430    for (int j=1; j<=ndim; ++j)
431  {
432    a[i][j] = a_new[i][j];
433    vec[i][j] = vec_new[i][j];
434  }
435}
436//
437// sort the eigenpairs
438//   If l_print=1, sort the eigenvalues in the descending order, i.e.,
439//      ev[1] >= ev[2] >= ... >= ev[ndim], and
440//   if l_print=0, in the ascending order, i.e.,
441//      ev[1] <= ev[2] <= ... <= ev[ndim].
442//
443void EVJacobi::getP()
444{
445  for (int i=1; i<=ndim; ++i) p[i] = i;
446  //
447  if (lSort==1)
448  {
449    for (int k=1; k<=ndim; ++k)
450    {
451      double emax = ev[p[k]];
452      for (int i=k+1; i<=ndim; ++i)
453      {
454        if (emax < ev[p[i]])
455        {
456          emax = ev[p[i]];
457          int pp = p[k];
458          p[k] = p[i];
459          p[i] = pp;
460        }
461      }
462    }
463  }
464  if (lSort==0)
465  {
466    for (int k=1; k<=ndim; ++k)
467    {
468      double emin = ev[p[k]];
469      for (int i=k+1; i<=ndim; ++i)
470      {
471        if (emin > ev[p[i]])
472        {
473          emin = ev[p[i]];
474          int pp = p[k];
475          p[k] = p[i];
476          p[i] = pp;
477        }
478      }
479    }
480  }
481}
482
483
484
485// void jacobi(float **A, float *D, float **V, int *nRot) {
486//
487// int n = 3;
488//
489// float   *B, *Z;
490// double  c=0.0f, g=0.0f, h=0.0f, s=0.0f, sm=0.0f, t=0.0f, tau=0.0f, theta=0.0f, tresh=0.0f;
491// int     i = 0, j = 0, ip = 0, iq = 0;
492//
493//   //void *vmblock1 = NULL;
494//
495//   //allocate vectors B, Z
496//   //vmblock1 = vminit();
497//   //B = (float *) vmalloc(vmblock1, VEKTOR,  100, 0);
498//   //Z = (float *) vmalloc(vmblock1, VEKTOR,  100, 0);
499//   B = new float[n+1];
500//   Z = new float[n+1];
501//
502//    //initialize V to identity matrix
503//   for(int i = 1; i <= n; i++)
504//   {
505//     for(int j = 1; j <= n; j++)
506//         V[i][j] = 0;
507//     V[i][i] = 1;
508//   }
509//
510//   for(int i = 1; i <= n; i++)
511//   {
512//     B[i] = A[i][i];
513//     D[i] = B[i];
514//     Z[i] = 0;
515//   }
516//
517//   *nRot = 0;
518//   for(int i = 1; i<=50; i++)
519//   {
520//     sm = 0;
521//     for(int k = 1; k < n; k++)    //sum off-diagonal elements
522//       for (int l = k + 1; l <= n; k++)
523//         sm = sm + fabs(A[k][l]);
524//     if ( sm == 0 )
525//     {
526//       //vmfree(vmblock1);
527//       delete[] B;
528//       delete[] Z;
529//       return;       //normal return
530//     }
531//     if (i < 4)
532//       tresh = 0.2 * sm * sm;
533//     else
534//       tresh = 0;
535//     for(int k = 1; k < n; k++)
536//     {
537//       for (iq=ip+1; iq<=n; iq++) {
538//         g=100*fabs(A[ip][iq]);
539// // after 4 sweeps, skip the rotation if the off-diagonal element is small
540//         if ((i > 4) && (fabs(D[ip])+g == fabs(D[ip])) && (fabs(D[iq])+g == fabs(D[iq])))
541//           A[ip][iq]=0;
542//         else if (fabs(A[ip][iq]) > tresh) {
543//           h=D[iq]-D[ip];
544//           if (fabs(h)+g == fabs(h))
545//             t=A[ip][iq]/h;
546//           else {
547//             theta=0.5*h/A[ip][iq];
548//             t=1/(fabs(theta)+sqrt(1.0+theta*theta));
549//             if (theta < 0)  t=-t;
550//           }
551//           c=1.0/sqrt(1.0+t*t);
552//           s=t*c;
553//           tau=s/(1.0+c);
554//           h=t*A[ip][iq];
555//           Z[ip] -= h;
556//           Z[iq] += h;
557//           D[ip] -= h;
558//           D[iq] += h;
559//           A[ip][iq]=0;
560//           for (j=1; j<ip; j++) {
561//             g=A[j][ip];
562//             h=A[j][iq];
563//             A[j][ip] = g-s*(h+g*tau);
564//             A[j][iq] = h+s*(g-h*tau);
565//           }
566//           for (j=ip+1; j<iq; j++) {
567//             g=A[ip][j];
568//             h=A[j][iq];
569//             A[ip][j] = g-s*(h+g*tau);
570//             A[j][iq] = h+s*(g-h*tau);
571//           }
572//           for (j=iq+1; j<=n; j++) {
573//             g=A[ip][j];
574//             h=A[iq][j];
575//             A[ip][j] = g-s*(h+g*tau);
576//             A[iq][j] = h+s*(g-h*tau);
577//           }
578//           for (j=1; j<=n; j++) {
579//             g=V[j][ip];
580//             h=V[j][iq];
581//             V[j][ip] = g-s*(h+g*tau);
582//             V[j][iq] = h+s*(g-h*tau);
583//           }
584//           *nRot=*nRot+1;
585//         } //end ((i.gt.4)...else if
586//       } // main iq loop
587//     } // main ip loop
588//     for (ip=1; ip<=n; ip++) {
589//       B[ip] += Z[ip];
590//       D[ip]=B[ip];
591//       Z[ip]=0;
592//     }
593//   } //end of main i loop
594//   printf("\n 50 iterations !\n");
595//   //vmfree(vmblock1);
596//   delete[] Z;
597//   delete[] B;
598//   return;  //too many iterations
599// }
600
Note: See TracBrowser for help on using the repository browser.