function B=rotmat(A,n,dim)
%ROTMAT  Rotate matrix along specified dimension.
%   ROTMAT(X), returns X.
%   ROTMAT(X,N), moves elements in matrix X with N steps in
%      a wrapping/rotating fashion. Rotation will be done row-wise.
%      Positive N will mean that elements are moved towards higher
%      row indicies. Last element(s) will be moved to the first row,
%      aso. Negative N will make the elements move upwards towards
%      lower row indicies. First element(s) will be moved to the last
%      row, aso. If N is zero or empty, no rotation will occur
%      and X will be returned.
%   ROTMAT(X,N,DIM), rotates matrix elements along dimension DIM.
%      If DIM is a singleton dimension, X will be returned.
%      Likewise if DIM < 1 or DIM > ndims(X), nothing will happen.
%      N must be scalar valued.
%
%   Examples:
%      X=rand(3,3,3)          %X is 3x3x3.
%      rotmat(X,1)            %rotates one step along rows.
%      rotmat(X,-2)           %rotates two steps along rows, opposite direction.
%      rotmat(X,1,2)          %rotates one step along columns.
%      rotmat(X,1,3)          %rotates one step along third dimension.
%
%   See also DELMAT, INSMAT, SHIFTMAT, REPMAT, RESHAPE, FLIPDIM.

% Copyright (c) 2003-10-28, B. Rasmus Anthin.
% Revision 2003-10-29.
% GPL license, freeware.

error(nargchk(1,3,nargin))
if nargin<2, n=0;end                    %do nothing
if isempty(n), n=0;end
if prod(size(n))~=1, error('N must be a scalar.'),end
n=round(n);
if nargin<3, dim=1;end                  %rotate row vectors
if dim<1, dim=ndims(A)+1;end            %if less than one, do nothing
dims=[dim:max(ndims(A),dim) 1:dim-1];
if dims(1)<=ndims(A) & n
   A=permute(A,dims);                             %move dimension to front
   sizA=size(A);                                  %get dimension sizes
   A=reshape(A,[sizA(1) prod(sizA(2:end))]);      %reshape to a 2-D matrix
   n=rem(n-1,sizA(1))+1;                          %wrapping
   idx=1:sizA(1);                                 %the row indices
   if n<0
      idx=[idx(1-n:end) idx(1:-n)];               %rotate row indices (negative rotation)
   else
      idx=[idx(end-n+1:end) idx(1:end-n)];        %rotate row indices (positive rotation)
   end
   B=A(idx,:);
   B=reshape(B,[size(B,1) sizA(2:end)]);          %back to previous shape minus removed vectors
   B=ipermute(B,dims);                            %replace dimensions to initial location
else
   B=A;
end