Submit it to bugtracker so that i can be considered by the FPC devs.any comment on that ?
function MyArcTan2(Y, X : float) : float; begin if (X = 0) then begin if (Y = 0) then Result:=0 else if (Y > 0) then Result:=0.5*pi else Result:=-0.5*pi end else begin Result:=ArcTan(Y/X); if (X < 0) then if (Y < 0) then Result:=Result-pi else Result:=Result+pi end; end;
Testing Math.arctan2... done: 0.816 sec
Testing PaoloArctan2... done: 1.062 sec
Testing JoshArctan2... done: 1.079 sec
Finished. Press ENTER to close.
The math.arctan2 function is faster by about 20% than the optimizations presented here because the math unit calls an assembler routine, at least on my system with Win11.
The best function to get the polar angle from cartesian coordinates (x, y) is the function arctan2(y, x) because it also finds the correct quadrant for the angle.
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.
Testing Math.arctan2... done: 0.818 secand for a 64-bit application on Win 11:
Testing PaoloArctan2... done: 1.057 sec
Testing JoshArctan2... done: 1.073 sec
Testing BobDogArctan2... done: 6.723 sec
Finished. Press ENTER to close.
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.
You are trying to take the square root of a negative number.
The algorithym that calculates arccos has a square root in it.
The "principal range" for arccos(y) is 0 <= y <= Pi and for arcsin(y) is -Pi/2 <= y <= Pi/2.
See: https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
Regards,
John
Then your initial post was very misleading because you don't need arccos and arcsin for this, just the ordinary cos and sin:The best function to get the polar angle from cartesian coordinates (x, y) is the function arctan2(y, x) because it also finds the correct quadrant for the angle.
I'm trying to get from the angle and magnitude to the coordinates, not the other way round.
You are trying to take the square root of a negative number.
The algorithym that calculates arccos has a square root in it.
The "principal range" for arccos(y) is 0 <= y <= Pi and for arcsin(y) is -Pi/2 <= y <= Pi/2.
See: https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
Regards,
John
John, you are correct mathematically. But, in the world of AC circuits we have both leading and lagging phase angles (from Pi/2 to -Pi/2) for the capacitive and inductive impedances respectively. That is the root of the calculations I need to do. Since there is a square root in the algorithm, I'll need to use a different approach.
Anway in my view the pascal ARCTAN2 should be updated as suggested... (maybe it'll go faster !)I don't see an essential speed gain, but the current code really looks "old-fashioned" Fortran-like. As I said: Write a bugreport, refer to this discussion and let the dev decide. The report should also contain a test program comparing the results of the methods (similar to what was shown above), also with corner cases x=y=0, x=0, y=0.
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
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
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
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
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
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
Hi wpPurely 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 11QuoteTesting Math.arctan2... done: 0.818 secand for a 64-bit application on Win 11:
Testing PaoloArctan2... done: 1.057 sec
Testing JoshArctan2... done: 1.073 sec
Testing BobDogArctan2... done: 6.723 sec
Finished. Press ENTER to close.QuoteTesting 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.
dont normally use internet on weekends.. ;)..and it is summer time.. :D, .. and arctan can wait :D
What's this? Why don't you cancel the 2? Or do you mean this, with brackets around "random - 0.5"?
procedure PrepareData; [...] SampleData[j]:=random-0.5*(2*TestMaxRange);
SampleData[j]:=(random-0.5)*(2*TestMaxRange)
Was not thinking straight, initially i was checking in small range of values to verify results across routines. then later expanded to larger values.Const MaxTanh = 5678.22249441322; // Ln(MaxExtended)/2
function tanh(x : float) : float;
var Temp : float;
begin
if x>MaxTanh then
exit(1.0)
else
if x<-MaxTanh then
exit (-1.0);
temp:=exp(-2*x);
tanh:=(1-temp)/(1+temp)
end;
for the arctan2and fixed 20 minutes later - that's the power of Open Source.
https://gitlab.com/freepascal.org/fpc/source/-/issues/39861