Switch to unified view

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