function B=shiftmat(A,n,dim,pad)
%SHIFTMAT Shift matrix along specified dimension.
% SHIFTMAT(X), returns X.
% SHIFTMAT(X,N), moves elements in matrix X with N steps. The trailing
% elements becomes zeros. Shifting will be done row-wise.
% Positive N will mean that elements are moved towards higher
% row indicies. First row will be filled with zeros,
% aso. Negative N will make the elements move upwards towards
% lower row indicies. Last row will be filled with zeros,
% aso. If N is zero or empty, no shifting will occur
% and X will be returned.
% SHIFTMAT(X,N,DIM), shifts 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.
% SHIFTMAT(X,N,DIM,PAD), uses PAD to pad the trailing elements with
% another value rather than zeros.
% PAD must be scalar valued.
%
% Examples:
% X=rand(3,3,3) %X is 3x3x3.
% shiftmat(X,1) %shifts one step down.
% shiftmat(X,-2) %shifts two steps up.
% shiftmat(X,1,2) %shifts ones step right.
% shiftmat(X,1,3) %shifts one step "down" along 3:rd dimension.
% shiftmat(X,-2,2,NaN) %shifts two steps left with trailing NaNs.
%
% See also DELMAT, INSMAT, ROTMAT, REPMAT, RESHAPE, FLIPDIM.
% Copyright (c) 2003-10-28, B. Rasmus Anthin.
% Revision 2003-10-29.
% GPL license, freeware.
error(nargchk(1,4,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
if nargin<4, pad=0;end %trailing elements are zeros as default
if prod(size(pad))~=1, error('PAD must be a scalar.'),end
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
idx=1:sizA(1); %the row indices
if n<0
idx=idx(1-n:end); %remove low valued indices
B=A(idx,:); %truncate matrix
B=[B;pad*ones(min(-n,sizA(1)),prod(sizA(2:end)))]; %pad with zeros (or PAD)
elseif n>0
idx=idx(1:end-n); %remove high valued indices
B=A(idx,:); %truncate matrix
B=[pad*ones(min(n,sizA(1)),prod(sizA(2:end)));B]; %pad with zeros (or PAD)
end
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