Logarithmus Instruktion neben FYL2X
-
Hallo,
ich berechne in einer Funktion den Logarithmus mit beliebiger Basis wie folgt:
global _log ; _log( ; _in_ long double base, ; _in_ long double num ; ); _log: push ebp ; save old frame pointer mov ebp, esp ; new frame pointer add esp, -8 ; allocate local variables fld1 ; st0 = 1.0 fld base ; st0 = base | st1 = 1.0 fyl2x ; st1 = result fstp QWORD PTR [esp] ; [esp] = result fld1 ; st0 = 1.0 fld num ; st0 = num | st1 = 1.0 fyl2x ; st1 = result fdiv QWORD PTR [esp] ; st1 = result mov esp, ebp pop ebp ret
Beispielhafter Aufruf:
BASE DQ 04024000000000000r ; 10.0 NUM DQ 0408f400000000000r ; 1000.0 RESULT DQ ? sub esp, 8 fld QWORD PTR [NUM] fstp QWORD PTR [esp] sub esp, 8 fld QWORD PTR [BASE] fstp QWORD PTR [esp] call _log add esp, 16 fstp QWORD PTR [RESULT]
So, meine Frage ist jetzt, ob jemand von euch eine Instruktion kennt, die lediglich log2(x) durchführt und nicht y * log2(x) wie fyl2x. Ehrlich gesagt verbirgt sich mir gerade auch der Sinn des Ganzen.
-
Ich glaube, sowas kann die FPU nicht. KA, ob evtl. irgendeine der tausend Befehlserweiterungen entsprechende Befehle bietet.
Ansonsten ist dieser Befehl so IMHO aber auch recht praktisch. Dass du das Produkt von einem Logarithmus mit irgendwas ausrechnen willst, kommt in der Praxis gar nicht mal so selten vor. Das klappt natuerlich nicht so gut, wenn du mit solchen Funktionen versuchst Funktionen zu kapseln, fuer die die fpu nicht unbedingt optimiert ist. Insofern hast du dort ein schoenes Beispiel, wie man moeglichst nicht Assembler programmieren sollte...Nur um ein Anwendungsbeispiel zu geben: Du haettest auch zuerst 1/ld(base) berechnen und das so mit dem ld(num) multiplizieren koennen. Und um die Sache noch besser zu nutzen, koenntest du auch gleich noch einen Faktor zum Ranmultiplizieren an die Funktion uebergeben.
-
y*log2(x) wird z.B. zur Berechnung von x^y benötigt.
-
Nobuo T schrieb:
Insofern hast du dort ein schoenes Beispiel, wie man moeglichst nicht Assembler programmieren sollte...
Wie würdest du es denn machen? Das was du weiter unten beschreibst ist ja nicht so viel anders.
-
Oben steht bereits ein Vorschlag, wie du die Funktion modifizieren kannst, um zumindest jeweils die Multiplikationen mitbenutzen zu koennen. Das koennte IMHO schon durchaus etwas bringen.
Ansonsten gilt fuer solche Optimierungen kleiner Funktionen ganz allgemein zB.: Schau, ob du die Funktion inline machen oder zumindest die Parameter ueber den fpu-Stack uebergeben kannst und ob du diese log-Funktion in der Form wirklich brauchst oder ob du das Problem evtl. auch irgendwie anders oder eleganter in Hinblick auf die fpu-Architektur loesen kannst. Da ist eben etwas Kreativitaet gefragt.
-
Kurze Zwischenfrage:
Wenn ld(x^y) = y * ld(x) ist, dann muss x^y = 2^(y * ld(x)) sein oder nicht? Will mir nicht so ganz gelingen:
fld exp // st0 = exp fld base // st0 = base | st1 = exp fyl2x // st1 = result fxch // st0 <=> st1 f2xm1
-
deine Annahme ist richtig, hier eine Realisierung für x >= 0 und beliebiges y:
(die fpu kann nur mit Integers 2^x bilden - fscale richtet das);st(0) = st(1)^st(0) = 2^(st(0)*ld(st(1))) fyl2x fld st(0) frndint fsub st(1),st(0) fxch f2xm1 fadd const_r4_one ; alternativ fld1,faddp fscale
-
ach, bevor ichs noch vergesse, diese Seite hier ist zu diesem Thema wohl auch
recht lesenswert: