J'essaie d'estimer la complexité d'un algorithme que j'ai écrit pour le décompilateur Reko , où j'essaie de "défaire" la transformation effectuée par un compilateur en une division entière par une constante. Le compilateur a converti la division en une multiplication entière et un décalage:, où est le nombre de bits du mot machine de l'ordinateur. La multiplication constante qui en résulte est beaucoup plus rapide qu'une division dans la plupart des architectures contemporaines, mais ne ressemble plus au code d'origine.
Pour illustrer: l'instruction C
y = x / 10;
sera compilé par le compilateur Microsoft Visual C ++ dans le langage d'assemblage suivant
mov edx,1999999Ah ; load 1/10 * 2^32
imul eax ; edx:eax = dividend / 10 * 2 ^32
mov eax,edx ; eax = dividend / 10
Le résultat net est que le registre eax
aura désormais la valeur attendue du y
code source.
Un décompilateur naïf décompilera ce qui précède pour
eax = ((long)eax * 0x1999999A) >> 32;
mais Reko vise à rendre la sortie résultante plus lisible que celle en récupérant la constante qui était utilisée dans la division d'origine.
L'algorithme évoqué ci-dessus est basé sur la description de cet article dans Wikipedia . Tout d'abord, l'algorithme traite le multiplicateur constant comme la réciproque mise à l'échelle. Il convertit cela en un nombre à virgule flottante puis le réduit à , où . La dernière étape coûteuse consiste à mettre entre crochets la valeur en virgule flottante entre deux nombres rationnels , (en commençant par 0/1 et 1/1) et calculer à plusieurs reprises le médiant jusqu'à ce qu'un certain critère de convergence soit atteint. Le résultat devrait être la "meilleure" approximation rationnelle à l'inverse .
Maintenant, si le bracketing était fait avec une recherche binaire typique commençant entre les rationnels et et calculer le point médian , Je m'attends à ce que l'algorithme converge pas. Mais quelle est la complexité de l'algorithme si le médiant est utilisé à la place?