-
Notifications
You must be signed in to change notification settings - Fork 27
/
limo_decomp.m
63 lines (56 loc) · 1.8 KB
/
limo_decomp.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
function [eigen_vectors,eigen_values] = limo_decomp(E,H,type)
% FORMAT: [eigen_vectors,eigen_values] = limo_decomp(E,H,type)
%
% INPUT E and H are matrices, typically square symmetric Sum of Squares and
% Cross Products
% type is 'Chol' (default) or 'SVD')
%
% OUTPUT: the eigen vectors and values of the decomposition of inv(E)*H
%
% Following Rencher 2002 (Methods of multivariate analysis - Wiley) we note
% that eig(inv(E)*H) = % eig((E^1/2)*H*inv(E^1/2)) = eig(inv(U')*H*inv(U))
% and E^1/2 is the square root matrix of E and U'U = E (Cholesky factorization).
% Using the Cholesky factorisation, we return positve eigen values from
% inv(U')*H*inv(U) which is positive semidefinite. If this procedre fails
% (E is not positive definite) we then use an eigen value decomposition of pinv(E)*H
% It is also possible to procede using an SVD decomposition using the argument
% type ('SVD')
%
% Cyril Pernet 2009
% Cyril Pernet and Iege Bassez 2017
% -----------------------------
% Copyright (C) LIMO Team 2010
% check input
if nargin < 2
error('not enough arguments in')
elseif nargin == 2
type = 'Chol';
end
% proceede
if strcmpi(type,'chol')
try
U = chol(E);
[eigen_vectors, D] = eig(inv(U')*H*inv(U));
eigen_values = diag(D);
catch
[eigen_vectors, eigen_values] = eig((pinv(E)*H));
end
elseif strcmpi(type,'SVD')
y = (pinv(E)*H);
[m, n] = size(y);
if m > n
[v,s,v] = svd(y*y');
s = diag(s);
v = v(:,1);
u = y*v/sqrt(s(1));
eigen_vectors = v;
else
[u, s,u] = svd(y'*y);
s = diag(s);
u = u(:,1);
v = y'*u/sqrt(s(1));
eigen_vectors = u;
end
d = sign(sum(v)); u = u*d;
eigen_values = u*sqrt(s(1)/n);
end