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 |
|
---|
23 | static
|
---|
24 | bool 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 |
|
---|
161 | bool 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 | }
|
---|