Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/collision_detection/lin_alg.h @ 5489

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

orxonox/trunk/src/lib/collision: rearanged the memory management and working on wrong array indexes…

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