0001 function M = centeredmatrixfactory(m, n, rows_or_cols)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 if ~exist('rows_or_cols', 'var') || isempty(rows_or_cols)
0029 rows_or_cols = 'cols';
0030 end
0031
0032
0033 switch lower(rows_or_cols)
0034 case 'cols'
0035 center = @(X) bsxfun(@minus, X, mean(X, 2));
0036 M.dim = @() m*n - m;
0037 case 'rows'
0038 center = @(X) bsxfun(@minus, X, mean(X, 1));
0039 M.dim = @() m*n - n;
0040 otherwise
0041 error('The third input must be either ''rows'' or ''cols''.');
0042 end
0043
0044
0045
0046 M.center = center;
0047
0048 M.name = @() sprintf('Space of size %d x %d matrices with centered %s', ...
0049 m, n, lower(rows_or_cols));
0050
0051 M.inner = @(x, d1, d2) d1(:).'*d2(:);
0052
0053 M.norm = @(x, d) norm(d, 'fro');
0054
0055 M.dist = @(x, y) norm(x-y, 'fro');
0056
0057 M.typicaldist = @() sqrt(M.dim());
0058
0059 M.proj = @(x, d) center(d);
0060
0061 M.egrad2rgrad = M.proj;
0062
0063 M.ehess2rhess = @(x, eg, eh, d) center(eh);
0064
0065 M.tangent = M.proj;
0066
0067 M.exp = @exp;
0068 function y = exp(x, d, t)
0069 if nargin == 3
0070 y = x + t*d;
0071 else
0072 y = x + d;
0073 end
0074 end
0075
0076 M.retr = M.exp;
0077
0078 M.log = @(x, y) y-x;
0079
0080 M.hash = @(x) ['z' hashmd5(x(:))];
0081
0082 M.randvec = @(X) randvec();
0083 function U = randvec()
0084 U = center(randn(m, n));
0085 U = U / norm(U, 'fro');
0086 end
0087
0088 M.rand = @() center(randn(m, n));
0089
0090 M.lincomb = @matrixlincomb;
0091
0092 M.zerovec = @(x) zeros(m, n);
0093
0094 M.transp = @(x1, x2, d) d;
0095
0096 M.pairmean = @(x1, x2) .5*(x1+x2);
0097
0098 M.vec = @(x, u_mat) u_mat(:);
0099 M.mat = @(x, u_vec) reshape(u_vec, [m, n]);
0100 M.vecmatareisometries = @() true;
0101
0102 end