Nombres entiers

Exponentiation

L'algorithme suivant est décrit intensivement dans Knuth, volume XXX. C'est une utilisation de l'exponentiation indienne en utilisant l'écriture binaire des nombres.

Rappelons l'algorithme d'exponentiation indienne qui calcule $x^y$ :

expo(x, y):

  r = 1
  tant que y n'est pas nul :
    si y est impair:
      y = y - 1
      r = r * y    # MULTIPLY
    sinon:
      x = x * x    # SQUARE
      y = y / y    
  
  rendre r

Nous avons mis en exergue deux lignes (SQUARE et MULTIPLY, l'algorithme est connu en langue anglaise comme square and multiply algorithm). L'astuce pour encore accélérer l'algorithme est de regarder la forme binaire de y. Par exemple supposons que $y = 0b101101$ et suivons l'algorithme pas à pas :

101101  # MULTIPLY
101100  -1
101100  # SQUARE
10110   /2
10110   # SQUARE
1011    /2
1011    # MULTIPLY
1010    -1
1010    # SQUARE
101     /2
101     # MULTIPLY
100     -1
100     # SQUARE
10      /2
10      # SQUARE
1       /2
1       # MULTIPLY
0       -1
  1. Il suffit de regarder le dernier bit de y
  2. diviser par deux revient à shift 1 vers la droite
  3. le nombre de :
    • MULTIPLY est exactement égal au nombre de bits à 1 dans $y$
    • SQUARE est exactement égal au nombre de bits de $y$

Au final, si $x$ est sur $m$ bits et $y$ sur $n$ bit, $x^y$ aura $2^n\cdot m$ bits.

Algorithme d'Euclide Étendu

Soit alors la suite de division euclidienne définies telles que:

Jusqu'à trouver $b_{i} = 0$, et donc $a_i = $\text{pgcd}(a, b)$.

Comme :

On peut remonter de proche en proche jusqu'à obtenir une équation du type : $\text{pgcd}(a, b) = u\cdot a + v\cdot b$

De façon surprenante, cet enchaînement s'écrit très bien sous la forme de pseudo code si o peut assigner 6 variables en même temps :

(r, u, v, ) = (a, 1, 0, b, 0, 1)

tant que r2 != 0:
  q = r % r2 
  (r, u, v, r2, u2, v2) = (r2, u2, v2, r - q*r2, u - q*u2, v - q*v2)

return (r, u, v) 

Les deux égalités suivantes sont les invariants de boucle de la ligne 3 :

Racine carrée entière

Dichotomie

Avec de la dichotomie :

def racine(N):
  g = 1
  d = N

  m = (g + d) / 2
  tant que m * m != N:
    si m * m > N:
      d = m - 1
    sinon:
      l = m + 1

Le temps pris sera de l'ordre de $\mathcal{O}(\log_2(N))$ boucles tant que, avec une multiplication par boucle. La complexité totale sera donc de l'ordre de $\mathcal{O}(n^3)$ où $n4 est la taille de $N$ en bits.

Bit à bit

1100011100011
      1000000  plus grande puissance de 2 dont le carré est < à N
      1x00000  x vaut 1 si 1100000 au carré <= N, vaut 0 sinon
      10x0000  x vaut 1 si 1010000 au carré <= N, vaut 0 sinon
      100x000  x vaut 1 si 1001000 au carré <= N, vaut 0 sinon
      1001x00  x vaut 1 si 1001100 au carré <= N, vaut 0 sinon
      10011x0  x vaut 1 si 1001110 au carré <= N, vaut 0 sinon
      100111x  x vaut 1 si 1001111 au carré <= N, vaut 0 sinon
      1001111  

On est pas obligé d'élever au carré à chaque fois, on peut s'en sortir juste avec des shift et des additions en stockant judicieusement des variables intermédiaires, voir wikipedia. On arrive à une formulation en $\mathcal{O}(n^2)$

TBD expliciter les variables

Factorisation

TBD : problème : sachant $n$, trouver $p$ et $q$ $n=pq$.

Pas d'algorithmes connu pour faire rapidement le calcul.

TBD :

Factorisation de Fermat

Marche bien si $p$ est proche de $q$

Donc pour RSA, il faut bien choisir deux nombres premiers indépendamment. Si vous vous contentez de prendre 1 nombre aléatoire puis de chercher le premier nombre premier au-dessus et en-dessous, la factorisation de Fermat va trouver très rapidement la solution.

Génération de nombres premiers

TBD :