folgender Code ist zu simpel um unter Tipps & Tricks gepostet zu werden, und es handelt sich auch nicht direkt um ein Bug, nur indirekt um ein Feature request. Ich habe die atan2 von PureBasic mit der internen von Lua 5.4 DLL (mit PellesC kompiliert) verglichen; Lua ist "viel" schneller, meistens ca. 7-15% in den vorigen Tests. Ich habe also versucht die atan2 nachzuschreiben, wie bei wikipedia angegeben. Das Ergebnis ist ein Tick schneller als die PB interne Procedure. Aber es ist immer noch langsamer als die C atan2 funktion welche Lua intern benutzt. Ich habe das nur auf meiner alten XP Möhre getestet, 32bit. Mit PB 6 beta ist es sogar ein bißchen schneller, aber immer noch ist die pb Funktion etwas langsamer. Ich denke die PB Funktion kann optimiert werden.
Code: Alles auswählen
#HalfPi = #PI / 2
ProcedureC.d WAtan2(x.d,y.d)
If x>0
ProcedureReturn ATan(y/x)
ElseIf x<0 And y>=0
ProcedureReturn ATan(y/x) + #PI
ElseIf x<0 And y<0
ProcedureReturn ATan(y/x) - #PI
ElseIf x=0 And y>0
ProcedureReturn #HalfPi
ElseIf x=0 And y<0
ProcedureReturn -#HalfPi
EndIf
ProcedureReturn 0
EndProcedure
(siehe weiter unten, neue Ergebnisse nach Bugfix und neuem Test code)
PureBasic Test Code
Update: mit ATan() Approximation + Negativwerte werden geprüft
Code: Alles auswählen
; Faster atan2() procedures
#HalfPi = #PI / 2
ProcedureC.d atan_scalar_approximation(x.d)
; Source:
; https://mazzo.li/posts/vectorized-atan2.html
; inline float atan_scalar_approximation(float x) {
; float a1 = 0.99997726f;
; float a3 = -0.33262347f;
; float a5 = 0.19354346f;
; float a7 = -0.11643287f;
; float a9 = 0.05265332f;
; float a11 = -0.01172120f;
;
; float x_sq = x*x;
; return
; x * (a1 + x_sq * (a3 + x_sq * (a5 + x_sq * (a7 + x_sq * (a9 + x_sq * a11)))));
; }
#a1 = 0.99997726;
#a3 = -0.33262347;
#a5 = 0.19354346;
#a7 = -0.11643287;
#a9 = 0.05265332;
#a11 = -0.01172120;
Protected x_sq.d = x * x
ProcedureReturn x * (#a1 + x_sq * (#a3 + x_sq * (#a5 + x_sq * (#a7 + x_sq * (#a9 + x_sq * #a11)))));
EndProcedure
ProcedureC.d XAtan2(x.d,y.d)
If x>0
ProcedureReturn atan_scalar_approximation(y/x)
ElseIf x<0 And y>=0
ProcedureReturn atan_scalar_approximation(y/x) + #PI
ElseIf x<0 And y<0
ProcedureReturn atan_scalar_approximation(y/x) - #PI
ElseIf x=0 And y>0
ProcedureReturn #HalfPi
ElseIf x=0 And y<0
ProcedureReturn -#HalfPi
EndIf
ProcedureReturn 0
EndProcedure
ProcedureC.d WAtan2(x.d,y.d)
If x>0
ProcedureReturn ATan(y/x)
ElseIf x<0 And y>=0
ProcedureReturn ATan(y/x) + #PI
ElseIf x<0 And y<0
ProcedureReturn ATan(y/x) - #PI
ElseIf x=0 And y>0
ProcedureReturn #HalfPi
ElseIf x=0 And y<0
ProcedureReturn -#HalfPi
EndIf
ProcedureReturn 0
EndProcedure
Define pe,ps, we,ws , xe, xs
Define max = 10000000
Define.d angleresult
Delay(1)
ps = ElapsedMilliseconds()
For i=1 To max Step 1
angleresult = ATan2(Random(10000)-5000,Random(10000)-5000 )
Next
pe =ElapsedMilliseconds()
Delay(1)
ws = ElapsedMilliseconds()
For i=1 To max Step 1
angleresult = WATan2(Random(10000)-5000,Random(10000)-5000 )
Next
we = ElapsedMilliseconds()
Delay(1)
xs = ElapsedMilliseconds()
For i=1 To max Step 1
angleresult = XATan2(Random(10000)-5000,Random(10000)-5000)
Next
xe = ElapsedMilliseconds()
msg$ = "Ergebnis" +#CRLF$
msg$ + "loops: "+Str(max)+#CRLF$
msg$ + "atan2 (PB intern):"+Str(pe-ps)+"ms"+#CRLF$
msg$ + "atan2 (WAtan2):"+Str(we-ws)+"ms"+#CRLF$
msg$ + "atan2 (XAtan2, Approximation):"+Str(xe-xs)+"ms"+#CRLF$
CompilerIf #PB_Compiler_Debugger
msg$+#CRLF$+"Hey, der Debugger ist AN. Das ist Schummelei!"+#CRLF$+"Probiere es bitte ohne Debugger."+#CRLF$
CompilerEndIf
SetClipboardText(msg$)
MessageRequester("Leistungsvergleich",msg$)
Lua Skript zur Vollständigkeit (Update)
Code: Alles auswählen
require "wmath"
require "clock"
require "math"
local max = 10000000
local i
local ms,me
local ws,we
local ps,pe
local xs,xe
local tick = clock.tick
local aatan2 = math.atan2
local watan2 = wmath.atan2
local xatan2 = wmath.atan2_2
local patan2 = wmath.pbatan2
local random = wmath.random
local angleresult
ms = tick()
for i=1,max,1 do
angleresult = aatan2(random(10000)-5000,random(10000)-5000)
end
me = tick()
ws = tick()
for i=1,max,1 do
angleresult = watan2(random(10000)-5000,random(10000)-5000)
end
we = tick()
xs = tick()
for i=1,max,1 do
angleresult = xatan2(random(10000)-5000,random(10000)-5000)
end
xe = tick()
ps = tick()
for i=1,max,1 do
angleresult = patan2(random(10000)-5000,random(10000)-5000)
end
pe = tick()
print("performance","loops:",max)
print("lua math",me-ms,"ms")
print("wmath xatan2 (approximation)",we-ws,"ms")
print("wmath watan2",xe-xs,"ms")
print("wmath pb atan2",pe-ps,"ms")