function [h,h2,rs] = chebdiff(N,L,us,ls)
% h = chebdiff(N,L,us,ls,g)
% A program for the design of symmetric FIR lowpass
% differentiators with flat passbands and equiripple stopbands.
%
% output
%  h  : filter
% input 
%  us : upper bound in stop band
%  ls : lower bound in stop band
%
% % EXAMPLE
%    N  =  16;
%    L  =  6;
%    us =  0.01;
%    ls = -us;
%    [h,h2,rs] = chebdiff(N,L,us,ls);

% Reference:
% "Exchange Algorithms for the Design of Linear Phase FIR Filters 
% and Differentiators Having Flat Monotonic Passbands and Equiripple 
% Stopbands" by I. W. Selesnick and C. S. Burrus, 
% IEEE Trans. on Cicuits and Systems II, 43(9):671-675, Sept 1996


% required subprogram: localmax.m

if (rem(N,2) == 1) | (rem(L,2) == 1)
   disp('N and L must both be even')
   return
else

g = 2^ceil(log2(4*N));               % number of grid points

q  = (N-L)/2;			% number of filter parameters

% compute "d" coefficients of structure
d = 2;
for k = 1:L/2
	d(k+1) = prod(1:2:2*k-1)/(k*(2*k+1)*prod(1:(k-1))*(2^(2*k-1)));
end

SN  = 1e-9;                     % SN : SMALL NUMBER
Y   = [ls*(1-(-1).^(1:q))/2 + us*((-1).^(1:q)+1)/2]';
w   = [0:g]'*pi/g;		% w : frequency grid
wo  = pi*(L/2)/((L/2)+(q-1));
wo  = wo - (us-ls);		% initial estimate of stopband edge
m   = 0:q-1;
rs  = m'*(pi-wo)/(q-1) + wo;	% rs: reference set.
Z   = zeros(2*(g+2-q)-3,1);

C  = 1-cos(w);
Cr = 1-cos(rs);
S  = sin(w/2);
Sr = sin(rs/2);
it = 0;
while 1 & (it < 10)

   rhs = Y./Sr;
   for k = 1:L/2
      rhs = (rhs-d(k))./Cr;
   end
   a3 = cos(rs*m)\rhs;		% solve for coefficients
   A3 = real(fft([a3(1);a3(2:q)/2;Z;a3(q:-1:2)/2])); A3 = A3(1:g+1);
				% A3 : Amplitude
   A = A3;
   for k = L/2:-1:1
      A = A.*C+d(k);
   end
   A = A.*S;			% A : Amplitude of total filter

   figure(1), plot(w/pi,A),
        hold on, plot(rs/pi,Y,'o'), hold off, 

   % update the reference set
   ri = sort([localmax(A); localmax(-A)]);
   ri(1:length(ri)-q) = [];
   rs = (ri-1)*pi/g;
   % rs = refine3(a,L/2,rs);
   Cr = 1-cos(rs);
   Sr  = sin(rs/2);
  
   % evaluate Amplitude over the reference set rs 
   Ar = cos(rs*m)*a3;
   for k = L/2:-1:1
      Ar = Ar.*Cr+d(k); 
   end
   Ar = Ar.*Sr;

   % check stopping criterion
   Err = max([max(Ar)-us, ls-min(Ar)]);
   fprintf(1,'    Err = %18.15f\n',Err);
   if Err < SN, fprintf(1,'\n    I have converged \n'), break, end
   it = it + 1;
end

% construct symmetric filter from cosine coefficients
h3 = [a3(q:-1:2)/2; a3(1); a3(2:q)/2];
h = h3;
% use the parameterization 
for k = L/2:-1:1
   h = conv(h,[-1 2 -1]')/2;
   h((length(h)+1)/2) = h((length(h)+1)/2) + d(k);
end
h = conv(h,[1 -1]/2);

end


