program arctan2_speed;
uses
sysutils, math;
function PaoloArcTan2(Y, X : Float) : Float;
begin
if (X = 0) then begin
if (Y = 0) then
Result:=0
else
if (Y > 0) then
Result:=pi/2
else
Result:=-pi/2
end
else begin
Result:=ArcTan(Y/X);
if (X < 0) then
if (Y < 0) then
Result:=Result-pi
else
Result:=Result+pi
end;
end;
function JoshArcTan2 (y, x : Float) : Float;
begin
result:=0.0; // set to 0.0 if it falls through with x and y =0.00 also stops hint result not initialized
if x>0.0 then result := arctan (y/x) // using /2 rather than *.5 as old school / was generally more accurate and for me more readable
else if x <0.0 then result := arctan (y/x) + pi
else if y<>0.0 then result := pi/2 * sign (y); // x=0 so if y is also 0.0 result stays set at 0.00 else result gets set +-pi/2
if result>pi then result:=result-2*pi; // keep result in range of +- pi could use abs sign here but then would be used every iteration of function
// else if result<-pi then result:=result+2*pi; // not sure if needed but safguarded like original code
// same check as math unit
end;
const
MILLION = 1000 * 1000;
N = 5 * MILLION;
type
TArcTan2Func = function(y, x: Float): Float;
TData = record
x, y: Float;
end;
var
Data: array[1..n] of TData;
j,m,p:Array[1..n] of Float;
procedure PrepareData;
var
i: Integer;
begin
RandSeed := 0;
for i := 1 to N do
begin
Data[i].X := (Random()-0.5) * high(dword);
Data[i].Y := (Random()-0.5) * high(dword);
end;
end;
procedure Test(Descr: String; ArcTan2Func: TArcTan2Func; w:string);
var
t: TDateTime;
i: Integer;
ans:float;
begin
Write('Testing ' + Descr + '...');
RandSeed := 0;
t := Now;
for i := 1 to N do
begin
ans:=ArcTan2Func(Data[i].Y, Data[i].X);
case w of
'j':j[i]:=ans;
'm':m[i]:=ans;
'p':p[i]:=ans;
end;
end;
t := Now - t;
WriteLn(' done: ', FormatDateTime('s.zzz', t), ' sec');
end;
var l,c:integer;
begin
PrepareData;
Test('Math.arctan2', @arctan2,'m');
Test('PaoloArctan2', @paoloarctan2,'p');
Test('JoshArctan2', @josharctan2,'j');
WriteLn('Finished. Calculating');
WriteLn('Check difference between josh and math Press ENTER.');
readln;
c:=0;
for l:=1 to n do
begin
if j[l]<>m[l] then
begin
writeln(l,':',j[l]-m[l]);
inc(c);
end;
end;
WriteLn('Differences '+c.ToString);
WriteLn('Check difference between josh and paola Press ENTER.');
readln;
c:=0;
for l:=1 to n do
begin
if j[l]<>p[l] then
begin
writeln(l,':',j[l]-p[l]);
inc(c);
end;
end;
WriteLn('Differences '+c.ToString);
ReadLn;
end.