function C = conv2(w, x, y, z) % CONV2 Two dimensional convolution. % (Quaternion overloading of standard Matlab function.) % Copyright © 2006 Stephen J. Sangwine and Nicolas Le Bihan. % See the file : Copyright.m for further details. % This function operates in a similar way to the standard Matlab function % apart from supporting both left and right coefficients. (Since quaternion % multiplication is not commutative, the general case requires both left % and right multiplication in the convolution product/summation.) The % Matlab function allows the first two parameters to be vectors - this is % not implemented as yet. Acceptable calling profiles are: % % C = conv2(A, B) - A is convolved on the left of B, that is A * B % C = conv2({L, R}, B) - The convolution is L * B * R. L and R must be of % the same size. % % An optional last parameter can specify 'shape' as for the standard Matlab % function. This is currently not implemented. error(nargchk(2, 4, nargin)), error(nargoutchk(0, 1, nargout)) if nargin == 4 error('conv2 does not yet support 4 parameters.') end % If two or three parameters are supplied, the first two can be either two % matrices, or a cell array and a matrix. The cell array must contain two % matrices of the same size, but they need not be quaternion valued, since % they could be real or complex. if iscell(w) % The first parameter must be a cell array of two elements, and the % elements must have the same size. if length(w) ~= 2 error('If a cell array, the first parameter must have two elements.') end L = w{1}; R = w{2}; if ~all(size(L) == size(R)) error('The elements of the cell array must have the same size.') end B = x; % The second parameter must be a matrix. % Should we do any checks on it here? else % The first parameter must be a matrix (or vector). It need not % be quaternion-valued, since it could be a left matrix of % coefficients. We treat the smaller matrix as a coefficient % matrix, but put it on the left or right according to its % position in the parameter list, and create a matrix of ones % of the same size for the coefficient on the opposite side. if numel(w) < numel(x) % Is this the best comparison that could be done? L = w; B = x; R = ones(size(w)); else L = ones(size(x)); B = w; R = x; end end if nargin == 3 % The third parameter must be a 'shape' parameter. Check for the % legal possibilities. if ~ischar(y) error('Third parameter must be a string.'); end if ~strcmp(y, 'full') && ~strcmp(y, 'same') && ~strcmp(y, 'valid') error(['The third parameter must be one of', ... '''full'', ''same'', or ''valid''']) else shape = y; end else shape = 'full'; % This wasn't specified, so use a default value. end % The variables L, B, R now contain the matrices to be convolved, in the % order L * B * R. [ma, na] = size(L); % This is the same as size(R), of course (we checked that above). [mb, nb] = size(B); mc = ma + mb - 1; nc = na + nb - 1; C = quaternion(zeros(mc, nc)); % Preconstruct the result array. for n1 = 1 : mc for n2 = 1 : nc % This code is vectorized: the two arrays are sliced to extract the % parts that must be multiplied element by element and summed to give % the current element of the output array. This is complicated by the % cases where one array overlaps the edge(s) of the other. k11 = max(1, n1 + 1 - mb); k12 = min(n1, ma); k21 = max(1, n2 + 1 - nb); k22 = min(n2, na); % We need to use indexing here, but since this is a class method, % normal array indexing doesn't work. See the comment in the file % svd.m where the same problem and solution occurs. The commented % statement below is what we would write if array indexing worked % here as per normal. % C(n1, n2) = ... % sum(L(k11:k12, k21:k22) * B(n1 + 1 - k1, n2 + 1 - k2) * ... % R(k11:k12, k21:k22)); s = substruct('()',{n1, n2}); t = substruct('()',{k11:k12, k21:k22}); C = subsasgn(C, s, ... sum(sum(subsref(L, t) .* ... flipud(fliplr(subsref(B, ... substruct('()', {n1 + 1 - k12 : n1 + 1 - k11, ... n2 + 1 - k22 : n2 + 1 - k21})))) .* ... subsref(R, t)) ... )); end end if ~strcmp(shape, 'full') error('The shape parameter is not implemented.') end