sandbox/easystab/poldif.m

    function DM = poldif(x, malpha, B)
    
    %  The function DM =  poldif(x, maplha, B) computes the
    %  differentiation matrices D1, D2, ..., DM on arbitrary nodes.
    %
    %  The function is called with either two or three input arguments.
    %  If two input arguments are supplied, the weight function is assumed 
    %  to be constant.   If three arguments are supplied, the weights should 
    %  be defined as the second and third arguments.
    %
    %  Input (constant weight):
    %
    %  x:        Vector of N distinct nodes.
    %  malpha:   M, the number of derivatives required (integer).
    %  B:        Omitted.
    %
    %  Note:     0 < M < N-1.
    %
    %  Input (non-constant weight):
    %
    %  x:        Vector of N distinct nodes.
    %  malpha:   Vector of weight values alpha(x), evaluated at x = x(k).
    %  B:        Matrix of size M x N,  where M is the highest 
    %            derivative required.  It should contain the quantities 
    %            B(ell,j) = beta(ell,j) = (ell-th derivative
    %            of alpha(x))/alpha(x),   evaluated at x = x(j).
    %
    %  Output:
    %  DM:       DM(1:N,1:N,ell) contains ell-th derivative matrix, ell=1..M.
    
    %  J.A.C. Weideman, S.C. Reddy 1998
    
           N = length(x);                      
           x = x(:);                     % Make sure x is a column vector 
    
    if nargin == 2                       % Check if constant weight function
           M = malpha;                   % is to be assumed.
       alpha = ones(N,1);              
           B = zeros(M,N);
    elseif nargin == 3
       alpha = malpha(:);                % Make sure alpha is a column vector
           M = length(B(:,1));           % First dimension of B is the number 
    end                                  % of derivative matrices to be computed
     
            I = eye(N);                  % Identity matrix.
            L = logical(I);              % Logical identity matrix.
    
           XX = x(:,ones(1,N));
           DX = XX-XX';                  % DX contains entries x(k)-x(j).
    
        DX(L) = ones(N,1);               % Put 1's one the main diagonal.
    
            c = alpha.*prod(DX,2);       % Quantities c(j).
    
            C = c(:,ones(1,N)); 
            C = C./C';                   % Matrix with entries c(k)/c(j).
       
            Z = 1./DX;                   % Z contains entries 1/(x(k)-x(j))
         Z(L) = zeros(N,1);              % with zeros on the diagonal.
    
            X = Z';                      % X is same as Z', but with 
         X(L) = [];                      % diagonal entries removed.
            X = reshape(X,N-1,N);
    
            Y = ones(N-1,N);             % Initialize Y and D matrices.
            D = eye(N);                  % Y is matrix of cumulative sums,
                                         % D differentiation matrices.
    for ell = 1:M
            Y   = cumsum([B(ell,:); ell*Y(1:N-1,:).*X]); % Diagonals
            D   = ell*Z.*(C.*repmat(diag(D),1,N) - D);   % Off-diagonals
         D(L)   = Y(N,:);                                % Correct the diagonal
    DM(:,:,ell) = D;                                     % Store the current D
    end