| 
11 | 11 | %  | 
12 | 12 | %   shape == 'circ': circular convolution over the size of spA.  | 
13 | 13 | %  | 
14 |  | -%   Version 1.0 by Andrew J. Milne, The MARCS Institute, Western Sydney  | 
15 |  | -%   University, 2018-01-09  | 
 | 14 | +%   By Andrew J. Milne, The MARCS Institute, Western Sydney University  | 
16 | 15 | %  | 
17 |  | -%   See also SPIND2SPSUB, SPSUB2SPIND, SPARSE, CONV, CCONV.  | 
 | 16 | +%   See also SPIND2SPSUB, SPSUB2SPIND, SPARSE, CONVN, CCONV.  | 
18 | 17 | 
 
  | 
19 | 18 | if nargin < 3  | 
20 | 19 |     shape = 'full';  | 
 | 
35 | 34 |     error('The two arrays must have the same numbers of dimensions.')  | 
36 | 35 | end  | 
37 | 36 | 
 
  | 
38 |  | -% Convert spB's linear index to subscripts  | 
 | 37 | +%% Convert indices to those of an array of size spA.Size+spB.Size-1  | 
 | 38 | +sizC = spA.Size+spB.Size-1;  | 
 | 39 | +% Convert linear indices to subscripts  | 
 | 40 | +subsA = spInd2spSub(spA);  | 
39 | 41 | subsB = spInd2spSub(spB);  | 
40 |  | - | 
41 |  | -% Convert spB's subscripts back to a linear index, but taking the size of the  | 
42 |  | -% array to be the same as spA (in non-sparse terms, this is zero padding)  | 
43 |  | -indBSzA = spSub2spInd(spA.Size,subsB);  | 
 | 42 | +% Convert subscripts back to a linear indices, but taking the size  | 
 | 43 | +% of the array to be the same as spA + spB - 1 (in non-sparse terms,  | 
 | 44 | +% this is zero padding)  | 
 | 45 | +indASzC = spSub2spInd(sizC,subsA);  | 
 | 46 | +indBSzC = spSub2spInd(sizC,subsB);  | 
44 | 47 | 
 
  | 
45 | 48 | % Do the convolution  | 
46 |  | -indCSizA = spA.Ind + indBSzA' - 1;  | 
47 |  | -indCSizA = indCSizA(:);  | 
48 |  | -valC = spA.Val.*spB.Val';  | 
 | 49 | +indC = indASzC + indBSzC' - 1; % Outer sum of indices, minus 1  | 
 | 50 | +indC = indC(:);  | 
 | 51 | +valC = spA.Val.*spB.Val'; % Outer product of values  | 
49 | 52 | valC = valC(:);  | 
50 |  | -sparseC = sparse(indCSizA,1,valC); % Accumulate (sum) over repeated indices  | 
 | 53 | +sparseC = sparse(indC,1,valC); % Accumulate (sum) over repeated indices  | 
51 | 54 | 
 
  | 
52 |  | -% Convert linear indices to subs for an array of size A  | 
53 |  | -[indCSizA,~,valC] = find(sparseC);  | 
54 |  | -spC = struct('Size',spA.Size,'Ind',indCSizA,'Val',valC);  | 
55 |  | -subsC = spInd2spSub(spC);  | 
 | 55 | +% Make sparse array structure for full convolution  | 
 | 56 | +[indC,~,valC] = find(sparseC);  | 
 | 57 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  | 
 | 58 | +spC = struct('Size',sizC,'Ind',indC,'Val',valC);  | 
 | 59 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  | 
56 | 60 | 
 
  | 
57 |  | -% If 'shape' is 'full', convert subsC to linear indices for array of   | 
58 |  | -% size A + size B - 1  | 
59 |  | -if isequal(shape,'full')  | 
60 |  | -    % Convert subsC to linear indices for array of size A + size B - 1  | 
61 |  | -    indCSizAB = spSub2spInd(spA.Size+spB.Size-1, subsC);  | 
 | 61 | +if isequal(shape,'same') % Remove entries outside size A  | 
 | 62 | +    % Convert linear indices of spC to subs  | 
 | 63 | +    subsC = spInd2spSub(spC);  | 
 | 64 | +    % Remove subsC outside sizeA  | 
 | 65 | +    subsCTrunc = subsC;  | 
 | 66 | +    indCTrunc = all(subsCTrunc<=spA.Size,2);  | 
 | 67 | +    valC = valC(indCTrunc,:);  | 
 | 68 | +    subsCTrunc = subsCTrunc(indCTrunc,:);  | 
 | 69 | +    % convert subsCTrunc to linear index for array of size spA.Size  | 
 | 70 | +    indC = spSub2spInd(spA.Size,subsCTrunc);  | 
62 | 71 |     % Make into a sparse array structure  | 
63 |  | -    spC = struct('Size',spA.Size+spB.Size-1,'Ind',indCSizAB,'Val',valC);  | 
64 |  | -      | 
65 |  | -% If 'shape' is 'circ', all spC's subs outside spA's size are wrapped  | 
66 |  | -elseif isequal(shape,'circ')  | 
67 |  | -    % Wrap subsC outside sizeA  | 
 | 72 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  | 
 | 73 | +    spC = struct('Size',spA.Size,'Ind',indC,'Val',valC);  | 
 | 74 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  | 
 | 75 | +elseif isequal(shape,'circ') % Wrap entries around size A  | 
 | 76 | +    % Convert linear indices of spC to subs  | 
 | 77 | +    subsC = spInd2spSub(spC);  | 
 | 78 | +    % Wrap subsC over sizeA  | 
68 | 79 |     subsCWrap = mod(subsC-1,spA.Size) + 1;  | 
69 | 80 |     % Convert wrapped subsC to linear index for size A  | 
70 |  | -    indC = spSub2spInd(spA.Size, subsCWrap);  | 
 | 81 | +    indC = spSub2spInd(spA.Size,subsCWrap);  | 
71 | 82 |     % Accumulate (sum) over repeated indices  | 
72 | 83 |     sparseC = sparse(indC,1,valC);  | 
73 | 84 |     % Make into a sparse array structure  | 
74 | 85 |     [indC,~,valC] = find(sparseC);  | 
 | 86 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  | 
75 | 87 |     spC = struct('Size',spA.Size,'Ind',indC,'Val',valC);  | 
76 |  | -      | 
77 |  | -% If 'shape' is 'same', all spC's subs outside spA's size are removed  | 
78 |  | -elseif isequal(shape,'same')  | 
79 |  | -    % Remove subsC outside sizeA  | 
80 |  | -    subsCTrunc = subsC;  | 
81 |  | -    valC  = valC(all(subsCTrunc<=spA.Size,2),:);  | 
82 |  | -    subsCTrunc = subsCTrunc(all(subsCTrunc<=spA.Size,2),:);   | 
83 |  | -    % convert subsCTrunc to linear index for SizA  | 
84 |  | -    indC = spSub2spInd(spA.Size,subsCTrunc);  | 
85 |  | -    % Make into a sparse array structure  | 
86 |  | -    spC = struct('Size',spA.Size,'Ind',indC,'Val',valC);  | 
 | 88 | +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  | 
87 | 89 | end  | 
88 | 90 | 
 
  | 
89 | 91 | end  | 
0 commit comments