Subversion Repositories gelsvn

Rev

Rev 12 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 bj 1
#include "eigensolution.h"
2
#include "Mat2x2f.h"
3
#include "Mat3x3f.h"
4
#include "Mat4x4f.h"
5
 
6
#include <iostream>
7
 
8
using namespace std;
9
 
10
 
11
namespace
12
{
13
	// During experiments 925 iterations were observed for a hard problem
14
	// Ten times that should be safe.
15
	const int KMAX = 10000;
16
 
17
	// The threshold below is the smallest that seems to give reliable
18
	// solutions.
19
	const float EV_THRESH = 0.0000001;
20
}
21
 
22
namespace CGLA
23
{
24
 
25
	template <class MT>
26
	int power_eigensolution(const MT& Ap, MT& Q, MT& L, int max_sol)
27
	{
28
		typedef typename MT::VectorType VT;
29
		MT A = Ap;
30
		int n = s_min(MT::get_v_dim(), max_sol);
31
 
32
		for(int i=0;i<n;++i)
33
			{
34
				// Seed the eigenvector estimate
35
				VT q(1);
36
				float l=0,l_old;
37
 
38
				// As long as we haven't reached the max iterations and the
39
				// eigenvalue has not converged, do
40
				int k=0;
41
				for(; k<2 || k<KMAX && (l-l_old > EV_THRESH * l) ; ++k)
42
					{
43
						// Multiply the eigenvector estimate onto A
44
						const VT z = A * q;
45
 
46
						// Check that we did not get the null vector.
47
						float z_len = z.length();
48
						if(z_len < EV_THRESH)
49
							return i;
50
 
51
						// Normalize to get the new eigenvector
52
						q = z/z_len;
53
 
54
						// Record the old eigenvalue estimate and get a new estimate.
55
						l_old = l;
56
						l = dot(q, A * q);
57
					}
58
				// If we hit the max iterations, we also don't trust the eigensolution
59
				if(k==KMAX)
60
					return i;
61
 
62
				// Update the solution by adding the eigenvector to Q and
63
				// the eigenvalue to the diagonal of L.
64
				Q[i] = q;
65
				L[i][i] = l;
66
 
67
				// Update A by subtracting the subspace represented by the 
68
				// eigensolution just found. This is called the method of 
69
				// deflation.
70
				MT B;
71
				outer_product(q,q,B);
72
				A = A - l * B;
73
			}
74
		return n;
75
	}
76
 
77
	/* There is no reason to put this template in a header file, since 
78
		 we will only use it on matrices defined in CGLA. Instead, we 
79
		 explicitly instantiate the function for the square matrices
80
		 of CGLA */
81
	template int power_eigensolution<Mat2x2f>(const Mat2x2f&,
82
																						Mat2x2f&,Mat2x2f&,int);
83
 
84
	template int power_eigensolution<Mat3x3f>(const Mat3x3f&,
85
																						Mat3x3f&,Mat3x3f&,int);
86
	template int power_eigensolution<Mat4x4f>(const Mat4x4f&,
87
																						Mat4x4f&,Mat4x4f&,int);
88
}
89