unit TestSpline;

interface

{$I _crw_sysdef}

{$IFDEF FPC}{$mode Delphi}{$ENDIF}{$H+}

uses
 _crw_sharemem, // NB: THIS UNIT MUST BE FIRST !!!
 {$IFDEF UNIX} cthreads, dl, {$ENDIF}
 {$IFDEF WINDOWS} windows, {$ENDIF}
 sysutils, classes, math,
 _crw_alloc, _crw_ef, _crw_zm, _crw_fpu, _crw_fifo, _crw_sort, _crw_spline;

procedure Test_Spline;

implementation

{$IFDEF UNIX}
uses unix,linux;
function clock_gettime(clk_id : clockid_t; tp: ptimespec) : cint; cdecl; external 'c' name 'clock_gettime';
function GetTickCount64(id:clockid_t=CLOCK_MONOTONIC_COARSE):QWord; inline;
var tp:timespec;
begin
 if (clock_gettime(id, @tp)=0) // exists since Linux Kernel 2.6
 then Result:=(Int64(tp.tv_sec)*1000)+(tp.tv_nsec div 1000000)
 else Result:=0;
end;
{$ENDIF}

function msecnow:int64;
begin
 Result:=GetTickCount64;
end;

function Kernel(x:double; CustomData:Pointer):double;
begin
 Result:=1-sqr(x);
end;

const
 nm=1000;
var
 x,y,w:array[0..nm-1] of double;

procedure Test_Spline;
const nt=1000; dt=1000; np=6; alfa=1e-4; win=0.05;
var z,t,tm,sum:double; i,n:integer; cnt:int64; poly:PDoubleArray; sp:TReinschSpline;
begin
 writeln('Test _spline unit.');
 {
 }
 writeln;
 writeln('Test of LinearInterpolation:');
 writeln('****************************');
 n:=nm;
 for i:=0 to n-1 do begin
  x[i]:=2*pi*i/(n-1);
  y[i]:=sin(x[i]);
 end;
 sum:=0;
 for i:=0 to nt-1 do begin
  t:=2*pi*random;
  z:=LinearInterpolation(x,y,n,t);
  sum:=sum+sqr(z-sin(t));
 end;
 sum:=sqrt(sum/nt);
 writeln('LinearInterpolation residual is ',sum);
 tm:=msecnow+dt;
 cnt:=0;
 while msecnow<tm do begin
  t:=2*pi*random;
  LinearInterpolation(x,y,n,t);
  inc(cnt);
 end;
 writeln('LinearInterpolation timing is ',dt/cnt*1000:11:4,' mks');
 //write('Press enter...'); readln;
 writeln;
 {
 }
 writeln;
 writeln('Test of Polynoms:');
 writeln('*****************');
 n:=nm;
 for i:=0 to n-1 do begin
  x[i]:=2*pi*i/(n-1);
  y[i]:=sin(x[i]);
 end;
 poly:=FindPoly(np,0,1,x,y,n);
 sum:=0;
 for i:=0 to nt-1 do begin
  t:=2*pi*random;
  z:=EvalPoly(poly^,np,t);
  sum:=sum+sqr(z-sin(t));
 end;
 sum:=sqrt(sum/nt);
 writeln('EvalPoly residual is ',sum);
 tm:=msecnow+dt;
 cnt:=0;
 while msecnow<tm do begin
  t:=2*pi*random;
  EvalPoly(poly^,np,t);
  inc(cnt);
 end;
 Deallocate(Pointer(poly));
 writeln('EvalPoly timing is ',dt/cnt*1000:11:4,' mks');
 //write('Press enter...'); readln;
 writeln;
 {
 }
 writeln;
 writeln('Test of Spline:');
 writeln('***************');
 n:=nm;
 for i:=0 to n-1 do begin
  x[i]:=2*pi*i/(n-1);
  y[i]:=sin(x[i]);
  w[i]:=alfa;
 end;
 sp:=NewReinschSpline(x,y,w,n);
 sum:=0;
 for i:=0 to nt-1 do begin
  t:=2*pi*random;
  z:=sp.get(t);
  sum:=sum+sqr(z-sin(t));
 end;
 sum:=sqrt(sum/nt);
 writeln('Spline residual is ',sum);
 tm:=msecnow+dt;
 cnt:=0;
 while msecnow<tm do begin
  t:=2*pi*random;
  sp.Get(t);
  inc(cnt);
 end;
 Kill(sp);
 writeln('Spline timing is ',dt/cnt*1000:11:4,' mks');
 //write('Press enter...'); readln;
 writeln;
 {
 }
 writeln;
 writeln('Test of WindowedKernelSmoothing:');
 writeln('********************************');
 n:=nm;
 for i:=0 to n-1 do begin
  x[i]:=2*pi*i/(n-1);
  y[i]:=sin(x[i]);
 end;
 sum:=0;
 for i:=0 to nt-1 do begin
  t:=2*pi*random;
  z:=WindowedKernelSmoothing(x,y,n,t,win,3,Kernel);
  sum:=sum+sqr(z-sin(t));
 end;
 sum:=sqrt(sum/nt);
 writeln('WindowedKernelSmoothing residual is ',sum);
 tm:=msecnow+dt;
 cnt:=0;
 while msecnow<tm do begin
  t:=2*pi*random;
  WindowedKernelSmoothing(x,y,n,t,win,3,Kernel);
  inc(cnt);
 end;
 writeln('WindowedKernelSmoothing timing is ',dt/cnt*1000:11:4,' mks');
 //write('Press enter...'); readln;
 writeln;
 {
 }
 writeln;
 writeln('Test of WindowedIntegrationSmoothing:');
 writeln('*************************************');
 n:=nm;
 for i:=0 to n-1 do begin
  x[i]:=2*pi*i/(n-1);
  y[i]:=sin(x[i]);
 end;
 sum:=0;
 for i:=0 to nt-1 do begin
  t:=2*pi*random;
  z:=WindowedIntegrationSmoothing(x,y,n,t,win,Kernel);
  sum:=sum+sqr(z-sin(t));
 end;
 sum:=sqrt(sum/nt);
 writeln('WindowedIntegrationSmoothing residual is ',sum);
 tm:=msecnow+dt;
 cnt:=0;
 while msecnow<tm do begin
  t:=2*pi*random;
  WindowedIntegrationSmoothing(x,y,n,t,win,Kernel);
  inc(cnt);
 end;
 writeln('WindowedIntegrationSmoothing timing is ',dt/cnt*1000:11:4,' mks');
 //write('Press enter...'); readln;
 writeln;
 {
 }
 writeln;
 writeln('Test _spline unit end.');
end;

end.
