Ich versuche, die Komplexität eines Algorithmus abzuschätzen, den ich für den Reko-Dekompiler geschrieben habe , wobei ich versuche, die von einem Compiler vorgenommene Umwandlung in eine ganzzahlige Division durch eine Konstante "rückgängig zu machen" . Der Compiler die Aufteilung in eine Ganzzahl umgewandelt Multiplikation und eine Verschiebung: ( x * ⌊ 2 β / n ⌋ ) > > β , wobei die Anzahl der Bits des Maschinenwort des Computers ist. Die resultierende konstante Multiplikation ist in den meisten zeitgenössischen Architekturen viel schneller als eine Division, ähnelt jedoch nicht mehr dem ursprünglichen Code.
Zur Veranschaulichung: die C-Anweisung
y = x / 10;
wird vom Microsoft Visual C ++ - Compiler in die folgende Assemblersprache kompiliert
mov edx,1999999Ah ; load 1/10 * 2^32
imul eax ; edx:eax = dividend / 10 * 2 ^32
mov eax,edx ; eax = dividend / 10
Das Nettoergebnis ist, dass das Register eax
jetzt den erwarteten Wert y
aus dem Quellcode hat.
Ein naiver Dekompiler dekompiliert das Obige zu
eax = ((long)eax * 0x1999999A) >> 32;
Reko zielt jedoch darauf ab, die resultierende Ausgabe lesbarer zu machen, indem die Konstante wiederhergestellt wird, die in der ursprünglichen Division verwendet wurde.
Der oben angedeutete Algorithmus basiert auf der Beschreibung dieses Artikels in Wikipedia . Erstens behandelt der Algorithmus den konstanten Multiplikator als den skalierten Kehrwert . Es konvertiert das in eine Gleitkommazahl und skaliert es dann um auf , wobei . Der letzte, teure Schritt besteht darin, den Gleitkommawert zwischen zwei rationalen Zahlen , (beginnend mit 0/1 und 1/1) zu klammern und den Medianten ) wiederholt zu berechnen2 & bgr; r f 2 & bgr; r f 0,0 < r f < 1,0 r f a / b c / d ( a + c ) / ( b + d ) r r f bis ein Konvergenzkriterium erreicht ist. Das Ergebnis sollte die "beste" rationale Annäherung an den Kehrwert .
Wenn nun die Belichtungsreihe mit einer typischen binären Suche durchgeführt wurde, die zwischen den Rationalen und beginnt und den Mittelpunkt berechnet , Ich erwarte, dass der Algorithmus in -Schritten konvergiert . Aber wie komplex ist der Algorithmus, wenn stattdessen der Mediant verwendet wird?2 β / 2 β ( a / b + c / d ) / 2 O ( β )