CircularShift - Shift matrix rows or columns circularly. Shift each matrix row (or column) circularly by a different amount. USAGE shifted = CircularShift(m,s) m matrix to rotate s shift amount for each row (horizontal vector) or column (vertical vector)
0001 function shifted = CircularShift(m,s) 0002 0003 %CircularShift - Shift matrix rows or columns circularly. 0004 % 0005 % Shift each matrix row (or column) circularly by a different amount. 0006 % 0007 % USAGE 0008 % 0009 % shifted = CircularShift(m,s) 0010 % 0011 % m matrix to rotate 0012 % s shift amount for each row (horizontal vector) or 0013 % column (vertical vector) 0014 0015 % Copyright (C) 2012 by Michaƫl Zugaro 0016 % 0017 % This program is free software; you can redistribute it and/or modify 0018 % it under the terms of the GNU General Public License as published by 0019 % the Free Software Foundation; either version 3 of the License, or 0020 % (at your option) any later version. 0021 0022 % Check number of parameters 0023 if nargin < 2, 0024 error('Incorrect number of parameters (type ''help <a href="matlab:help CircularShift">CircularShift</a>'' for details).'); 0025 end 0026 0027 [mm,nm] = size(m); 0028 [ms,ns] = size(s); 0029 0030 % Check parameter sizes 0031 if ~isivector(s), 0032 error('Second parameter is not a vector of integers (type ''help <a href="matlab:help CircularShift">CircularShift</a>'' for details).'); 0033 end 0034 if mm ~= ms && nm ~= ns, 0035 error('Incompatible parameter sizes (type ''help <a href="matlab:help CircularShift">CircularShift</a>'' for details).'); 0036 end 0037 0038 % The algorithm below works along columns; transpose if necessary 0039 s = -s(:)'; 0040 if ns == 1, 0041 m = m'; 0042 [mm,nm] = size(m); 0043 end 0044 0045 % Shift matrix S, where Sij is the vertical shift for element ij 0046 shift = repmat(s,mm,1); 0047 0048 % Before we start, each element Mij has a linear index Aij. After circularly shifting the rows, it will have a linear index Bij. 0049 % We now construct Bij. 0050 0051 % First, create matrix C where each item Cij = i (row number) 0052 lines = repmat((1:mm)',1,nm); 0053 % Next, update C so that Cij becomes the target row number (after circular shift) 0054 lines = mod(lines+shift,mm); 0055 lines(lines==0) = mm; 0056 % Finally, transform Cij into a linear index, yielding Bij 0057 indices = lines + repmat((0:nm-1).*mm,mm,1); 0058 0059 % Circular shift (reshape so that it is not transformed into a vector) 0060 shifted = reshape(m(indices),mm,nm); 0061 0062 % Transpose back if necessary 0063 if ns == 1, 0064 shifted = shifted'; 0065 end