Utilisateur:Spitfire06/Brouillon

Une page de Wikipédia, l'encyclopédie libre.

Page Racine carrée inverse rapide en cours de trad

Fonctionnement de l'algorithme[modifier | modifier le code]

L'algorithme calcule 1/x en effectuant les étapes suivantes :

  1. Transforme l'argument x en entier afin d'appliquer une approximation de log2(x)
  2. Utilise cet entier pour calculer une approximation de log2(1/x)
  3. Transforme celui-ci afin de revenir à un nombre flottant afin d'effectuer une approximation de l'exponentielle base-2
  4. Affine l'approximation en utilisant une itération de la méthode de Newton.

Représentation en nombre flottant[modifier | modifier le code]

Puisque cet algorithme se base fortement sur la représentation bit à bit des nombres à virgule flottante de simple-précision, un aperçu rapide de ce système est fourni ici. Afin d'encoder un nombre réel non nul x en tant que flottant de simple-précision, on commence par écrire x comme un nombre binaire en notation scientifique :

Où l'exposant ex est un entier, mx ∈ [0, 1), et 1.b1b2b3... est la représentation binaire de la "mantisse" (1 + mx). Notons qu'il n'est pas nécessaire d'enregistrer le bit avant le point dans la mantisse car il vaut toujours 1. Avec ce formalisme, on calcule 3 entiers :

  • Sx, le "bit de signe", valant 0 si x > 0 ou 1 si x < 0 (1 bit)
  • Ex = ex + B est "l'exposant biaisé" où B = 127 est le "biais d'exposant" (en)[1] (8 bits)
  • Mx = mx × L, où L = 223 [2] (23 bits)

Ces valeurs sont ensuite condensées de gauche à droite dans un conteneur 32 bit.

Par exemple, en utilisant le nombre x = 0.15625 = 0.001012. En normalisant x on a :

Donc, les trois valeurs entières non signées sont :

  • S = 0
  • E = −3 + 127 = 124 = 011111002
  • M = 0.25 × 223 = 2097152 = 010000000000000000000002

Ces champs sont condensés comme ceci :

Approcher un logarithme en passant à l'entier[modifier | modifier le code]

S'il fallait calculer 1/x sans un ordinateur ou une calculatrice, une table de logarithmes serait utile accompagnée de l'identité logb(1/x) = −½ logb(x) valide quelle que soit la base b. La racine carrée inverse rapide repose sur cette dernière ainsi que sur le fait que l'on puisse effectuer un logarithme approximatif d'un nombre en passant d'un float32 à un entier. Explications :

Soit x un nombre normal positif :

On a alors

Mais puisque mx ∈ [0, 1), le logarithme de la partie droite peut être arrondi par[3]

σ est un paramètre arbitraire permettant de régler l'arrondi. Par exemple : σ = 0 fournit des résultats exacts aux bords de l'intervalle tandis que σ ≈ 0.0430357 fournit l'approximation optimale.

L'entier converti en nombre flottant (en bleu), comparé à un logarithme décalé et à l'échelle (en gris).

Alors nous avons l'approximation

D'un autre côté, en interprétant la réprésentation binaire de x en tant qu'entier, on obtient :[4]

On remarque alors que Ix est un approximation linéaire mise à l'échelle et décalée de log2(x), comme présenté sur le graphique ci-contre. En d'autres termes, log2(x) est approché par

Première approximation du résultat[modifier | modifier le code]

Le calcul de y = 1/x est basé sur l'identité

En utilisant l'approximation du logarithme telle que précédemment définie et appliquée à x et y, l'équation devient :

Qui s'écrit en code C :

i  = 0x5f3759df - ( i >> 1 );

Le premier terme étant le nombre magique

à partir duquel on déduit σ ≈ 0.0450466. Le second terme, ½ Ix est déterminé en décalant à droite une fois les bits de Ix.[5]

Méthode de Newton[modifier | modifier le code]

Après avoir appliqué ces opérations, l'algorithme considère de nouveau le mot double comme nombre flottant (y = *(float*)&i;) et effectue une multiplication en nombre flottant (y = y*(1.5f - xhalf*y*y);). Celle-ci étant une itération de la méthode de Newton permettant de trouver des solutions à une équation donnée. Pour ce même exemple :

est la racine carrée inverse, ou encore, en fonction de y :
.
Avec représentant l'expression générale de la méthode de Newton avec comme première approximation,
est l'expression particulière où et .
Ainsi y = y*(1.5f - xhalf*y*y); est semblable à

La première approximation est générée en utilisant les opérations en tant qu'entiers puis fournie aux deux dernières lignes de code de la fonction. Des itérations répétées de cet algorithme en utilisant la sortie de la fonction () comme argument pour l'itération suivante fait converger l'algorithme sur la racine avec une incertitude de plus en plus faible.[6] Une seule itération a été utilisée dans le cadre du moteur de Quake III, une seconde itération ayant été commentée et laissée.

  1. Ex doit être dans le domaine [1, 254] afin que x soit représentable comme un nombre normal (en)
  2. Les seuls réels pouvant être représentés exactement comme des nombres à virgule flottante sont ceux pour lesquels Mx est un entier. Les autres nombres ne peuvent être représentés que de façon approchée en les arrondissant au nombre représentable le plus proche.
  3. (en) Charles McEniry, « The Mathematics Behind the Fast Inverse Square Root Function Code », sur daxia.com, (consulté le ), p. 3
  4. Sx = 0 puisque x > 0.
  5. Hennessey & Patterson 1998, p. 305.
  6. (en) Charles McEniry, « The Mathematics Behind the Fast Inverse Square Root Function Code », sur daxia.com, (consulté le ), p. 6