-
Notifications
You must be signed in to change notification settings - Fork 29
/
opSubsAsgn.m
235 lines (196 loc) · 8.32 KB
/
opSubsAsgn.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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
classdef opSubsAsgn < opSpot
%OPSUBSASGN Redefine rectangular subset of operator.
%
% opSubsAsign(A,ROWIDX,COLIDX,B), index = ':' is valid. Size of B
% must match that of rowidx and colidx. THe indices can exceed the
% size of A (even if idx is given as logical) but must not be negative?
%
% See also opRestrict, opSubsRef.
% Copyright 2009, Ewout van den Berg and Michael P. Friedlander
% See the file COPYING.txt for full copyright information.
% Use the command 'spot.gpl' to locate this file.
% http://www.cs.ubc.ca/labs/scl/spot
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Properties
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
properties (SetAccess = private)
opIntrnl = []; % Internal operator
rowIndices = []; % Row indices
colIndices = []; % Column indices
end % Properties
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Methods
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
methods
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Constructor
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function op = opSubsAsgn(A,rowIdx,colIdx,B)
if nargin ~= 4
error('Exactly four operators must be specified.')
end
% Input matrices are immediately cast as opMatrix's.
if isa(A,'numeric'), A = opMatrix(A); end
if isa(B,'numeric'), B = opMatrix(B); end
% Check that the input operators are valid.
if ~isa(A,'opSpot') || ~isa(A,'opSpot')
error('Input operators are not valid.')
end
% Initialize
subs = {rowIdx, colIdx};
% Ensure numeric vectors are full and in vectorized form
for i=1:length(subs)
idx = subs{i}; idx = idx(:);
subs{i} = full(idx);
end
% Check index type and get additional information
allIndex = zeros(1,2); % Set if entire dimension in A covered
sizeIndex = zeros(1,2);
maxIndex = zeros(1,2);
minIndex = zeros(1,2);
for i=1:2
idx = subs{i};
if strcmp(idx,':')
% Replace by vector of logicals
subs{i} = true(size(A,i),1);
sizeIndex(i) = size(A,i);
allIndex(i) = 1;
minIndex(i) = 1;
maxIndex(i) = size(A,i);
elseif islogical(idx)
% Pad vector with false values if needed
if length(idx) < size(A,i)
idx(sizeA(i)) = false;
subs{i} = idx;
end
sizeIndex(i) = sum(double(idx ~= 0));
minIndex(i) = min(find(idx));
maxIndex(i) = max(find(idx));
% Check if all indices are specified
if all(idx(1:size(A,i)))
allIndex(i) =1;
end
elseif spot.utils.isposintmat(idx)
sizeIndex(i) = length(idx);
minIndex(i) = min(idx);
maxIndex(i) = max(idx);
% Check for duplicates
if length(idx) ~= length(unique(idx))
error('Subscripts cannot contain duplicates.');
end
% Check if all indices are specified
if isempty(setdiff(1:size(A,i),idx))
allIndex(i) = 1;
end
else
error(['Subscript indices must either be real positive ' ...
'integers or logicals.']);
end
end
% Check if index and operator dimensions match
if isscalar(B)
B = opFoG(B,opOnes(sizeIndex(1),sizeIndex(2)));
elseif (sizeIndex(1) ~= size(B,1)) || (sizeIndex(2) ~= size(B,2))
error('Subscripted assignment dimension mismatch.');
end
% Determine final operator size
m = max(maxIndex(1),size(A,1));
n = max(maxIndex(2),size(A,2));
% Embed operators A into one matching the final size
embedA = A;
if m > size(A,1)
embedA = opRestriction(m,1:size(A,1))' * embedA;
end
if n > size(A,2)
embedA = embedA * opRestriction(n,1:size(A,2));
end
% Embed and possibly permute operator B
embedB = opRestriction(m,subs{1})' * B;
embedB = embedB * opRestriction(n,subs{2});
% Set default cflag and linear flag
cflag = A.cflag | B.cflag;
linear = A.linear | B.linear;
if allIndex(1) && allIndex(2)
% --------------------------------------------------------
% Case 1: Full overlap
% Embed(B)
% --------------------------------------------------------
opIntrnl = embedB;
cflag = B.cflag;
linear = B.linear;
elseif allIndex(1)
% --------------------------------------------------------
% Case 2: Number of entire rows
% Embed(A)*Mask + Embed(B)
% --------------------------------------------------------
if islogical(subs{2})
idx = xor(true(n,1), subs{2});
else
idx = setdiff(1:size(A,2),subs{2});
end
maskA = opMask(n,idx);
opIntrnl = embedA * maskA + embedB;
elseif allIndex(2)
% --------------------------------------------------------
% Case 3: Number of entire columns
% Mask*Embed(A) + Embed(B)
% --------------------------------------------------------
if islogical(subs{1})
idx = xor(true(m,1), subs{1});
else
idx = setdiff(1:size(A,1),subs{1});
end
maskA = opMask(m,idx);
opIntrnl = maskA * embedA + embedB;
elseif (minIndex(1) > size(A,1)) || (minIndex(2) > size(A,2))
% --------------------------------------------------------
% Case 4: No overlap
% Embed(A) + Embed(B)
% --------------------------------------------------------
opIntrnl = embedA + embedB;
else
% --------------------------------------------------------
% Case 5: Partial overlap
% Embed(A) + Embed(B) - maskA1 * Embed(A) * maskA2
% --------------------------------------------------------
if islogical(subs{1})
idx1 = true(m,1) & subs{1};
else
idx1 = intersect(1:size(A,1),subs{1});
end
if islogical(subs{2})
idx2 = true(n,2) & subs{2};
else
idx2 = intersect(1:size(A,2),subs{2});
end
maskA1 = opMask(m,idx1);
maskA2 = opMask(n,idx2);
opIntrnl = embedA + embedB - maskA1 * embedA * maskA2;
end
% Construct operator
op = op@opSpot('SubsAsgn', m, n);
op.cflag = cflag;
op.linear = linear;
op.children = {A,B};
op.precedence = 1;
op.opIntrnl = opIntrnl;
op.rowIndices = rowIdx;
op.colIndices = colIdx;
end % Constructor
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Display
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function str = char(op)
str = ['Subsasgn(', char(op.children{1}),', ',...
char(op.children{2}),')'];
end % Char
end % Methods
methods ( Access = protected )
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Multiply
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function y = multiply(op,x,mode)
y = applyMultiply(op.opIntrnl,x,mode);
end % Multiply
end % Methods
end % Classdef