Code covered by the BSD License  

Highlights from
ScaleTime

image thumbnail
from ScaleTime by Jan Simon
Fast linear interpolation of equally spaced data (C-MEX and M)

TestScaleTime(doSpeed)
function TestScaleTime(doSpeed)
% Test ScaleTime
%
% Tested: Matlab 6.5, 7.7
% Author: Jan Simon, Heidelberg, (C) 2009 J@n-Simon.De

% $JRev: R0f V:005 Sum:265F0599 Date:30-Sep-2009 01:00:47 $
% $File: User\JSim\Published\ScaleTime\TestScaleTime.m $

% Initialize: ==================================================================
ErrID = ['JSim:', mfilename];
whichScaleTime = which('ScaleTime');

disp(['==== Test ScaleTime:  ', datestr(now, 0), char(10), ...
      'Version: ', whichScaleTime, char(10)]);

% Key for linear interpolation - the source of INTERP1 in Matlab6.5 states, that
% "*linear" is the old Matlab 5.3 method. But for large arrays the test of
% equally spaced steps is time-consuming!
% Set it to 'linear', if '*linear' does not work anymore.
linearMethod = '*linear';

if nargin == 0
   doSpeed = true;
end

% Look for lininterp1f, Umberto Picchini, Nov 2005
% http://www.mathworks.com/matlabcentral/fileexchange/8627
hasInterp1f = ~isempty(which('lininterp1f'));

% Look for qinterp1, Nathaniel Brahms,
% http://www.mathworks.com/matlabcentral/fileexchange/10286
hasQinterp1 = ~isempty(which('qinterp1'));

% Do we use the MEX or M version:
[dummy1, dummy2, fileExt] = fileparts(whichScaleTime);  %#ok<ASGLU>
useMex = strcmpi(strrep(fileExt, '.', ''), mexext);

% Start tests: -----------------------------------------------------------------
try
   desc = 'ScaleTime([], [])';
   y = ScaleTime([], []);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isempty(y)
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime([], 1, 2, 0)';
   y = ScaleTime([], 1, 2, 0);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isempty(y)
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime([], 1, 2, -1)';
   y = ScaleTime([], 1, 2, -1);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isempty(y)
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime([1; 2], 1.5, 1, 1)';
   y = ScaleTime([1; 2], 1.5, 1, 1);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isempty(y)
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime((1:10)'', [])';
   y = ScaleTime((1:10)', []);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isempty(y)
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime(ones(10, 10), [])';
   y = ScaleTime(ones(10, 10), []);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isempty(y)
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime((1:10)'', 1)';
   y = ScaleTime((1:10)', 1);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isequal(y, 1)
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime(ones(10, 10), 1)';
   y = ScaleTime(ones(10, 10), 1);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isequal(y, ones(1, 10))
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime(ones(10, 10), 10)';
   y = ScaleTime(ones(10, 10), 10);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isequal(y, ones(1, 10))
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime([1; 2], 1, 1, 1)';
   y = ScaleTime([1; 2], 1, 1, 1);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isequal(y, 1)
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime([1; 2], 1.5, 2, 1)';
   y = ScaleTime([1; 2], 1.5, 2, 1);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isEqualTol(y, 1.5)
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime([1; 3], 1.6)';
   y = ScaleTime([1; 3], 1.6);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isEqualTol(y, 2.2)
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime((1:10)'', 1, 10, 9)';
   y = ScaleTime((1:10)', 1, 10, 9);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isEqualTol(y, (1:1.125:10)')
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime((1:10)'', 1, 10, 10)';
   y = ScaleTime((1:10)', 1, 10, 10);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isEqualTol(y, (1:10)')
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime((1:10)'', 1, 10, 11)';
   y = ScaleTime((1:10)', 1, 10, 11);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isEqualTol(y, (1:0.9:10)')
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime((1:10)'', 1, 9, 8)';
   y = ScaleTime((1:10)', 1, 9, 8);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isEqualTol(y, (1:(8 / 7):9)')
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime((1:10)'', 1, 9, 9)';
   y = ScaleTime((1:10)', 1, 9, 9);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isEqualTol(y, (1:9)')
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime((1:10)'', 1, 9, 10)';
   y = ScaleTime((1:10)', 1, 9, 10);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isEqualTol(y, (1:8/9:9)')
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime(1:10, 1, 9, 10) row vector';
   data = rand(1, 10);
   yRow = ScaleTime(data,    1, 9, 10);
   yCol = ScaleTime(data(:), 1, 9, 10);
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isequal(yRow(:), yCol(:)) && isequal(size(yRow), [1, 10])
   disp(['  ok: ', desc]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

% Compare with INTERP1: --------------------------------------------------------
disp([char(10), '== Compare with INTERP1:']);
try
   desc = 'ScaleTime(sin, 1, 2*pi, 100)';
   data = sin(0:0.1:2*pi)';
   y    = ScaleTime(data, 1, 2*pi, 100);
   yM   = interp1(1:size(data, 1), data, linspace(1, 2*pi, 100)');
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isEqualTol(y, yM)
   disp(['  ok: ', desc, ' == INTERP1']);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime([sin, sin(down:up)], 1, 2*pi, 100)';
   data = cat(2, data, data(end:-1:1));
   y    = ScaleTime(data, 1, 2*pi, 100);
   yM   = interp1(1:size(data, 1), data, linspace(1, 2*pi, 100)');
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isEqualTol(y, yM)
   disp(['  ok: ', desc, ' == INTERP1']);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

try
   desc = 'ScaleTime(rand(100, 100), 1, 100, 57)';
   data = rand(100, 100);
   y    = ScaleTime(data, 1, 100, 57);
   yV   = ScaleTime(data, 1:99/56:100);
   yM   = interp1(1:size(data, 1), data, linspace(1, 100, 57)');
catch
   error(ErrID, ['Crash: ', desc, char(10), lasterr]);
end
if isEqualTol(y, yM, 100 * eps)
   disp(['  ok: ', desc, ' == INTERP1']);
   disp(['      max deviation: ', ...
         sprintf('%.1f * eps', max(abs(y(:) - yM(:))) / eps)]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end
if isEqualTol(y, yV, 100 * eps)
   disp(['  ok: ', desc, ' == ScaleTime(rand(100, 100), 1:99/56:100)']);
   disp(['      max deviation: ', ...
         sprintf('%.1f * eps', max(abs(yM(:) - yV(:))) / eps)]);
else
   error(ErrID, ['Bad reply from: ', desc]);
end

% Speed: -----------------------------------------------------------------------
if doSpeed
   TestTime = 0.5;  % sec
   fprintf('\n== Speed test (test time: %g sec):\n', TestTime);
else
   TestTime = 0.1;
   fprintf('\n== Speed test (test time: %g sec - may be inaccurate):\n', ...
      TestTime);
end

DataLen   = [10, 100, 1000, 10000, 100000];
DataWidth = [1, 10, 100];
InterpLen = [10, 100, 1000, 10000];

for aDataLen = DataLen
   for aDataWidth = DataWidth
      fprintf('Data size: [%d x %d]\n', aDataLen, aDataWidth);
      fprintf('  Interpolation steps:  ');
      fprintf('  %7d', InterpLen);
      fprintf('\n    INTERP1:            ');
      for aInterpLen = InterpLen
         Data = rand(aDataLen, aDataWidth);
         NewT = 1:(aDataLen - 1) / (aInterpLen - 1):aDataLen;
         
         % At least 2 loops!
         iTime     = cputime;
         y         = interp1(1:aDataLen, Data, NewT, linearMethod); %#ok<*NASGU>
         y         = interp1(1:aDataLen, Data, NewT, linearMethod);
         interp1_N = 2;
         while cputime - iTime < TestTime
            y         = interp1(1:aDataLen, Data, NewT, linearMethod);
            interp1_N = interp1_N + 1;
         end
         aTime        = cputime - iTime;
         interp1_Loop = interp1_N / aTime;  % Loops per second
         PrintLoop(interp1_Loop);
      end
      fprintf('  loops/sec\n');
      drawnow;
      
      fprintf('    ScaleTime (vector): ');
      for aInterpLen = InterpLen
         Data = rand(aDataLen, aDataWidth);
         NewT = 1:(aDataLen - 1) / (aInterpLen - 1):aDataLen;
         
         iTime    = cputime;
         y        = ScaleTime(Data, NewT);
         y        = ScaleTime(Data, NewT);
         ScaleV_N = 2;
         while cputime - iTime < TestTime
            y        = ScaleTime(Data, NewT);
            ScaleV_N = ScaleV_N + 1;
         end
         aTime       = cputime - iTime;
         ScaleV_Loop = ScaleV_N / aTime;  % Loops per second
         PrintLoop(ScaleV_Loop);
      end
      fprintf('  loops/sec\n');
      drawnow;
      
      fprintf('    ScaleTime (index):  ');
      for aInterpLen = InterpLen
         iTime    = cputime;
         y        = ScaleTime(Data, 1, aDataLen, aInterpLen);
         y        = ScaleTime(Data, 1, aDataLen, aInterpLen);
         ScaleT_N = 2;
         while cputime - iTime < TestTime
            y        = ScaleTime(Data, 1, aDataLen, aInterpLen);
            ScaleT_N = ScaleT_N + 1;
         end
         aTime       = cputime - iTime;
         ScaleT_Loop = ScaleT_N / aTime;  % Loops per second
         PrintLoop(ScaleT_Loop);
      end
      fprintf('  loops/sec\n');
      drawnow;
      
      % Compare with local Matlab version:
      if useMex
         fprintf('    ScaleTime (Matlab): ');
         for aInterpLen = InterpLen
            iTime    = cputime;
            NewT     = 1:(aDataLen - 1) / (aInterpLen - 1):aDataLen;
            y        = ScaleTime_local(Data, NewT);
            y        = ScaleTime_local(Data, NewT);
            ScaleM_N = 2;
            while cputime - iTime < TestTime
               y        = ScaleTime_local(Data, NewT);
               ScaleM_N = ScaleM_N + 1;
            end
            aTime       = cputime - iTime;
            ScaleM_Loop = ScaleM_N / aTime;  % Loops per second
            PrintLoop(ScaleM_Loop);
         end
         fprintf('  loops/sec\n');
         drawnow;
      end
      
      % Compare with functions from Matlab's FEX:
      if hasInterp1f && aDataWidth == 1
         fprintf('    lininterp1f:        ');
         for aInterpLen = InterpLen
            iTime      = cputime;
            NewT       = 1:(aDataLen - 1) / (aInterpLen - 1):aDataLen;
            y          = lininterp1f(1:length(Data), Data, NewT, []);
            y          = lininterp1f(1:length(Data), Data, NewT, []);
            interp1f_N = 2;
            while cputime - iTime < TestTime
               y          = lininterp1f(1:length(Data), Data, NewT, []);
               interp1f_N = interp1f_N + 1;
            end
            aTime         = cputime - iTime;
            interp1f_Loop = interp1f_N / aTime;  % Loops per second
            PrintLoop(interp1f_Loop);
         end
         fprintf('  loops/sec\n');
         drawnow;
      end
      
      if hasQinterp1 && aDataWidth == 1
         fprintf('    qinterp1:           ');
         for aInterpLen = InterpLen
            iTime      = cputime;
            NewT       = 1:(aDataLen - 1) / (aInterpLen - 1):aDataLen;
            y          = qinterp1(1:length(Data), Data, NewT, 1);
            y          = qinterp1(1:length(Data), Data, NewT, 1);
            qinterp1_N = 2;
            while cputime - iTime < TestTime
               y          = qinterp1(1:length(Data), Data, NewT, 1);
               qinterp1_N = qinterp1_N + 1;
            end
            aTime         = cputime - iTime;
            qinterp1_Loop = qinterp1_N / aTime;  % Loops per second
            PrintLoop(qinterp1_Loop);
         end
         fprintf('  loops/sec\n');
         drawnow;
      end
      
      fprintf('\n');
   end
end

return;

% ******************************************************************************
function PrintLoop(N)
if N > 10
   fprintf('  %7.0f', N);
else
   fprintf('  %7.1f', N);
end

return;

% ******************************************************************************
% Local copy of ScaleTime to test speed if compiled MEX is in the path:
function Yi = ScaleTime_local(Y, Ti, Tf, Tn)
% Author: Jan Simon, Heidelberg, (C) 2009 J@n-Simon.De
% Was JRev: R0h V:033 Sum:98748BA6 Date:30-Sep-2009 00:50:13 $
% Was File: Tools\GLMath\ScaleTime.m $

[nRow, nCol] = size(Y);
doTranspose  = (nRow == 1 && nCol > 1);
if doTranspose
   nRow = nCol;
   nCol = 1;
   Y    = Y(:);
end

switch nargin
   case 4
      if and(Ti < 1, Tf > nRow)
         error(['*** ', mfilename, ': Interpolation frames out of range.']);
      end
      
      if Tn < 1.0
         Yi = [];
         return;
      elseif Tn > 1
         Ti = Ti:((Tf - Ti) / (Tn - 1)):Tf;
      elseif Tf < Ti
         Ti = [];
      end
      
   case 2
      if any(Ti < 1)
         error(['*** ', mfilename, ': All [Ti] must be >= 1.']);
      end
      if any(Ti > nRow)
         error(['*** ', mfilename, ...
               ': All [Ti] must be <= number of rows of Y.']);
      end
      
   otherwise
      error(['*** ', mfilename, ': 2 or 4 inputs required.']);
end

if isempty(Ti)
   Yi = [];
   return;
end

if nRow < 2
   error(['*** ', mfilename, ': Y must have at least 2 rows.']);
end

Ti = Ti(:);
Si = Ti - floor(Ti);
Ti = floor(Ti);

d     = (Ti == nRow);
Ti(d) = Ti(d) - 1;
Si(d) = 1;

if nCol > 1
   Si = Si(:, ones(1, nCol));
end
Yi = Y(Ti, :) .* (1 - Si) + Y(Ti + 1, :) .* Si;

if doTranspose
   Yi = reshape(Yi, 1, []);
end

return;

Contact us at files@mathworks.com