| Bsoft 2.0.5 Bernard's software package

matrix.cpp
Go to the documentation of this file.
1
9 #include "Matrix.h"
10 #include "matrix_linear.h"
11 #include "math_util.h"
12 #include "random_numbers.h"
13 #include "utilities.h"
14
15 // Declaration of global variables
16 extern int verbose; // Level of output to the screen
17
18 ostream& operator<<(ostream& output, Matrix& mat) {
19 output.setf(ios::fixed, ios::floatfield);
20 output.precision(4);
21 long i, j;
22 for ( i=0; i<mat.rows(); i++ ) {
23 for ( j=0; j<mat.columns(); j++ )
24 output << "\t" << mat[i][j];
25 output << endl;
26 }
27 return output;
28 }
29
30 /*int Matrix::multiply_in_place(double* vec)
31 {
32 long i, j;
33
34 double* t = new double[n];
35
36 for ( i=0; i<n; i++ ) {
37 t[i] = 0;
38 for ( j=0; j<n; j++ )
39 t[i] += p[i][j]*vec[j];
40 }
41
42 for ( i=0; i<n; i++ ) vec[i] = t[i];
43
44 delete[] t;
45
46 return 0;
47 }*/
48
49 int Matrix::multiply_in_place(vector<double>& vec)
50 {
51 if ( vec.size() != n ) return -1;
52
53 long i, j;
54
55 vector<double> t(n);
56
57 for ( i=0; i<n; i++ ) {
58 t[i] = 0;
59 for ( j=0; j<n; j++ )
60 t[i] += p[i][j]*vec[j];
61 }
62
63 for ( i=0; i<n; i++ ) vec[i] = t[i];
64
65 return 0;
66 }
67
78 double Matrix::LU_decomposition()
79 {
80 if ( m != n ) {
81 cerr << "Error: rows:" << m << " != columns:" << n << endl;
82 return 0;
83 }
84
85 long i, j, k, ibig;
86 double big, det(1);
87 vector<long> ind(n);
88 vector<double> x(n);
89 Matrix a(n,n);
90
91 for ( i=0; i<n; i++ ) x[i] = ind[i] = 0;
92
93 if ( verbose & VERB_DEBUG )
94 cout << "DEBUG Matrix::LU_decomposition: n = " << n << endl;
95
96 // Find the largest element in each row for scaling and pivoting
97 // Additionally test for singularity
98 for ( i=0; i<n; i++ ) {
99 ind[i] = i; // Initialize the indices for tracking pivoting
100 big = 0;
101 for ( j=0; j<n; j++ )
102 if ( big < fabs(p[i][j]) ) big = fabs(p[i][j]);
103 if ( big < 1e-37 ) {
104 cerr << "Error: Singular matrix in Matrix::LU_decomposition" << endl;
105 // if ( verbose & VERB_DEBUG ) {
106 cerr << *this << endl;
107 // bexit(-1);
108 // }
109 return -1e30;
110 } else
111 x[i] = 1.0/big;
112 }
113
114 // The LU decomposition
115 for ( j=0; j<n; j++ ) {
116 for ( i=0; i<j; i++ ) { // Calculating the upper triangle
117 for ( k=0; k<i; k++ ) // not the diagonal
118 p[i][j] -= p[i][k]*p[k][j];
119 }
120 big = 0; // Largest element for pivoting
121 ibig = -1;
122 for ( i=j; i<n; i++ ) { // Calculating the lower triangle
123 for ( k=0; k<j; k++ ) // and diagonal (i==j)
124 p[i][j] -= p[i][k]*p[k][j];
125 if ( x[i]*fabs(p[i][j]) >= big ) { // Get the biggest element
126 big = x[i]*fabs(p[i][j]); // for pivoting
127 ibig = i;
128 }
129 }
130 if ( j != ibig ) { // Interchange rows if necessary
131 for ( k=0; k<n; k++ ) swap(p[ibig][k], p[j][k]);
132 swap(x[ibig], x[j]); // Switch scales
133 swap(ind[ibig], ind[j]); // Switch indices
134 det = -det; // Change the sign of the determinant
135 }
136 if ( p[j][j] == 0 ) p[j][j] = 1e-37;
137 for ( i=j+1; i<n; i++ ) p[i][j] /= p[j][j]; // Divide by pivot element
138 }
139
140 // Calculate the determinant
141 for ( i=0; i<n; i++ ) det *= p[i][i];
142
143 // Invert matrix
144 for ( k=0; k<n; k++ ) {
145 for ( i=0; i<n; i++ ) x[i] = 0;
146 x[k] = 1;
147 for ( i=0; i<n; i++ ) // Forward substitution
148 for ( j=0; j<i; j++ ) x[i] -= p[i][j]*x[j];
149 for ( i=n-1; i>=0; i-- ) { // Backward substitution
150 for ( j=i+1; j<n; j++ ) x[i] -= p[i][j]*x[j];
151 x[i] /= p[i][i];
152 a[i][k] = x[i];
153 }
154 }
155
156 // Reorder the matrix back to the original row order
157 for ( i=0; i<n; i++ ) {
158 j = ind[i]; // Find the old row at this position
159 for ( k=0; k<n; k++ ) // Pack it back in order into matrix A
160 p[k][j] = a[k][i];
161 }
162
163 if ( verbose & VERB_DEBUG )
164 cout << "DEBUG Matrix::LU_decomposition: done" << endl << *this << endl;
165
166 return det;
167 }
168
177 double Matrix::singular_value_decomposition()
178 {
179 long flag, i, its, j, jj, k, l, nm;
180 double anorm, c, f, g, h, s, scale, x, y, z, t;
181
182 vector<double> w(n);
183 vector<double> tmp(n);
184 Matrix v(n,n);
185
186 for ( i=0; i<n; i++ ) w[i] = tmp[i] = 0;
187
188 g=scale=anorm=0.0;
189 for (i=0;i<n;i++) {
190 l=i+1;
191 tmp[i]=scale*g;
192 g=s=scale=0.0;
193 if (i <= m) {
194 for (k=i;k<m;k++) scale += fabs(p[k][i]);
195 if (scale) {
196 for (k=i;k<m;k++) {
197 p[k][i] /= scale;
198 s += p[k][i]*p[k][i];
199 }
200 f=p[i][i];
201 g = -copysign(sqrt(s),f);
202 h=f*g-s;
203 p[i][i]=f-g;
204 for (j=l;j<n;j++) {
205 for (s=0.0,k=i;k<m;k++) s += p[k][i]*p[k][j];
206 f=s/h;
207 for (k=i;k<m;k++) p[k][j] += f*p[k][i];
208 }
209 for (k=i;k<m;k++) p[k][i] *= scale;
210 }
211 }
212 w[i]=scale *g;
213 g=s=scale=0.0;
214 if (i < m && i != n) {
215 for (k=l;k<n;k++) scale += fabs(p[i][k]);
216 if (scale) {
217 for (k=l;k<n;k++) {
218 p[i][k] /= scale;
219 s += p[i][k]*p[i][k];
220 }
221 f=p[i][l];
222 g = -copysign(sqrt(s),f);
223 h=f*g-s;
224 p[i][l]=f-g;
225 for (k=l;k<n;k++) tmp[k]=p[i][k]/h;
226 for (j=l;j<m;j++) {
227 for (s=0.0,k=l;k<n;k++) s += p[j][k]*p[i][k];
228 for (k=l;k<n;k++) p[j][k] += s*tmp[k];
229 }
230 for (k=l;k<n;k++) p[i][k] *= scale;
231 }
232 }
233 t = fabs(w[i])+fabs(tmp[i]);
234 if ( anorm < t ) anorm = t;
235 }
236
237 for (i=n-1;i>=0;i--) {
238 if (i < n-1) {
239 if (g) {
240 for (j=l;j<n;j++)
241 v[j][i]=(p[i][j]/p[i][l])/g;
242 for (j=l;j<n;j++) {
243 for (s=0.0,k=l;k<n;k++) s += p[i][k]*v[k][j];
244 for (k=l;k<n;k++) v[k][j] += s*v[k][i];
245 }
246 }
247 for (j=l;j<n;j++) v[i][j]=v[j][i]=0.0;
248 }
249 v[i][i]=1.0;
250 g=tmp[i];
251 l=i;
252 }
253
254 for (i=( m < n )? m-1: n-1;i>=0;i--) {
255 l=i+1;
256 g=w[i];
257 for (j=l;j<n;j++) p[i][j]=0.0;
258 if (g) {
259 g=1.0/g;
260 for (j=l;j<n;j++) {
261 for (s=0.0,k=l;k<m;k++) s += p[k][i]*p[k][j];
262 f=(s/p[i][i])*g;
263 for (k=i;k<m;k++) p[k][j] += f*p[k][i];
264 }
265 for (j=i;j<m;j++) p[j][i] *= g;
266 } else for (j=i;j<m;j++) p[j][i]=0.0;
267 ++p[i][i];
268 }
269
270 for (k=n-1;k>=0;k--) {
271 for (its=0;its<30;its++) {
272 flag=1;
273 for (l=k;l>=0;l--) {
274 nm=l-1;
275 if ((double)(fabs(tmp[l])+anorm) == anorm) {
276 flag=0;
277 break;
278 }
279 if ( l==0 ) break; // JBH
280 if ((double)(fabs(w[nm])+anorm) == anorm) break;
281 }
282 // printf("k=%d its=%d nm=%d flag=%d\n", k, its, nm, flag);
283 if (flag) { // Examples never get into this block
284 c=0.0;
285 s=1.0;
286 for (i=l;i<=k;i++) {
287 f=s*tmp[i];
288 tmp[i]=c*tmp[i];
289 if ((double)(fabs(f)+anorm) == anorm) break;
290 g=w[i];
291 h=sqrt(f*f + g*g); // JBH
292 w[i]=h;
293 h=1.0/h;
294 c=g*h;
295 s = -f*h;
296 for (j=0;j<m;j++) {
297 y=p[j][nm];
298 z=p[j][i];
299 p[j][nm]=y*c+z*s;
300 p[j][i]=z*c-y*s;
301 }
302 }
303 }
304 z=w[k];
305 if (l == k) {
306 if (z < 0.0) {
307 w[k] = -z;
308 for (j=0;j<n;j++) v[j][k] = -v[j][k];
309 }
310 break;
311 }
312 if (its == 29) cerr << "Error: no convergence in 30 svdcmp iterations" << endl;
313 x=w[l];
314 nm=k-1;
315 y = g = 0; // JBH
316 if ( nm >= 0 ) { // JBH
317 y=w[nm]; // JBH
318 g=tmp[nm]; // JBH
319 }
320 h=tmp[k];
321 f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
322 g=sqrt(f*f + 1.0); // JBH
323 f=((x-z)*(x+z)+h*((y/(f+copysign(g,f)))-h))/x;
324 c=s=1.0;
325 // cout << "k=%d its=%d l=%d nm=%d\n", k, its, l, nm);
326 for (j=l;j<=nm;j++) { // if nm<0 => no loop
327 i=j+1;
328 g=tmp[i];
329 y=w[i];
330 h=s*g;
331 g=c*g;
332 z=sqrt(f*f + h*h); // JBH
333 tmp[j]=z;
334 c=f/z;
335 s=h/z;
336 f=x*c+g*s;
337 g = g*c-x*s;
338 h=y*s;
339 y *= c;
340 for (jj=0;jj<n;jj++) {
341 x=v[jj][j];
342 z=v[jj][i];
343 v[jj][j]=x*c+z*s;
344 v[jj][i]=z*c-x*s;
345 }
346 z=sqrt(f*f + h*h); // JBH
347 w[j]=z;
348 if (z) {
349 z=1.0/z;
350 c=f*z;
351 s=h*z;
352 }
353 f=c*g+s*y;
354 x=c*y-s*g;
355 for (jj=0;jj<m;jj++) {
356 y=p[jj][j];
357 z=p[jj][i];
358 p[jj][j]=y*c+z*s;
359 p[jj][i]=z*c-y*s;
360 }
361 }
362 tmp[l]=0.0;
363 tmp[k]=f;
364 w[k]=x;
365 }
366 }
367
368 // Setting singular values to zero
369 double wmax, wmin;
370 for ( wmax=w[0], l=0; l<n; l++ )
371 if ( wmax < w[l] ) wmax = w[l];
372 wmin = 1e-6*wmax;
373 for ( l=0; l<n; l++ )
374 if ( w[l] < wmin ) w[l] = 0;
375 else w[l] = 1/w[l];
376
377 // Invert
378 Matrix u(*this);
379
380 for ( j=0; j<n; j++ )
381 for ( i=0; i<n; i++)
382 v[j][i] *= w[i];
383
384 for ( j=0; j<n; j++ )
385 for ( i=0; i<m; i++ ) {
386 p[j][i] = 0;
387 for ( k=0; k<n; k++ )
388 p[j][i] += v[j][k]*u[i][k];
389 }
390
391 return 0;
392 }
393
394 int Matrix::jrotate(double s, double tau, long i, long j, long k, long l)
395 {
396 double g, h;
397
398 g = p[i][j];
399 h = p[k][l];
400 p[i][j] = g - s*(h + g*tau);
401 p[k][l] = h + s*(g - h*tau);
402
403 return 0;
404 }
405
414 /*double* Matrix::jacobi_rotation_old() {
415 vector<double> v = jacobi_rotation();
416 double* vo = new double[n];
417 for ( long i=0; i<n; ++i ) vo[i] = v[i];
418 return vo;
419 }*/
420
421 vector<double> Matrix::jacobi_rotation()
422 {
423 long j, iq, ip, i, nrot(0);
424 double tresh, theta, tau, t, sm, s, h, g, c;
425 vector<double> val(n);
426 Matrix vec(m,n);
427
428 for ( ip=i=j=0; ip<n; ip++ ) {
429 for ( iq=0; iq<n; iq++, i++ ) {
430 j += ( fabs(p[ip][iq]) < 1e-12 ); // Check if small to prevent too many iterations bailout
431 }
432 vec[ip][ip] = 1.0;
433 val[ip] = p[ip][ip];
434 }
435
436 if ( j == n*n ) return val; // The matrix is zero
437
438 vector<double> b(n);
439 vector<double> z(n);
440
441 for ( ip=0; ip<n; ip++ ) {
442 b[ip] = val[ip];
443 z[ip] = 0;
444 }
445
446 for ( i=1; i<=50; i++ ) {
447 sm=0.0;
448 for ( ip=0; ip<n-1; ip++ ) {
449 for ( iq=ip+1; iq<n; iq++ )
450 sm += fabs(p[ip][iq]);
451 }
452 if ( sm == 0.0 ) {
453 for ( ip=0; ip<len; ip++ ) d[ip] = vec.d[ip];
454 return val; // Function exit
455 }
456 if ( i < 4 )
457 tresh=0.2*sm/(n*n);
458 else
459 tresh=0.0;
460 for ( ip=0; ip<n-1; ip++ ) {
461 for ( iq=ip+1; iq<n; iq++ ) {
462 g = 100.0*fabs(p[ip][iq]);
463 if ( i > 4 && (double)(fabs(val[ip])+g) == (double)fabs(val[ip])
464 && (double)(fabs(val[iq])+g) == (double)fabs(val[iq]))
465 p[ip][iq] = 0.0;
466 else if ( fabs(p[ip][iq]) > tresh ) {
467 h = val[iq] - val[ip];
468 if ( (double)(fabs(h)+g) == (double)fabs(h))
469 t = p[ip][iq]/h;
470 else {
471 theta = 0.5*h/p[ip][iq];
472 t = 1.0/(fabs(theta)+sqrt(1.0+theta*theta));
473 if (theta < 0.0) t = -t;
474 }
475 c = 1.0/sqrt(1+t*t);
476 s = t*c;
477 tau = s/(1.0+c);
478 h = t*p[ip][iq];
479 z[ip] -= h;
480 z[iq] += h;
481 val[ip] -= h;
482 val[iq] += h;
483 p[ip][iq] = 0.0;
484 for ( j=0; j<ip; j++ ) {
485 jrotate(s, tau, j, ip, j, iq);
486 }
487 for ( j=ip+1; j<iq; j++ ) {
488 jrotate(s, tau, ip, j, j, iq);
489 }
490 for ( j=iq+1; j<n; j++ ) {
491 jrotate(s, tau, ip, j, iq, j);
492 }
493 for ( j=0; j<n; j++ ) {
494 vec.jrotate(s, tau, j, ip, j, iq);
495 }
496 nrot++;
497 }
498 }
499 }
500 for ( ip=0; ip<n; ip++ ) {
501 b[ip] += z[ip];
502 val[ip] = b[ip];
503 z[ip] = 0.0;
504 }
505 }
506
507 error_show("Error in Matrix::jacobi_rotation", __FILE__, __LINE__);
508 cerr << "Too many iterations (" << i << ")" << endl;
509
510 for ( ip=0; ip<n; ip++ ) {
511 for ( iq=0; iq<n; iq++ ) p[ip][iq] = 0.0;
512 p[ip][ip] = 1.0;
513 val[ip] = 0;
514 }
515
516 return val;
517 }
518 /*
519 long Matrix::jacobi_rotation_row(long ip, long n, long i, double* val, double* z, Matrix* vec)
520 {
521 long j, iq, nrot(0);
522 double tresh, theta, tau, t, sm, s, h, g, c;
523
524 for ( iq=ip+1; iq<n; iq++ ) {
525 g = 100.0*fabs(p[ip][iq]);
526 if ( i > 4 && (double)(fabs(val[ip])+g) == (double)fabs(val[ip])
527 && (double)(fabs(val[iq])+g) == (double)fabs(val[iq]))
528 p[ip][iq] = 0.0;
529 else if ( fabs(p[ip][iq]) > tresh ) {
530 h = val[iq] - val[ip];
531 if ( (double)(fabs(h)+g) == (double)fabs(h))
532 t = p[ip][iq]/h;
533 else {
534 theta = 0.5*h/p[ip][iq];
535 t = 1.0/(fabs(theta)+sqrt(1.0+theta*theta));
536 if (theta < 0.0) t = -t;
537 }
538 c = 1.0/sqrt(1+t*t);
539 s = t*c;
540 tau = s/(1.0+c);
541 h = t*p[ip][iq];
542 z[ip] -= h;
543 z[iq] += h;
544 val[ip] -= h;
545 val[iq] += h;
546 p[ip][iq] = 0.0;
547 for ( j=0; j<ip; j++ ) {
548 jrotate(s, tau, j, ip, j, iq);
549 }
550 for ( j=ip+1; j<iq; j++ ) {
551 jrotate(s, tau, ip, j, j, iq);
552 }
553 for ( j=iq+1; j<n; j++ ) {
554 jrotate(s, tau, ip, j, iq, j);
555 }
556 for ( j=0; j<n; j++ ) {
557 vec->jrotate(s, tau, j, ip, j, iq);
558 }
559 nrot++;
560 }
561 }
562
563 return nrot;
564 }
565 */
574 /*double* Matrix::jacobi_rotation_parallel()
575 {
576 long j, iq, ip, i, nrot(0);
577 double tresh, theta, tau, t, sm, s, h, g, c;
578 double* val = new double[n];
579 Matrix* vec = new Matrix(m,n);
580
581 for ( ip=i=j=0; ip<n; ip++ ) {
582 for ( iq=0; iq<n; iq++, i++ ) {
583 j += ( fabs(p[ip][iq]) < 1e-12 ); // Check if small to prevent too many iterations bailout
584 }
585 (*vec)[ip][ip] = 1.0;
586 val[ip] = p[ip][ip];
587 }
588
589 if ( j == n*n ) return val; // The matrix is zero
590
591 double* b = new double[n];
592 double* z = new double[n];
593
594 for ( ip=0; ip<n; ip++ ) {
595 b[ip] = val[ip];
596 z[ip] = 0;
597 }
598
599 for ( i=1; i<=50; i++ ) {
600 sm=0.0;
601 for ( ip=0; ip<n-1; ip++ ) {
602 for ( iq=ip+1; iq<n; iq++ )
603 sm += fabs(p[ip][iq]);
604 }
605 if ( sm == 0.0 ) {
606 delete[] b;
607 delete[] z;
608 for ( ip=0; ip<len; ip++ ) d[ip] = vec->d[ip];
609 return val; // Function exit
610 }
611 if ( i < 4 )
612 tresh=0.2*sm/(n*n);
613 else
614 tresh=0.0;
615
616 for ( ip=0; ip<n-1; ip++ ) {
617 #ifdef HAVE_GCD
618 dispatch_apply(n - 1, dispatch_get_global_queue(0, 0), ^(size_t ip){
619 jacobi_rotation_row(ip, n, i, val, z, vec);
620 });
621 #else
622 #pragma omp parallel for
623 for ( ip=0; ip<n-1; ip++ ) {
624 jacobi_rotation_row(ip, n, i, val, z, vec);
625 }
626 #endif
627 }
628
629 for ( ip=0; ip<n; ip++ ) {
630 b[ip] += z[ip];
631 val[ip] = b[ip];
632 z[ip] = 0.0;
633 }
634 }
635
636 error_show("Error in Matrix::jacobi_rotation", __FILE__, __LINE__);
637 cerr << "Too many iterations (" << i << ")" << endl;
638
639 for ( ip=0; ip<n; ip++ ) {
640 for ( iq=0; iq<n; iq++ ) p[ip][iq] = 0.0;
641 p[ip][ip] = 1.0;
642 val[ip] = 0;
643 }
644
645 return val;
646 }
647 */
648
659 /*void Matrix::eigen_sort(double* val)
660 {
661 long k,j,i;
662 double t;
663
664 for ( i=0; i<n-1; i++ ) {
665 t = val[k=i];
666 for ( j=i+1; j<n; j++ )
667 if ( val[j] >= t ) t = val[k=j];
668 if ( k != i ) {
669 val[k] = val[i];
670 val[i] = t;
671 for ( j=0; j<n; j++ )
672 swap(p[j][i], p[j][k]);
673 }
674 }
675 }*/
676
677 void Matrix::eigen_sort(vector<double>& val)
678 {
679 long k,j,i;
680 double t;
681
682 for ( i=0; i<n-1; i++ ) {
683 t = val[k=i];
684 for ( j=i+1; j<n; j++ )
685 if ( val[j] >= t ) t = val[k=j];
686 if ( k != i ) {
687 val[k] = val[i];
688 val[i] = t;
689 for ( j=0; j<n; j++ )
690 swap(p[j][i], p[j][k]);
691 }
692 }
693 }
694
706 Vector3<double> principal_axes(Vector3<double> avg, Vector3<double> avg2, Vector3<double> avgx, Vector3<double>* eigenvec)
707 {
708 Matrix a(3,3);
709
710 a[0][0] = avg2[0] - avg[0]*avg[0];
711 a[1][1] = avg2[1] - avg[1]*avg[1];
712 a[2][2] = avg2[2] - avg[2]*avg[2];
713 a[0][1] = a[1][0] = avgx[0] - avg[0]*avg[1];
714 a[0][2] = a[2][0] = avgx[1] - avg[0]*avg[2];
715 a[1][2] = a[2][1] = avgx[2] - avg[1]*avg[2];
716
717 vector<double> d = a.jacobi_rotation();
718 a.eigen_sort(d);
719
720 Vector3<double> eigenval(d[0], d[1], d[2]);
721 Vector3<double> pax = (eigenval * 3).square_root();
722
723 long i, j;
724 if ( eigenvec ) {
725 for ( i=0; i<3; i++ )
726 for ( j=0; j<3; j++ )
727 eigenvec[i][j] = a[j][i];
728 }
729
730 if ( verbose & VERB_PROCESS ) {
731 cout << "Center of mass: " << avg << " A" << endl;
732 cout << "Principal axis lengths: " << pax << " A" << endl;
733 cout << "Volume: " << (4.0*M_PI/3.0)*pax.volume() << " A3" << endl;
734 cout << "Eigenvalues: " << eigenval << endl;
735 cout << "Eigenvectors:" << endl;
736 for ( i=0; i<3; i++ )
737 cout << tab << a[0][i] << tab << a[1][i] << tab << a[2][i] << endl;
738 cout << endl;
739 }
740
741 return pax;
742 }
743
744 // Macros
745 #define SQR(x) ((x)*(x)) // x^2
746
764 void dsytrd3(Matrix& A, vector<double>& d, vector<double>& e)
765 {
766 const int n = 3;
767 int i, j;
768 double u[3], q[3];
769 double omega, f;
770 double K, h, g;
771 double Q[3][3];
772
773 // Initialize Q to the identitity matrix
774 for (i=0; i < n; i++)
775 {
776 Q[i][i] = 1.0;
777 for (j=0; j < i; j++)
778 Q[i][j] = Q[j][i] = 0.0;
779 }
780
781 // Bring first row and column to the desired form
782 h = SQR(A[0][1]) + SQR(A[0][2]);
783 if (A[0][1] > 0)
784 g = -sqrt(h);
785 else
786 g = sqrt(h);
787 e[0] = g;
788 f = g * A[0][1];
789 u[1] = A[0][1] - g;
790 u[2] = A[0][2];
791
792 omega = h - f;
793 if (omega > 0.0)
794 {
795 omega = 1.0 / omega;
796 K = 0.0;
797 for (i=1; i < n; i++)
798 {
799 f = A[1][i] * u[1] + A[i][2] * u[2];
800 q[i] = omega * f; // p
801 K += u[i] * f; // u* A u
802 }
803 K *= 0.5 * SQR(omega);
804
805 for (i=1; i < n; i++)
806 q[i] = q[i] - K * u[i];
807
808 d[0] = A[0][0];
809 d[1] = A[1][1] - 2.0*q[1]*u[1];
810 d[2] = A[2][2] - 2.0*q[2]*u[2];
811
812 // Calculate updated A[1][2] and store it in e[1]
813 e[1] = A[1][2] - q[1]*u[2] - u[1]*q[2];
814
815 // Store inverse Householder transformation in Q
816 for (j=1; j < n; j++)
817 {
818 f = omega * u[j];
819 for (i=1; i < n; i++)
820 Q[i][j] = Q[i][j] - f*u[i];
821 }
822
823 }
824 else
825 {
826 for (i=0; i < n; i++)
827 d[i] = A[i][i];
828 e[1] = A[1][2];
829 }
830
831 for ( i=0; i<3; ++i )
832 for ( j=0; j<3; ++j )
833 A[j][i] = Q[j][i];
834
835 }
836
850 vector<double> dsyevq3(Matrix& A)
851 {
852 const int n(3);
853 vector<double> e(3); // The third element is used only as temporary workspace
854 double g, r, p, f, b, s, c, t; // Intermediate storage
855 int nIter;
856 int m, k, l, i;
857 vector<double> w(3); /* Array with unordered eigenvalues */
858
859 // Transform A to real tridiagonal form by the Householder method
860 dsytrd3(A, w, e);
861 // Calculate eigensystem of the remaining real symmetric tridiagonal matrix
862 // with the QL method
863 //
864 // Loop over all off-diagonal elements
865 for (l=0; l < n-1; l++)
866 {
867 nIter = 0;
868 while (1)
869 {
870 // Check for convergence and exit iteration loop if off-diagonal
871 // element e(l) is zero
872 for (m=l; m <= n-2; m++)
873 {
874 g = fabs(w[m])+fabs(w[m+1]);
875 if (fabs(e[m]) + g == g)
876 break;
877 }
878 if (m == l)
879 break;
880
881 if (nIter++ >= 30)
882 return w;
883
884 // Calculate g = d_m - k
885 g = (w[l+1] - w[l]) / (e[l] + e[l]);
886 r = sqrt(SQR(g) + 1.0);
887 if (g > 0)
888 g = w[m] - w[l] + e[l]/(g + r);
889 else
890 g = w[m] - w[l] + e[l]/(g - r);
891
892 s = c = 1.0;
893 p = 0.0;
894 for (i=m-1; i >= l; i--)
895 {
896 f = s * e[i];
897 b = c * e[i];
898 if (fabs(f) > fabs(g))
899 {
900 c = g / f;
901 r = sqrt(SQR(c) + 1.0);
902 e[i+1] = f * r;
903 c *= (s = 1.0/r);
904 }
905 else
906 {
907 s = f / g;
908 r = sqrt(SQR(s) + 1.0);
909 e[i+1] = g * r;
910 s *= (c = 1.0/r);
911 }
912
913 g = w[i+1] - p;
914 r = (w[i] - g)*s + 2.0*c*b;
915 p = s * r;
916 w[i+1] = g + p;
917 g = c*r - b;
918
919 // Form eigenvectors
920 for (k=0; k < n; k++)
921 {
922 t = A[k][i+1];
923 A[k][i+1] = s*A[k][i] + c*t;
924 A[k][i] = c*A[k][i] - s*t;
925 }
926 }
927 w[l] -= p;
928 e[l] = g;
929 e[m] = 0.0;
930 }
931 }
932
933 return w;
934 }
935
936
937
938
Matrix::jacobi_rotation
vector< double > jacobi_rotation()
Computes all eigenvalues and eigenvectors of a real symmetric matrix.
Definition: matrix.cpp:421
Matrix::rows
long rows()
Definition: Matrix.h:153
utilities.h
Header file for general utilities.
VERB_DEBUG
#define VERB_DEBUG
Definition: utilities.h:112
Matrix::multiply_in_place
int multiply_in_place(vector< double > &vec)
Definition: matrix.cpp:49
Matrix.h
Generalized matrix class.
Matrix::columns
long columns()
Definition: Matrix.h:154
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
Matrix::singular_value_decomposition
double singular_value_decomposition()
Singular value decomposition of a matrix .
Definition: matrix.cpp:177
Matrix::LU_decomposition
double LU_decomposition()
Matrix inversion by LU decomposition.
Definition: matrix.cpp:78
M_PI
#define M_PI
Definition: utilities.h:59
operator<<
ostream & operator<<(ostream &output, Matrix &mat)
Definition: matrix.cpp:18
principal_axes
Vector3< double > principal_axes(Vector3< double > avg, Vector3< double > avg2, Vector3< double > avgx, Vector3< double > *eigenvec)
Calculates the principal axes of 3D coordinates.
Definition: matrix.cpp:706
Matrix::eigen_sort
void eigen_sort(vector< double > &val)
Computes all eigenvalues and eigenvectors of a real symmetric matrix.
Definition: matrix.cpp:677
verbose
int verbose
random_numbers.h
Header file for functions for creating random images.
Matrix
Definition: Matrix.h:21
matrix_linear.h
Header file for matrix functions.
dsyevq3
vector< double > dsyevq3(Matrix &A)
Calculates the eigenvalues and normalized eigenvectors of a symmetric 3x3 matrix.
Definition: matrix.cpp:850
Matrix::jrotate
int jrotate(double s, double tau, long i, long j, long k, long l)
Definition: matrix.cpp:394
SQR
#define SQR(x)
Definition: matrix.cpp:745
Vector3< double >
dsytrd3
void dsytrd3(Matrix &A, vector< double > &d, vector< double > &e)
Reduces a symmetric 3x3 matrix to tridiagonal form.
Definition: matrix.cpp:764
Vector3::volume
double volume()
Definition: Vector3.h:235
error_show
int error_show(string message, string file, int line)
Displays the error with file and line reference.
Definition: utilities.cpp:755
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
math_util.h
Header file for general utilities.