Buchempfehlung
Windows-Programmierung. Das Entwicklerhandbuch zur WIN32-API
Windows-Programmierung. Das Entwicklerhandbuch zur WIN32-API
"Der" Petzold, das über 1000 Seiten starke Standardwerk zum Win32-API - besonders nützlich u. a. bei der GUI-Programmierung in FreeBASIC! [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Code-Beispiel

Code-Beispiele » Mathematik

FBSinCos, eine neue FreeBASIC-Anweisung

Lizenz:Erster Autor:Letzte Bearbeitung:
k. A.Redakteurytwinky 15.02.2013

Das wunderschöne Feuerwerk2008 war der Grund, dieses Programm zu schreiben. Nicht, weil ich volta's Programm verbessern wollte(was sowieso schwer genug ist)..^^
Es geht um ein grundsätzliches Problem, was die meisten Grafik-Programme betrifft:
Die zeitaufwändige Berechnung der Funktionen Sin() und Cos(), die ja immer Double-Werte liefern.
(Das macht sich in Schleifen schon bemerkbar..)
Es wäre einfach, ein Unterprogramm(UP) zu entwickeln, das beide Funktionen berechnet und die Werte zurückgibt, doch die zeitraubende Berechnung der Funktionen bliebe dann ja erhalten..
Glücklicherweise hat der CoProzessor, der in den meisten der heutzutage eingesetzten Rechner vorhanden ist, eine eingebaute Funktion, die genau dies liefert: fsincos
Tolle Wurst, wie geht das denn?
Na, zuerst muß der Winkel(MUSS im Bogenmaß sein) an den CoProzessor übergeben werden, dann wird die Berechnung ausgeführt und fertig..
Ganz so einfach ist es zwar nicht wirklich, aber das folgende Programm zeigt, wie es geht:

'+-----------------------------------------------------------------------------------+
'|    Header: Check parameters(if any..)                                             |
'|    DisplayCheck:|Il1 are Alt-0124, Big i, small L, One „ä”öüáߎę֚Üñ±¸©ø°        |
Const Author="FBSinCos.Bas v018.3b ¸2008 by ytwinky, MD"'                            |
'|           (ShortCuts: none)                                                       |
'|    Credits: Thx @ volta 4 optimizing the ASM-part ;-))                            |
'|    Purpose: Evaluate Sin AND Cos with ONE (Asm-)Statement                         |
'+-----------------------------------------------------------------------------------+
'(For the special chars: the first is the DOS-char, then the Win-char)
Const RhoD=45.0/Atn(1.0)
Dim As Double Angle, fbSin, fbCos

Sub FBSinCos(Angle As Double, byRef fbSin As Double, byRef fbCos As Double)
'©2008 by ytwinky, optimized by volta ;-))
  Asm
    fld qword Ptr [Angle] 'Angle -> st(0)
    fsincos               'compute sin AND cos
    mov edx, [fbCos]      'Addr. of fbCos -> EDX
    fstp qword Ptr [edx]  'St(0) = cos -> fbCos
    mov edx, [fbSin]      'Addr. of fbSin -> EDX
    fstp qword Ptr [edx]  'St(0) = sin -> fbSin
  End Asm
End Sub

Print Author &!"\nCompute Sin AND Cos with ONE (ASM-)Statement"
Do
  Input "Angleø(0 --> End):", Angle
  If Angle=0 Then End
  Angle/=RhoD
  Print "Angle=";
  Print Using"####.####";Angle*RhoD
  FBSinCos(Angle, fbSin, fbCos)
  Print "FBSin=" &fbSin &!"\n  Sin=" &Sin(Angle) &!"\nFBCos=" &fbCos
  Print "  Cos=" &Cos(Angle) &!"\nTest=" &fbCos^2+fbSin^2 &"(MUST be 1)"
Loop

So, das funktioniert ja prächtig ^^
Was bringt das nun oder bringt es überhaupt etwas? Rein von der Überlegung her müßte es schneller sein, nur wie messe ich das? Da war doch noch..
Richtig, mit Counter.Bas läßt sich leicht herausfinden, wie sich der neue Befehl verhält:

#include once "windows.bi"
#include "counter.bas"

#Macro dbl_SinCos(Angle, fbSin, fbCos) 'alle als Double
Asm
  fld qword Ptr [Angle] 'Angle -> st(0)
  fsincos               'compute sin AND cos
  fstp qword Ptr [fbCos]'St(0) = cos -> fbCos
  fstp qword Ptr [fbSin]'St(0) = sin -> fbSin
End Asm
#EndMacro

Sub FBSinCos(Angle As Double, byRef fbSin As Double, byRef fbCos As Double)
'©2008 by ytwinky, optimized by volta ;-))
  Asm
    fld qword Ptr [Angle] 'Angle -> st(0)
    fsincos               'compute sin AND cos
    mov edx, [fbCos]      'Addr. of fbCos -> EDX
    fstp qword Ptr [edx]  'St(0) = cos -> fbCos
    mov edx, [fbSin]      'Addr. of fbSin -> EDX
    fstp qword Ptr [edx]  'St(0) = sin -> fbSin
  End Asm
End Sub
Const sf="######", where=19, LoopCounterValue=100

Dim As Double fbSin, fbCos, Angle=Atn(1.0)/2.0
Print "Statements";Tab(where+1);" cycles"

counter_begin(LoopCounterValue, High_PRIORITY_CLASS)
  fbSin = Sin(Angle)
Counter_end
print "Sin(Angle)";:Print Tab(where);:Print Using sf;counter_cycles

counter_begin(LoopCounterValue, High_PRIORITY_CLASS)
  fbCos = Cos(Angle)
counter_end
print "Cos(Angle)";:Print Tab(where);:Print Using sf;counter_cycles

counter_begin(LoopCounterValue, High_PRIORITY_CLASS)
  fbSin = Sin(Angle)
  fbCos = Cos(Angle)
counter_end
print !"\nSin & Cos";:Print Tab(where);:Print Using sf;counter_cycles

counter_begin(LoopCounterValue, High_PRIORITY_CLASS)
    FBSinCos(Angle, fbSin, fbCos)
counter_end
print "FBSinCos(Angle)";:Print Tab(where);:Print Using sf;counter_cycles

counter_begin(LoopCounterValue, High_PRIORITY_CLASS)
    dbl_SinCos(Angle, fbSin, fbCos)
counter_end
print "dbl_SinCos(Angle)";:Print Tab(where);:Print Using sf;counter_cycles;

GetKey

Der Unterschied ist leider nicht so groß wie ich erhofft hatte, allerdings wird hier auch nur EIN Aufruf ausgewertet. Läuft das Ganze nun in einer großen Schleife sollte ein Geschwindigkeitsgewinn spürbar werden..
So, nun aber wirklich viel Spaß beim FBSinCosen
Gruß
ytwinky


Zusätzliche Informationen und Funktionen
  • Das Code-Beispiel wurde am 01.01.2008 von Redakteurytwinky angelegt.
  • Die aktuellste Version wurde am 15.02.2013 von RedakteurVolta gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen