source: GTP/trunk/Lib/Vis/Preprocessing/src/mixkit/MxMat4-jacobi.cxx @ 1097

Revision 1097, 3.8 KB checked in by mattausch, 18 years ago (diff)
Line 
1/************************************************************************
2
3  Jacobi iteration on 4x4 matrices.
4
5  Copyright (C) 1998 Michael Garland.  See "COPYING.txt" for details.
6
7  NOTE: This code was adapted from VTK source code (vtkMath.cxx) which
8        seems to have been adapted directly from Numerical Recipes in C.
9        See Hoppe's Recon software for an alternative adaptation of the
10        Numerical Recipes code.
11 
12  $Id: MxMat4-jacobi.cxx,v 1.1 2002/09/24 16:53:54 wimmer Exp $
13
14 ************************************************************************/
15
16#include "stdmix.h"
17#include "MxMat4.h"
18
19#define ROT(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);a[k][l]=h+s*(g-h*tau);
20
21#define MAX_ROTATIONS 60
22
23static
24bool internal_jacobi4(double a[4][4], double w[4], double v[4][4])
25{
26    int i, j, k, iq, ip;
27    double tresh, theta, tau, t, sm, s, h, g, c;
28    double b[4], z[4], tmp;
29
30    // initialize
31    for (ip=0; ip<4; ip++)
32    {
33        for (iq=0; iq<4; iq++) v[ip][iq] = 0.0;
34        v[ip][ip] = 1.0;
35    }
36    for (ip=0; ip<4; ip++)
37    {
38        b[ip] = w[ip] = a[ip][ip];
39        z[ip] = 0.0;
40    }
41
42    // begin rotation sequence
43    for (i=0; i<MAX_ROTATIONS; i++)
44    {
45        sm = 0.0;
46        for (ip=0; ip<3; ip++)
47        {
48            for (iq=ip+1; iq<4; iq++) sm += fabs(a[ip][iq]);
49        }
50        if (sm == 0.0) break;
51
52        if (i < 4) tresh = 0.2*sm/(16);
53        else tresh = 0.0;
54
55        for (ip=0; ip<3; ip++)
56        {
57            for (iq=ip+1; iq<4; iq++)
58            {
59                g = 100.0*fabs(a[ip][iq]);
60                if (i > 4 && (fabs(w[ip])+g) == fabs(w[ip])
61                    && (fabs(w[iq])+g) == fabs(w[iq]))
62                {
63                    a[ip][iq] = 0.0;
64                }
65                else if (fabs(a[ip][iq]) > tresh)
66                {
67                    h = w[iq] - w[ip];
68                    if ( (fabs(h)+g) == fabs(h)) t = (a[ip][iq]) / h;
69                    else
70                    {
71                        theta = 0.5*h / (a[ip][iq]);
72                        t = 1.0 / (fabs(theta)+sqrt(1.0+theta*theta));
73                        if (theta < 0.0) t = -t;
74                    }
75                    c = 1.0 / sqrt(1+t*t);
76                    s = t*c;
77                    tau = s/(1.0+c);
78                    h = t*a[ip][iq];
79                    z[ip] -= h;
80                    z[iq] += h;
81                    w[ip] -= h;
82                    w[iq] += h;
83                    a[ip][iq]=0.0;
84                    for (j=0;j<ip-1;j++)
85                    {
86                        ROT(a,j,ip,j,iq)
87                            }
88                    for (j=ip+1;j<iq-1;j++)
89                    {
90                        ROT(a,ip,j,j,iq)
91                            }
92                    for (j=iq+1; j<4; j++)
93                    {
94                        ROT(a,ip,j,iq,j)
95                            }
96                    for (j=0; j<4; j++)
97                    {
98                        ROT(v,j,ip,j,iq)
99                            }
100                }
101            }
102        }
103
104        for (ip=0; ip<4; ip++)
105        {
106            b[ip] += z[ip];
107            w[ip] = b[ip];
108            z[ip] = 0.0;
109        }
110    }
111
112    if ( i >= MAX_ROTATIONS )
113    {
114        mxmsg_signal(MXMSG_WARN, "Error computing eigenvalues.", "jacobi");
115        return false;
116    }
117
118    // sort eigenfunctions
119    for (j=0; j<4; j++)
120    {
121        k = j;
122        tmp = w[k];
123        for (i=j; i<4; i++)
124        {
125            if (w[i] >= tmp)
126            {
127                k = i;
128                tmp = w[k];
129            }
130        }
131        if (k != j)
132        {
133            w[k] = w[j];
134            w[j] = tmp;
135            for (i=0; i<4; i++)
136            {
137                tmp = v[i][j];
138                v[i][j] = v[i][k];
139                v[i][k] = tmp;
140            }
141        }
142    }
143    // insure eigenvector consistency (i.e., Jacobi can compute vectors that
144    // are negative of one another (.707,.707,0) and (-.707,-.707,0). This can
145    // reek havoc in hyperstreamline/other stuff. We will select the most
146    // positive eigenvector.
147    int numPos;
148    for (j=0; j<4; j++)
149    {
150        for (numPos=0, i=0; i<4; i++) if ( v[i][j] >= 0.0 ) numPos++;
151        if ( numPos < 3 ) for(i=0; i<4; i++) v[i][j] *= -1.0;
152    }
153
154    return true;
155}
156
157
158#undef ROT
159#undef MAX_ROTATIONS
160
161bool jacobi(const Mat4& m, Vec4& eig_vals, Vec4 eig_vecs[4])
162{
163    double a[4][4], w[4], v[4][4];
164    int i,j;
165
166    for(i=0;i<4;i++) for(j=0;j<4;j++) a[i][j] = m(i,j);
167
168    bool result = internal_jacobi4(a, w, v);
169    if( result )
170    {
171        for(i=0;i<4;i++) eig_vals[i] = w[i];
172
173        for(i=0;i<4;i++) for(j=0;j<4;j++) eig_vecs[i][j] = v[j][i];
174    }
175
176    return result;
177}
Note: See TracBrowser for help on using the repository browser.