|
a |
|
b/Analysis/jPCA_ForDistribution/reshapeSkew.m |
|
|
1 |
%%%%%%%%%%%%%%%%%%%%%%%%% |
|
|
2 |
% John P Cunningham |
|
|
3 |
% 2010 |
|
|
4 |
% |
|
|
5 |
% reshapeSkew.m |
|
|
6 |
% |
|
|
7 |
% jPCA2 support function |
|
|
8 |
% |
|
|
9 |
% A skew-symmetric matrix xMat of size n by n really only |
|
|
10 |
% has n*(n-1)/2 unique entries. That is, the diagonal is 0, and the |
|
|
11 |
% upper/lower triangle is the negative transpose of the lower/upper. So, |
|
|
12 |
% we can just think of such a matrix as a vector x of size n(n-1)/2. This |
|
|
13 |
% function reshapes such a vector into the appropriate skew-symmetric |
|
|
14 |
% matrix. |
|
|
15 |
% |
|
|
16 |
% The required ordering in x is row-minor, namely that xMat(1,1) = 0, |
|
|
17 |
% xMat(2,1) = x(1), xMat(3,1) = x(2), and so on. |
|
|
18 |
% |
|
|
19 |
% This function goes either from vector to matrix or vice versa, depending |
|
|
20 |
% on what the argument x is. |
|
|
21 |
% |
|
|
22 |
% In short, this function just reindexes a vector to a matrix or vice |
|
|
23 |
% versa. |
|
|
24 |
%%%%%%%%%%%%%%%%%%%%%%%% |
|
|
25 |
|
|
|
26 |
|
|
|
27 |
function [ Z ] = reshapeSkew( x ) |
|
|
28 |
|
|
|
29 |
% this reshapes a n(n-1)/2 vector to a n by n skew symmetric matrix, or vice versa. |
|
|
30 |
% First we must check if x is a matrix or a vector. |
|
|
31 |
if isvector(x) |
|
|
32 |
% then we are making a matrix |
|
|
33 |
|
|
|
34 |
% first get the size of the appropriate matrix |
|
|
35 |
% this should be n(n-1)/2 entries. |
|
|
36 |
% this is the positive root |
|
|
37 |
n = (1 + sqrt(1 + 8*length(x)))/2; |
|
|
38 |
% error check |
|
|
39 |
if n~=round(n) % if not an integer |
|
|
40 |
% this is a bad argument |
|
|
41 |
fprintf('ERROR... the size of the x vector prevents it from being shaped into a skew symmetric matrix.\n'); |
|
|
42 |
keyboard; |
|
|
43 |
end |
|
|
44 |
|
|
|
45 |
% now make the matrix |
|
|
46 |
% initialize the return matrix |
|
|
47 |
Z = zeros(n); |
|
|
48 |
% and the marker index |
|
|
49 |
indMark = 1; |
|
|
50 |
|
|
|
51 |
for i = 1 : n-1 |
|
|
52 |
% add the elements as appropriate. |
|
|
53 |
Z(i+1:end,i) = x(indMark:indMark+(n-i)-1); |
|
|
54 |
% now update the index Marker |
|
|
55 |
indMark = indMark + (n-i); |
|
|
56 |
end |
|
|
57 |
|
|
|
58 |
% now add the skew symmetric part |
|
|
59 |
Z = Z - Z'; |
|
|
60 |
|
|
|
61 |
else |
|
|
62 |
% then we are making a vector from a matrix (note that the |
|
|
63 |
% standard convention of lower case being a vector and upper case |
|
|
64 |
% being a matrix is now reversed). |
|
|
65 |
|
|
|
66 |
% first check that everything is appropriately sized and skew |
|
|
67 |
% symmetric |
|
|
68 |
if size(x) ~= size(x') |
|
|
69 |
% this is not symmetric |
|
|
70 |
fprintf('ERROR... the matrix x is not square, let alone skew-symmetric.\n'); |
|
|
71 |
keyboard; |
|
|
72 |
end |
|
|
73 |
% now check for skew symmetry |
|
|
74 |
if abs(norm(x + x'))>1e-8 |
|
|
75 |
% this is not skew symmetric. |
|
|
76 |
fprintf('ERROR... the matrix x is not skew-symmetric.\n'); |
|
|
77 |
keyboard; |
|
|
78 |
end |
|
|
79 |
% everything is ok, so take the size |
|
|
80 |
n = size(x,1); |
|
|
81 |
|
|
|
82 |
|
|
|
83 |
% now make the vector Z |
|
|
84 |
indMark = 1; |
|
|
85 |
for i = 1 : n-1 |
|
|
86 |
% add the elements into a column vector as appropriate. |
|
|
87 |
Z(indMark:indMark+(n-i)-1,1) = x(i+1:end,i); |
|
|
88 |
% now update the index Marker |
|
|
89 |
indMark = indMark + (n-i); |
|
|
90 |
end |
|
|
91 |
|
|
|
92 |
end |
|
|
93 |
|
|
|
94 |
end |