Greg Hewgill et IllidanS4 ont donné un lien avec une excellente explication mathématique. Je vais essayer de résumer ici pour ceux qui ne veulent pas trop entrer dans les détails.
Toute fonction mathématique, à quelques exceptions près, peut être représentée par une somme polynomiale:
y = f(x)
peut être exactement transformé en:
y = a0 + a1*x + a2*(x^2) + a3*(x^3) + a4*(x^4) + ...
Où a0, a1, a2, ... sont des constantes . Le problème est que pour de nombreuses fonctions, comme la racine carrée, pour une valeur exacte cette somme a un nombre infini de membres, elle ne se termine pas à un certain x ^ n . Mais, si nous nous arrêtons à un x ^ n, nous aurions toujours un résultat avec une certaine précision.
Donc, si nous avons:
y = 1/sqrt(x)
Dans ce cas particulier, ils ont décidé de rejeter tous les membres polynomiaux au-dessus de la seconde, probablement à cause de la vitesse de calcul:
y = a0 + a1*x + [...discarded...]
Et la tâche consiste maintenant à calculer a0 et a1 afin que y ait le moins de différence avec la valeur exacte. Ils ont calculé que les valeurs les plus appropriées sont:
a0 = 0x5f375a86
a1 = -0.5
Donc, lorsque vous mettez cela dans l'équation, vous obtenez:
y = 0x5f375a86 - 0.5*x
Qui est la même que la ligne que vous voyez dans le code:
i = 0x5f375a86 - (i >> 1);
Edit: en fait, ce y = 0x5f375a86 - 0.5*x
n'est pas la même chose que i = 0x5f375a86 - (i >> 1);
puisque le décalage de float comme entier non seulement divise par deux, mais divise également l'exposant par deux et provoque d'autres artefacts, mais cela revient toujours à calculer certains coefficients a0, a1, a2 ....
À ce stade, ils ont découvert que la précision de ce résultat n'est pas suffisante à cet effet. Ainsi, ils n'ont en outre fait qu'une seule étape de l'itération de Newton pour améliorer la précision du résultat:
x = x * (1.5f - xhalf * x * x)
Ils auraient pu faire d'autres itérations en boucle, chacune améliorant le résultat, jusqu'à ce que la précision requise soit atteinte. C'est exactement comme cela que cela fonctionne dans CPU / FPU! Mais il semble qu'une seule itération ait suffi, ce qui était également une bénédiction pour la vitesse. CPU / FPU fait autant d'itérations que nécessaire pour atteindre la précision du nombre à virgule flottante dans lequel le résultat est stocké et il a un algorithme plus général qui fonctionne dans tous les cas.
Donc, en bref, ce qu'ils ont fait est:
Utilisez (presque) le même algorithme que CPU / FPU, exploitez l'amélioration des conditions initiales pour le cas particulier de 1 / sqrt (x) et ne calculez pas jusqu'à la précision CPU / FPU ira mais arrêtez plus tôt, donc gagner en vitesse de calcul.