Recent

Author Topic: Strange error with arccos()  (Read 5477 times)

Josh

  • Hero Member
  • *****
  • Posts: 1274
Re: Strange error with arccos()
« Reply #30 on: August 05, 2022, 08:09:07 pm »
Difference in speed I think is too dependent on CPU / architecture /OS but results I get on my HP Laptop
Intel(R) Pentium(R) CPU 5405U @ 2.30GHz  win 11 64, 8GB RAM. Laz/FPC Trunk 64 bit.

Quote
Calculating and testing 20000000 samples
Testing Math.arctan2... done: 1.796 sec
Testing PaoloArctan2... done: 2.161 sec
Testing JoshArctan2... done: 1.690 sec
Finished. Calculating
Check difference between math and josh Press ENTER.

Differences 0
Total of Differences 0.0000000000000000

Check difference between math and Paolo Press ENTER.

Differences 1143105
Total of Differences 0.0000000003991967

Finished Press ENTER
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

Paolo

  • Hero Member
  • *****
  • Posts: 510
Re: Strange error with arccos()
« Reply #31 on: August 05, 2022, 08:19:08 pm »
@Josh, In my testing I don't see too much difference (on both intel and AMD), but can you repeat the test with "constant" input X=Y=0 ?

Josh

  • Hero Member
  • *****
  • Posts: 1274
Re: Strange error with arccos()
« Reply #32 on: August 05, 2022, 08:34:58 pm »
Quote
Calculating and testing 20000000 random x & y samples
Testing Math.arctan2... done: 1.613 sec
Testing PaoloArctan2... done: 2.134 sec
Testing JoshArctan2... done: 1.463 sec
Finished. Calculating
Check difference between math and josh Press ENTER.

Differences 0
Total of Differences 0.0000000000000000

Check difference between math and Paolo Press ENTER.

Differences 1143105
Total of Differences 0.0000000003991967

Finished Press ENTER
Quote
Calculating and testing 20000000 samples with all x=0
Testing Math.arctan2... done: 1.036 sec
Testing PaoloArctan2... done: 1.215 sec
Testing JoshArctan2... done: 0.428 sec
Finished. Calculating
Check difference between math and josh Press ENTER.

Differences 0
Total of Differences 0.0000000000000000

Check difference between math and Paolo Press ENTER.

Differences 0
Total of Differences 0.0000000000000000

Finished Press ENTER
Quote
Calculating and testing 20000000 samples with all y=0
Testing Math.arctan2... done: 1.107 sec
Testing PaoloArctan2... done: 1.245 sec
Testing JoshArctan2... done: 0.709 sec
Finished. Calculating
Check difference between math and josh Press ENTER.

Differences 0
Total of Differences 0.0000000000000000

Check difference between math and Paolo Press ENTER.

Differences 0
Total of Differences 0.0000000000000000

Finished Press ENTER
Quote
Calculating and testing 20000000 samples with all y=0 and x=0
Testing Math.arctan2... done: 0.880 sec
Testing PaoloArctan2... done: 0.890 sec
Testing JoshArctan2... done: 0.466 sec
Finished. Calculating
Check difference between math and josh Press ENTER.

Differences 0
Total of Differences 0.0000000000000000

Check difference between math and Paolo Press ENTER.

Differences 0
Total of Differences 0.0000000000000000

Finished Press ENTER
« Last Edit: August 05, 2022, 08:38:46 pm by Josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

Paolo

  • Hero Member
  • *****
  • Posts: 510
Re: Strange error with arccos()
« Reply #33 on: August 05, 2022, 08:59:20 pm »
How do you explain the result for input x=y=0, my code just test x , y and exit, how do you explain your code is twice faster?

Josh

  • Hero Member
  • *****
  • Posts: 1274
Re: Strange error with arccos()
« Reply #34 on: August 05, 2022, 09:44:40 pm »
code and results below on my laptop
what are others result.
Code: Pascal  [Select][+][-]
  1. program arctan2_speed;
  2.  
  3. uses
  4.   sysutils, math;
  5.  
  6.  
  7.  
  8. function PaoloArcTan2(Y, X : Float) : Float;
  9. begin
  10.   if (X = 0) then begin
  11.     if (Y = 0) then
  12.       Result:=0
  13.     else
  14.       if (Y > 0) then
  15.         Result:=0.5*pi
  16.       else
  17.         Result:=-0.5*pi
  18.   end
  19.   else begin
  20.     Result:=ArcTan(Y/X);
  21.     if (X < 0) then
  22.       if (Y < 0) then
  23.         Result:=Result-pi
  24.       else
  25.         Result:=Result+pi
  26.   end;
  27. end;
  28.  
  29. function JoshArcTan2 (y, x : Float) : Float;
  30. begin
  31.  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
  32.    else if x <0.0 then result := arctan (y/x) + pi
  33.      else if y<>0.0 then result := pi/2 * sign (y)
  34.             else result:=0.0;// x=0 so if y is also 0.0 result stays set at 0.00 else result gets set +-pi/2
  35.  
  36.  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
  37. end;
  38.  
  39. const
  40.   MILLION = 1000 * 1000;
  41.   N = 20 * MILLION;
  42.  
  43. type
  44.   TArcTan2Func = function(y, x: Float): Float;
  45.  
  46.   TData = record
  47.     x, y: Float;
  48.   end;
  49.  
  50. var
  51.   Data: array[1..n] of TData;
  52.   j,m,p:Array[1..n] of Float;
  53.  
  54. procedure PrepareData(fixx,fixy:boolean;v:float);
  55. var
  56.   i: Integer;
  57. begin
  58.  // randomize;
  59.   RandSeed := 0;
  60.   for i := 1 to N do
  61.   begin
  62.     if fixx then Data[i].X:=v else Data[i].X := (Random()-0.5) * high(dword);
  63.     if fixy then Data[i].Y:=v else Data[i].Y := (Random()-0.5) * high(dword);
  64.   end;
  65. end;
  66.  
  67. procedure Test(Descr: String; ArcTan2Func: TArcTan2Func; w:string);
  68. var
  69.   t: TDateTime;
  70.   i: Integer;
  71.   ans:float;
  72. begin
  73.   Write('Testing ' + Descr + '...');
  74.   RandSeed := 0;
  75.   t := Now;
  76.   for i := 1 to N do
  77.   begin
  78.     ans:=ArcTan2Func(Data[i].Y, Data[i].X);
  79.     case w of
  80.       'j':j[i]:=ans;
  81.       'm':m[i]:=ans;
  82.       'p':p[i]:=ans;
  83.     end;
  84.   end;
  85.   t := Now - t;
  86.   WriteLn(' done: ', FormatDateTime('s.zzz', t), ' sec');
  87. end;
  88. var l,c:integer;
  89.   td:extended;
  90.  
  91. procedure reportresult(heading:string);
  92. begin
  93.   WriteLn(heading);
  94.   Test('Math.arctan2', @arctan2,'m');
  95.   Test('PaoloArctan2', @paoloarctan2,'p');
  96.   Test('JoshArctan2', @josharctan2,'j');
  97.   WriteLn('Finished. Calculating');
  98.   Write('Check difference between math and Josh');
  99.   c:=0;
  100.   td:=0;
  101.   for l:=1 to n do
  102.   begin
  103.     if j[l]<>m[l] then
  104.       begin
  105.         inc(c);
  106.         td:=td+abs(j[l]-m[l]);
  107.       end;
  108.   end;
  109.   if c=0 then WriteLn(' No Differences')
  110.   else
  111.   begin
  112.     WriteLn;
  113.     WriteLn('     Differences '+c.ToString+'Total of Differences ',td:4:16);
  114.   end;
  115.   Write('Check difference between math and Paolo');
  116.   c:=0;
  117.   td:=0;
  118.   for l:=1 to n do
  119.   begin
  120.     if m[l]<>p[l] then
  121.       begin
  122.         inc(c);
  123.         td:=td+abs(p[l]-m[l]);
  124.       end;
  125.   end;
  126.   if c=0 then WriteLn(' No Differences')
  127.   else
  128.   begin
  129.     WriteLn;
  130.     WriteLn('     Differences '+c.ToString+'Total of Differences ',td:4:16);
  131.   end;
  132.   Writeln('** End of Test ** '+heading);
  133.   Writeln;Writeln;
  134. end;
  135.  
  136. begin
  137.   randomize;
  138.   PrepareData(false,false,0);
  139.   reportresult('Calculating and testing '+n.ToString+' random x & y samples');
  140.   PrepareData(true,false,0);
  141.   reportresult('Calculating and testing '+n.ToString+' samples with all x=0');
  142.   PrepareData(false,true,0);
  143.   reportresult('Calculating and testing '+n.ToString+' samples with all y=0');
  144.   PrepareData(true,true,0);
  145.   reportresult('Calculating and testing '+n.ToString+' samples with all y=0 and x=0');
  146.   ReadLn;
  147. end.
  148.  

result from above code
Quote
Calculating and testing 20000000 random x & y samples
Testing Math.arctan2... done: 1.527 sec
Testing PaoloArctan2... done: 1.858 sec
Testing JoshArctan2... done: 1.165 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo
     Differences 1143105Total of Differences 0.0000000003991967
** End of Test ** Calculating and testing 20000000 random x & y samples


Calculating and testing 20000000 samples with all x=0
Testing Math.arctan2... done: 0.694 sec
Testing PaoloArctan2... done: 0.880 sec
Testing JoshArctan2... done: 0.275 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo No Differences
** End of Test ** Calculating and testing 20000000 samples with all x=0


Calculating and testing 20000000 samples with all y=0
Testing Math.arctan2... done: 0.764 sec
Testing PaoloArctan2... done: 0.976 sec
Testing JoshArctan2... done: 0.465 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo No Differences
** End of Test ** Calculating and testing 20000000 samples with all y=0


Calculating and testing 20000000 samples with all y=0 and x=0
Testing Math.arctan2... done: 0.507 sec
Testing PaoloArctan2... done: 0.727 sec
Testing JoshArctan2... done: 0.191 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo No Differences
** End of Test ** Calculating and testing 20000000 samples with all y=0 and x=0

I assume to check for >0.00 the compiler would just check that the MSB is set to on; to evaluate the expression, to compare with a specific value it would need to check the whole value for comparison 8 bytes.
I always where possible use this technique <0 or >0 as it is generally much faster,even with integers.
« Last Edit: August 05, 2022, 10:29:01 pm by Josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

d4eva

  • New Member
  • *
  • Posts: 24
Re: Strange error with arccos()
« Reply #35 on: August 05, 2022, 10:18:41 pm »
Results on Mac M1 mini compiled as native aarch64

Calculating and testing 20000000 random x & y samples
Testing Math.arctan2... done: 0.761 sec
Testing PaoloArctan2... done: 0.924 sec
Testing JoshArctan2... done: 0.596 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo
     Differences 1141138Total of Differences 0.0000000003992473
** End of Test ** Calculating and testing 20000000 random x & y samples


Calculating and testing 20000000 samples with all x=0
Testing Math.arctan2... done: 0.339 sec
Testing PaoloArctan2... done: 0.493 sec
Testing JoshArctan2... done: 0.098 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo No Differences
** End of Test ** Calculating and testing 20000000 samples with all x=0


Calculating and testing 20000000 samples with all y=0
Testing Math.arctan2... done: 0.376 sec
Testing PaoloArctan2... done: 0.523 sec
Testing JoshArctan2... done: 0.239 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo No Differences
** End of Test ** Calculating and testing 20000000 samples with all y=0


Calculating and testing 20000000 samples with all y=0 and x=0
Testing Math.arctan2... done: 0.238 sec
Testing PaoloArctan2... done: 0.375 sec
Testing JoshArctan2... done: 0.095 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo No Differences
** End of Test ** Calculating and testing 20000000 samples with all y=0 and x=0

BobDog

  • Sr. Member
  • ****
  • Posts: 394
Re: Strange error with arccos()
« Reply #36 on: August 05, 2022, 10:41:36 pm »
Purely for fun..
Added this to my test application - see attachment. Of course, it is much slower than the others based on the built-in arctan, but it is an interesting alternative on systems where unit math is not applicable. I added one optimization: your code had calculated the value of pi with every call of the Arctan2 function, and this doubles the entire execution time. Now pi (called MyPI here) is calculated only once per program run. Very probably, further optimizations are possible.

These are my result for a 32-bit application on Win 11
Quote
Testing Math.arctan2... done: 0.818 sec
Testing PaoloArctan2... done: 1.057 sec
Testing JoshArctan2... done: 1.073 sec
Testing BobDogArctan2... done: 6.723 sec
Finished. Press ENTER to close.
and for a 64-bit application on Win 11:
Quote
Testing Math.arctan2... done: 0.446 sec
Testing PaoloArctan2... done: 0.471 sec
Testing JoshArctan2... done: 0.498 sec
Testing BobDogArctan2... done: 4.378 sec
Finished. Press ENTER to close.
Hi wp
I have set the counter at zero in my code.
Thanks for noticing that.
Couldn't you use (for speed)
 const MyPi=3.141592653589793;
just above the var near the function end.


Paolo

  • Hero Member
  • *****
  • Posts: 510
Re: Strange error with arccos()
« Reply #37 on: August 05, 2022, 10:45:51 pm »
@Josh and 4deva,

try to modify the case test sequence

from
Code: Pascal  [Select][+][-]
  1.     case w of
  2.       'j':j[i]:=ans;
  3.       'm':m[i]:=ans;
  4.       'p':p[i]:=ans;
  5.     end;
  6.  

to
Code: Pascal  [Select][+][-]
  1.     case w of
  2.       'p':p[i]:=ans;
  3.       'j':j[i]:=ans;
  4.       'm':m[i]:=ans;
  5.     end;
  6.  

and tell me the results :)

Paolo

  • Hero Member
  • *****
  • Posts: 510
Re: Strange error with arccos()
« Reply #38 on: August 05, 2022, 11:06:54 pm »
@Josh, trying to compile in "debug" mode I see error in the picture ("default" and "Release" are fine)

I did a working copy...
« Last Edit: August 05, 2022, 11:33:07 pm by Paolo »

jamie

  • Hero Member
  • *****
  • Posts: 6133
Re: Strange error with arccos()
« Reply #39 on: August 06, 2022, 03:42:00 am »
For a good time in bug hunting..

 ArcCos(YourValue Mod 1.0);

 :o
The only true wisdom is knowing you know nothing

d4eva

  • New Member
  • *
  • Posts: 24
Re: Strange error with arccos()
« Reply #40 on: August 06, 2022, 08:33:01 am »
Results after changing the switch statement:

Calculating and testing 20000000 random x & y samples
Testing Math.arctan2... done: 0.937 sec
Testing PaoloArctan2... done: 0.627 sec
Testing JoshArctan2... done: 0.731 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo
     Differences 1141138Total of Differences 0.0000000003992473
** End of Test ** Calculating and testing 20000000 random x & y samples


Calculating and testing 20000000 samples with all x=0
Testing Math.arctan2... done: 0.499 sec
Testing PaoloArctan2... done: 0.188 sec
Testing JoshArctan2... done: 0.238 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo No Differences
** End of Test ** Calculating and testing 20000000 samples with all x=0


Calculating and testing 20000000 samples with all y=0
Testing Math.arctan2... done: 0.532 sec
Testing PaoloArctan2... done: 0.209 sec
Testing JoshArctan2... done: 0.393 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo No Differences
** End of Test ** Calculating and testing 20000000 samples with all y=0


Calculating and testing 20000000 samples with all y=0 and x=0
Testing Math.arctan2... done: 0.395 sec
Testing PaoloArctan2... done: 0.095 sec
Testing JoshArctan2... done: 0.232 sec
Finished. Calculating
Check difference between math and Josh No Differences
Check difference between math and Paolo No Differences
** End of Test ** Calculating and testing 20000000 samples with all y=0 and x=0



Paolo

  • Hero Member
  • *****
  • Posts: 510
Re: Strange error with arccos()
« Reply #41 on: August 06, 2022, 09:02:30 am »
@d4eva, thanks to check.
This explain the huge difference in the results.
Any speed test should avoid things that interfere with the measurement. I have also the suspect on the array dimension playing some role.
« Last Edit: August 06, 2022, 09:16:41 am by Paolo »

Josh

  • Hero Member
  • *****
  • Posts: 1274
Re: Strange error with arccos()
« Reply #42 on: August 06, 2022, 07:29:23 pm »
hi

dont normally use internet on weekends..  ;)

yep case is expensive (more than i thought), so replaced with if then statements, so everytime the same comparisons are done, no favour to routines.
.

Also moded test app, so that it repeats the samples unitil stops, but keeps a running total and average time.
The app also nows has a copy of the function from the math unit, so that any optimizations are kept the same.
also moded the matharctan2 function so that it does not -2pi the result; this has the effect of correcting the rounding error and all function generate equal data.

on line 26 if you comment out the define it will compile as factory. ie add // before the define

on my laptop the longer it runs the more they even out...

images are runs of 200+ so each routine visited over 4 Billion Times.



« Last Edit: August 06, 2022, 08:30:25 pm by Josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

Paolo

  • Hero Member
  • *****
  • Posts: 510
Re: Strange error with arccos()
« Reply #43 on: August 06, 2022, 08:16:14 pm »
dont normally use internet on weekends..  ;)
..and it is summer time..  :D, .. and arctan can wait  :D

Can you post your latest version of code ? From my testing I see something still not clear.

Your conclusion on the basis of such results ?

Josh

  • Hero Member
  • *****
  • Posts: 1274
Re: Strange error with arccos()
« Reply #44 on: August 06, 2022, 08:29:02 pm »
test code is added in previous post
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

 

TinyPortal © 2005-2018