function apen = ApEn( dim, r, data, tau )
%ApEn
% dim : embedded dimension
% r : tolerance (typically 0.2 * std)
% data : time-series data
% tau : delay time for downsampling
% Changes in version 1
% Ver 0 had a minor error in the final step of calculating ApEn
% because it took logarithm after summation of phi's.
% In Ver 1, I restored the definition according to original paper's
% definition, to be consistent with most of the work in the
% literature. Note that this definition won't work for Sample
% Entropy which doesn't count self-matching case, because the count
% can be zero and logarithm can fail.
%
% A new parameter tau is added in the input argument list, so the users
% can apply ApEn on downsampled data by skipping by tau.
%---------------------------------------------------------------------
% coded by Kijoon Lee, kjlee@ntu.edu.sg
% Ver 0 : Aug 4th, 2011
% Ver 1 : Mar 21st, 2012
%---------------------------------------------------------------------
%
%
%Copyright (c) 2012, Kijoon Lee
%All rights reserved.
%
%Redistribution and use in source and binary forms, with or without
%modification, are permitted provided that the following conditions are
%met:
%
% * Redistributions of source code must retain the above copyright
% notice, this list of conditions and the following disclaimer.
% * Redistributions in binary form must reproduce the above copyright
% notice, this list of conditions and the following disclaimer in
% the documentation and/or other materials provided with the distribution
%
%THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
%AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
%IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
%ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
%LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
%CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
%SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
%INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
%CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
%ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
%POSSIBILITY OF SUCH DAMAGE.
%
%
if nargin < 4, tau = 1; end
if tau > 1, data = downsample(data, tau); end
N = length(data);
result = zeros(1,2);
for j = 1:2
m = dim+j-1;
phi = zeros(1,N-m+1);
dataMat = zeros(m,N-m+1);
% setting up data matrix
for i = 1:m
dataMat(i,:) = data(i:N-m+i);
end
% counting similar patterns using distance calculation
for i = 1:N-m+1
tempMat = abs(dataMat - repmat(dataMat(:,i),1,N-m+1));
boolMat = any( (tempMat > r),1);
phi(i) = sum(~boolMat)/(N-m+1);
end
% summing over the counts
result(j) = sum(log(phi))/(N-m+1);
end
apen = result(1)-result(2);
end