ATN (ROM-Routine)
Anmerkung: Dieser Artikel beschreibt die numerische ATN-Routine im BASIC-ROM.
Name: | ATN | ||||||
Beschreibung: | Arkustangens des Fließkommaregisters FAC berechnen | ||||||
Einsprungpunkt: | $E30E / 58126 | ||||||
Übergebene Argumente: | |||||||
Rückgabe-Werte: |
Die ROM-Routine ATN[1][2] — manchmal auch als ARCTAN[3] bezeichnet — berechnet den Arkustangens der im Fließkommaregister FAC gespeicherten Zahl. Ihr Einsprungpunkt ist in der Tabelle der BASIC-Funktionen an Adresse $A06C hinterlegt, so dass die Routine bei jeder Auswertung der Funktion ATN vom BASIC-Interpreter aufgerufen wird. Das Resultat wird im Bogenmaß berechnet.
Nach dem Aufruf steht in FAC der Wert der Arkusfunktion, während der Inhalt von ARG undefiniert ist. Neben dem Inhalt der Fließkommaregister FAC und ARG ändert ATN auch den Zähler an Adresse 103/$67, die Hilfszeiger an den Adressen 34/$22 (Low-Byte) und 35/$23 (High-Byte) sowie 113/$71 (Low-Byte) und 114/$72 (High-Byte) und die Fließkommaregister FAC#3 und FAC#4 an den Adressen 87/$57 bis 96/$60.
Algorithmus[Bearbeiten | Quelltext bearbeiten]
Die Routine ATN führt nacheinander die folgenden Schritte aus:
- Ist der Wert in FAC negativ, so wird das Vorzeichen umgekehrt, das ursprüngliche Vorzeichen jedoch in jedem Fall zur späteren Verarbeitung auf den Stack gerettet.
- Ist der resultierende Wert von FAC größer oder gleich 1, so wird er durch seinen Kehrwert ersetzt; im folgenden wird also der zunächst der Arkuskotangens berechnet. Auch der ursprüngliche Exponent wird aber immer auf den Stack gerettet.
In allen Fällen liegt FAC nun zwischen 0 und 1. - FAC wird nun in das folgende Polynom[4] 23. Grades eingesetzt, das im Intervall [0; 1[ die Funktion f(x) = atn(x) approximiert. Die zugehörigen Koeffizienten finden sich im ROM an Adresse $E33E / 58158. Zur Berechnung des Funktionswerts wird die ROM-Routine POLYX aufgerufen:
p(x) = - 0.0006847939119 x23 + 0.004850942156 x21 - 0.01611170184 x19 + 0.03420963804 x17 - 0.05427913276 x15 + 0.07245719654 x13 - 0.089802395 x11 + 0.1109324134 x9 - 0.1428398077 x7 + 0.1999991205 x5 - 0.3333333157 x3 + x
- Falls anhand des im zweiten Schritt zwischengespeicherte Exponenten erkennbar ist, dass der an ATN übergebene Parameter größer oder gleich 1 war und somit statt des Arcustangens der Arkuskotangens berechnet wurde, so wird hieraus nun der Wert des entsprechenden Arkustangens ermittelt, indem der Wert p(x) in FAC ersetzt wird durch π/2 - p(x).
- Zuletzt wird das im ersten Schritt gesicherte Vorzeichen des ursprünglichen Parameters geprüft. War der Parameter negativ, so wird nun noch der Wert in FAC negiert, da die Arkustangens-Funktion punktsymmtrisch zum Koordinatenursprung ist.
Die folgenden beiden Schaubilder zeigen den Graphen dieses Polynoms (violett). In beiden Bildern ist das Intervall, das von der ATN-Routine genutzt wird, hellrot eingefärbt. Im rechten Bild ist zudem der Verlauf der Arkustangens-Funktion (grün) zum Vergleich eingezeichnet.
Die nächsten beiden Bilder veranschaulichen noch die Qualität der Approximation. Das linke Bild zeigt im Intervall [-2, 2] die Abweichung zwischen dem Approximationspolynom und dem exakten Arkustangens (violett), multipliziert mit 1010. Diese Werte wurden als doppelt genaue Fließkommazahlen (52 Bit-Mantisse) berechnet. Der maximale Betrag der so ermittelten Abweichung zwischen p(x) und atn(x) liegt im betrachteten Intervall bei 1.24E-10. Zum Vergleich ist die Arkustangens-Funktion (grün) in das Schaubild eingezeichnet.
Das rechte Bild zeigt die Abweichung zwischen dem von der ATN-Routine gelieferten Wert und dem exakten Arkustangens (violett, wieder berechnet als Fließkommazahl mit doppelter Genauigkeit). Zur besseren Orientierung ist auch der Verlauf der Arkustangens-Funktion eingezeichnet (grün, in y-Richtung gestreckt um den Faktor 20). Für die Erstellung des Schaubilds wurden die Werte nicht etwa mit PRINT ausgegeben, sondern es wurde der binäre Inhalt von FAC vor und nach dem Aufruf der ATN-Routine ausgelesen. Auf diese Weise gehen keine Ungenauigkeiten oder eventuelle Fehler aus der Umwandlung von der Fließkommadarstellung nach ASCII in die Analyse ein. Zudem wurden als Argumente von ATN nur die ganzzahligen Vielfachen von 2-15 im Intervall ]-2; 2[ verwendet, um exakt äquidistante Eingabewerte betrachten zu können. Das Schaubild zeigt, dass die Abweichung zwischen Approximationspolynom und exaktem Arkustangens (von durchschnittlich 0.36E-10, maximal 1.24E-10) im Intervall ]-1; 1[ in einer ähnlichen Größenordnung liegt wie die Abweichung zwischen dem Resultat der ATN-Routine und dem Arkustangens (durchschnittlich 0.48E-10, maximal 2.39E-10). In den Intervallen [-2; -1] bzw. [1; 2], in denen das Polynom auf den Kehrwert des ursprünglichen Parameters angewendet wird, machen sich dagegen Differenzen zwischen den Resultaten von ATN-Routine und dem Arkustangens (von durchschnittlich 0.91E-10, maximal 4.45E-10, mit einzelnen Ausreißern von bis zu 115.33E-10 aufgrund eines Fehlers in der Multiplikationsroutine) deutlich bemerkbar.
Laufzeitverhalten[Bearbeiten | Quelltext bearbeiten]
ATN wertet in jedem Fall das in Schritt 3 des Algorithmus angegebene Polynom aus. Da die in POLYX genutzten ROM-Routinen FADD und FMULT allerdings auf einen Summanden bzw. einen Faktor von 0 prüfen und in diesem Fall keine Addition bzw. Multiplikation durchführen, benötigt der Aufruf von ATN(0) nur 4251 Systemtakte. In allen anderen Fällen ist aufgrund der großen Zahl von Rechenoperationen ein funktionaler Zusammenhang zwischen dem in FAC übergebenen Wert und der Laufzeit von ATN nicht erkennbar. Im Rahmen ausgiebiger Messreihen lag die Laufzeit von ATN zwischen 34847 und 43439 Systemtakten.
Ein Systemtakt entspricht auf dem Commodore 64 rund einer Mikrosekunde (μs). Im ungünstigsten Fall benötigt die ATN-Routine also etwas mehr als 43 Millisekunden (ms).
Bugs[Bearbeiten | Quelltext bearbeiten]
- Wie aus dem obigen Schaubild mit den Abweichungen zwischen dem Ergebnis von ATN und dem exakten Arkustangens ersichtlich, zeigen sich die Auswirkungen eines Fehlers in FMULT auch in den Ergebnissen der hierauf aufbauenden ROM-Routine ATN: Bei insgesamt 4 von 131072 Berechnungen der Analyse verursachte dieser Fehler eine Abweichung von mehr als 10E-10, im Extremfall — bei der Berechnung von ATN(56522 / 32768) — sogar von 115.33E-10.
Weblinks[Bearbeiten | Quelltext bearbeiten]
- Disassembly von ATN/$E30E auf All About Your 64
- CodeBase 64: Floating Point Math
- C64 BASIC & KERNAL ROM Disassembly von Michael Steil
- C64OS: Floating Point Math from BASIC
Quellen[Bearbeiten | Quelltext bearbeiten]
- ↑ Florian Müller: C64 für Insider, S. 470
- ↑ Said Baloui/Rolf Brückmann/Lothar Englisch/Jacques Felt/Ralf Gelfand/Klaus Gerits/Darko Krsnik: Das neue Commodore 64 Intern Buch, S. 627
- ↑ Winfried Kassera/Frank Kassera: C64 Programmieren in Maschinensprache, S. 300
- ↑ John Fraser Hart et al.: Computer Approximations, John Wiley & Sons, Inc. 1968, S. 269 (Polynom 4995)