Code covered by the BSD License  

Highlights from
The matrix exponential

from The matrix exponential by Thomas Schmelzer
Computes exp(A)*b where A is real and symmetric

cf_realaxis(fct,n,varargin)
% Caratheodory-Fejer method for constructing a uniform rational approximation 
% of the function f of type (n,n) on the negative real axis. 
% This is a modified version of a code published in 
% Trefethen, Weideman, Schmelzer
% Talbot Quadratures and Rational Approximations
% BIT, 2006

% zi      -- poles of the rational function
% ci      -- residues associated with those poles
% r_inf   -- r at infinity
% decay   -- SVD of the Hankel matrix associated with the problem
% s       -- error introduced by the (n,n) approximation.
function [zi,ci,r_inf,s,decay] = cf_realaxis(fct,n,varargin)

  K = 75;                                 % no of Cheb coeffs
  nf = 1024;                              % no of pts for FFT
  w = exp(2i*pi*(0:nf-1)/nf);             % roots of unity
  t = real(w);                            % Cheb pts (twice over)
  scl = 9;                                % scale factor for stability
  F = zeros(size(t));
  g = (t~=-1);
  F(g) = feval(fct,scl*(t(g)-1)./(t(g)+1),varargin{:});
  c = real(fft(real(F)))/nf;              % Cheb coeffs of F
  f = polyval(c(K+1:-1:1),w);             % analytic part f of F
  [U,S,V] = svd(hankel(c(2:K+1)));        % SVD of Hankel matrix
  s = S(n+1,n+1);                         % singular value
  decay = diag(S);                        % decay of the error
  u = U(K:-1:1,n+1)'; v = V(:,n+1)';      % singular vectors
  zz = zeros(1,nf-K);                     % zeros for padding
  b = fft([u zz])./fft([v zz]);           % finite Blaschke product
  rt = f-s*w.^K.*b;                       % extended function r-tilde
  zr = roots(v); qj = zr(abs(zr)>1);      % poles
  qc = poly(qj);                          % coeffs of denominator
  pt = rt.*polyval(qc,w);                 % numerator
  ptc = real(fft(pt)/nf);                 % coeffs of numerator
  ptc = ptc(n+1:-1:1); ci = 0*qj;
  for k = 1:n                             % calculate residues
    q = qj(k); q2 = poly(qj(qj~=q));
    ci(k) = polyval(ptc,q)/polyval(q2,q);
  end
  zi = scl*(qj-1).^2./(qj+1).^2;          % poles in z-plane
  ci = 4*ci.*zi./(qj.^2-1);               % residues in z-plane
  r_inf = 0.5*(feval(fct,0,varargin{:})+sum(ci./zi));    % r at infinity

  [m, order]=sort(imag(zi));              % sort poles
  zi=zi(order);                           % reorder poles
  ci=ci(order);                           % reorder residues

Contact us at files@mathworks.com