function m=mapwindows(fn,x,L,M)
% mapwindows - Apply function to windowed signal with causality control
%
% mapwindows ::
%    F:([[N]]->[[M]]) ~'function to apply to windowed segments',
%    [[T]]            ~'signal of length T',
%    L:natural        ~'post-window (ie causal part)',
%    M:natural        ~'pre-window (ie anti-causal part)'
% -> [[M,T]]          ~'sequence of results'.
%
% This function applies a function to a sequence of segments extracted from
% the given signal by sliding a window along the signal. The
% post- and pre- window lengths determine the positioning of the window:
%
%    ....   x1   x2   x3   x4   x5    x6   x7   x8   x9  ...
%         |<--- post --> | now |<----- pre ------> |
%         \________________________________________/
%                           |
%                       function
%                           |
%               ...   y3   y4   y5 ...
%
% Note: the function F must make sense when applied to windows of
% different lengths since the first and last few windows will
% be shorter than L+M+1. The windows will not be zero padded!
%
% EXAMPLES
%
% To compute a running mean using only past values (ie causally)
% >> Y=mapwindows(@mean,X,6,0);
%
% To compute a running local median
% >> Y=mapwindows(@median,X,4,3);

N=length(x);

for i=1:min(L,N)
	k=min(i+M,N);
	MM=feval(fn,x(1:k));
	m(:,i)=feval(fn,x(1:k));
end

if N>(L+M)
	m=[m feval(fn,buffer(x,L+M+1,L+M,'nodelay'))];
end

for i=N+(1-M:0)
	j=max(i-L,1);
	m(:,i)=feval(fn,x(j:end));
end

