schon mehrfach ist die Frage nach Winkelfunktionen unter LUA aufgetaucht. Zufällig habe ich den Artikel bei Wikipedia zum CORDIC-Algorithmus und die hier beschriebene C++ Umsetzung (Absatz: Programm: Festkomma Bibliothek) gelesen. Das Verfahren ist für Integerrechnung und Schiebeoperationen entwickelt worden.
Um einen Eindrück von der Leistungsfähigkeit zu bekommen, ist dabei eine LUA-Bibliothek entstanden.
Größtes Problem in LUA unter CHDK ist die Zahlendarstelleung ohne Nachkommateil und der Wertebereich von -2^31 .. 2^31-1. Alle Berechnungen mit der Bibliothek cordicLib.lua erfolgen mit um 10^3 erweiterten Werten, welche damit drei Nachkommastellen repräsentieren. Intern arbeitet die Bibliothek mit vier Nachkommastellen. Weiterhin wurde die übliche Winkelangabe im Bogenmaß durch das Gradmaß ersetzt, was die Berechnung um mehr als eine Nachkommastelle verbessert. Der Genauigkeit wirken die üblichen Probleme mit der Umrechnung zwischen Dezimal- und Dualsystem entgegen.
Einen Eindruck vermittelt das Testproramm cordic.lua. Es werden alle implementirten Winkelfunktionen benutzt. Zusätzlich wurde die Funktion Int2Str() neu geschrieben.
Ausgabe cordic.lua:
- Code: Alles auswählen
CORDIC LIBRARY Version 0.3
Konstanten:
Multiplikator = 1000
2*PI = 6.283
PI = 3.141
PI/2 = 1.570
Funktionen:
DEG(30) -> RAD(0.523)
RAD(0.523) -> DEG(29.980)
4/3 = 1.333
Winkelfunktionen im Bogenmaß (RAD):
SINR(0.523) = 0.499
COSR(0.523) = 0.866
TANR(0.523) = 0.576
ASINR(0.499) = 0.522
ACOSR(0.866) = 0.523
ATANR(0.576) = 0.522
RECR(4.000, 3.000) = POLR(5.000, 0.643)
POLR(5.000, 0.643) = RECR(4.001, 2.997)
Winkelfunktionen in Grad (DEG):
SIND(30) = 0.500
COSD(30) = 0.866
TAND(30) = 0.577
ASIND(0.500) = 29.992
ACOSD(0.866) = 30.006
ATAND(0.577) = 29.992
RECD(4.000, 3.000) = POLD(5.000, 36.865)
POLD(5.000, 36.865) = RECD(4.000, 2.999)
Zu tun bleibt die Ermittlung der Arbeitsbereiche der Winkelfunktionen und die daraus resultierende Konvertierung der Werte in die richtigen Quadranten.
Arbeitsbereiche:
- Code: Alles auswählen
sind(ALL) = -0.999..+0.999
cosd(ALL) = -0.999..+0.999
tand(ALL) = -3332.666..3332.666 (90°/270° = -3332.666)
asind(-0.986..+0.986) = -90°..+90°
acosd(-0.986..+0.986) = 0°..+180°
atand(-214747..+214747) = -90°..+90°
recd(0..21, ALL) = pold(-21..+21, -21..+21)
pold(-10..+10, -10..+10) = recd(0..14.14, 0°..360°)
[EDIT 28.11.2012]
Version 0.3:
- Den Winkelfunktionen für Winkel in Grad wir ein "d" (für deg) angehangen, wie tand().
- Winkelfunktionen im Bogenmaß (rad) hinzugefügt. Bsp. tanr()
- Umrechnungsfunktionen fur deg <-> rad hinzugefügt.
- Vorbeugung für Überlauf überarbeitet und als Funktion integer_mul_div () = a * b / c zugänglich gemacht.
- Konstanten für 2*PI, PI und PI/2 hinterlegt.
[EDIT 30.11.2012]
Version 0.4:
- Bugfix in Funktion integer_mul_div().
- Funktion integer_mul_div() um gemischte Brüche erweitert.
[EDIT 02.12.2012]
Version 0.5:
- Bugfix in Funktion integer_mul_div()-Abschnitt gmischte Brüche.
- Laufzeiten optimiert in der Funktion integer_mul_div().
Gruß rudi