Algorithme de Cipolla

algorithme de calcul de racines carrées modulaires

En théorie algorithmique des nombres, l'algorithme de Cipolla est une méthode pour résoudre une congruence de la forme

x2≡n(modp),

où p est un nombre premier, n est un entier donné et x est un entier inconnu. Une fois fixé p, il revient de résoudre l'équation x2=n dans le corps fini 𝐅p à p éléments, c'est-à-dire de trouver une racine carrée de n dans ce corps. L'algorithme porte le nom de Michele Cipolla, le mathématicien italien qui l'a inventé en 1903[1] avant de l'étendre aux équations de degré quelconque xn≡a(modp) en 1907[2].

Outre les modules premiers, l'algorithme de Cipolla permet également de calculer les racines carrées modulo les puissances d'un nombre premier[3].

L'algorithme

modifier

Entrées :

  • p, un nombre premier impair,
  • n∈𝐅p, un carré modulo p.

Sortie :

  • x∈𝐅p tel que x2=n.

Déroulement :

  • Étape 1 : on trouve un élément a∈𝐅p tel que a2−n n'est pas un carré.
On ne connaît pas d'algorithme déterministe pour trouver un tel élément a mais on peut utiliser la méthode essai-erreur suivante : on choisit un a au hasard et on calcule le symbole de Legendre (a2−np) pour déterminer si a convient.
La probabilité qu'un élément aléatoire a satisfasse à la condition est (p−1)/(2p). Pour p suffisamment grand, elle est proche de 1/2[4]. On s'attend donc à faire environ deux essais avant de trouver une valeur convenable pour a.
  • Étape 2 : on calcule
x0=(a+a2−n)(p+1)/2
dans l'extension de corps 𝐅p2=𝐅p(a2−n). Cet élément est solution de l'équation x2=n.

NB : Si x02=n, alors (−x0)2=n également. Comme p est impair, x0≠−x0, si bien que dès que l'on a une solution x0, on en obtient une seconde, −x0.

Exemple

modifier

On fixe p=13. Les éléments qui apparaissent dans la première étape sont des éléments de 𝐅13, ceux qui interviennent dans la deuxième étape sont des éléments de 𝐅132.

On chercher les x tels que x2=10.

Avant d'appliquer l'algorithme, il est préférable de vérifier que 10 est bien un carré dans 𝐅13, c'est-à-dire que le symbole de Legendre (10|13) est égal à 1. Pour cela, on peut utiliser le critère d'Euler : (10|13)≡106≡1(mod13) (par exemple parce que 106−1=(103−1)(103+1) et que 103+1=1001=7⋅11⋅13). Ainsi, 10 est un bien un carré modulo 13.

  • Étape 1 : Trouver un a tel que a2−n n'est pas un carré. Comme indiqué, procède par tâtonnement. On part de a=2, de sorte que a2−n=7. On calcule le symbole de Legendre (7|13) à l'aide du critère d'Euler : 76=3432≡52≡25≡−1(mod13). Ainsi, le choix de a=2 convient.
  • Étape 2 : Calculer x=(a+a2−n)(p+1)/2=(2+−6)7 dans 𝐅13(−6) :
(2+−6)2=4+4−6−6=−2+4−6
(2+−6)4=(−2+4−6)2=−1−3−6
(2+−6)6=(−2+4−6)(−1−3−6)=9+2−6
(2+−6)7=(9+2−6)(2+−6)=6.

Ainsi, x=6 est une solution, de même que −x=−6 . De fait, on a bien 62≡10(mod13).

Démonstration

modifier

Préliminaires : un corps de cardinal p2

modifier

La première partie de la preuve consiste à définir un corps 𝐅p2=𝐅p(a2−n)={x+ya2−n:x,y∈𝐅p}. Pour simplifier, on note ω=a2−n. Comme a2−n n'est pas un résidu quadratique, il n'a pas de racine carrée dans 𝐅p. L'élément ω peut donc être considéré comme un analogue du nombre complexe i. Les opérations sont faciles à définir. Pour x1,x2,y1,y2∈𝐅p, leur somme est définie comme

(x1+y1ω)+(x2+y2ω)=(x1+x2)+(y1+y2)ω

et leur produit se détermine en se rappelant que ω2=a2−n, ce qui donne :

(x1+y1ω)(x2+y2ω)=x1x2+x1y2ω+y1x2ω+y1y2ω2=(x1x2+y1y2(a2−n))+(x1y2+y1x2)ω.

Il faut maintenant vérifier les propriétés du corps. L'addition et la multiplication étant bien définies, on vérifie qu'elles sont associatives, commutatives et que le produit est distributif sur la somme. C'est d'autant plus facile si l'on voit le corps 𝐅p2 comme un analogue fini du corps des nombres complexes (ω étant l'analogue de i).

Le neutre de la somme est 0, ou plus formellement 0+0ω. Pour α=x+yω∈𝐅p2,

α+0=(x+yω)+(0+0ω)=(x+0)+(y+0)ω=x+yω=α.

Le neutre du produit est 1, ou plus formellement 1+0ω :

α⋅1=(x+yω)(1+0ω)=(x⋅1+0⋅y(a2−n))+(x⋅0+1⋅y)ω=x+yω=α.

Il n'y a plus qu'à trouver des opposés et des inverses pour les éléments non nuls. On vérifie sans peine que l'opposé de x+yω est −x−yω. On cherche un inverse de α=x1+y1ω sous la forme α−1=x+yω. La condition αα−1=1 s'écrit

(x1+y1ω)(x+yω)=(x1x+y1y(a2−n))+(x1y+y1x)ω=1,

ce qui équivaut un système de deux équations : x1x+y1(a2−n)y=1 et y1x+x1y=0. Le déterminant de ce système est x12−y12(a2−n). Supposons qu'il s'annule : si y1≠0, alors a2−n=(x1/y1)2, ce qui est absurde ; ainsi, y1=0, puis x1=0, ce qui est contraire aux hypothèses. Cela entraîne que le système a une unique solution, et donc qu'il y a un inverse unique, déterminé par

x=x1x12−y12(a2−n),
y=−y1x12−y12(a2−n).

Préliminaires (suite) : une « conjugaison »

modifier

Maintenant que l'on dispose d'une extension 𝐅p2 de degré deux de 𝐅p, on introduit un analogue de la conjugaison complexe. Il est clair que l'application F qui à α∈𝐅p associe αp envoie 0 sur 0, 1 sur 1 et le produit de deux éléments α et β sur le produit de leurs images : (αβ)p=αpβp. De plus, on sait que pour p premier et k compris entre 1 et p−1, le coefficient binomial (pk) est un multiple de p : cela entraîne que (α+β)p=αp+βp. Autrement dit, F est un morphisme de corps. Il est automatiquement injectif et, comme 𝐅p2 est fini, il est également surjectif.

De plus, pour tout élément x+yω∈𝐅p2, on a

(x+yω)p=x−yω.

En effet, comme ω2=a2−n n'est pas un carré dans 𝐅p, on a par le critère d'Euler ωp−1=(ω2)(p−1)/2=−1. Ainsi ωp=−ω, ce qui avec le petit théorème de Fermat (qui stipule que xp=x pour tout x∈𝐅p) donne la relation voulue : (x+yω)p=xp+ypωp=x−yω.

Le morphisme F est appelé automorphisme de Frobenius de 𝐅p2.

Validité de l'algorithme de Cipolla

modifier

Enfin, on montre que si x0=(a+ω)(p+1)/2∈𝐅p2, alors x02=n∈𝐅p. On calcule, à l'aide de ce qui précède :

x02=(a+ω)p+1=(a+ω)(a+ω)p=(a+ω)(a−ω)=a2−ω2=a2−(a2−n)=n.

A priori, on sait seulement que x0∈𝐅p2. Cependant, puisque sur un corps, un polynôme non nul de degré n possède au plus n racines dans tout corps K, et puisque x2−n a deux racines dans 𝐅p, ces racines sont toutes les racines dans 𝐅p2. Cela montre que x0 et −x0 sont les racines de x2−n dans 𝐅p2, donc que x0,−x0∈𝐅p[5].

Nombre d'opérations

modifier

Une fois trouvés une valeur convenable pour a, le nombre d'opérations requises pour l'algorithme est 4m+2k−4 multiplications, 4m−2 sommes, où m est le nombre de chiffres dans l'écriture binaire de p et k le nombre de 1 dans cette représentation. Pour trouver a par essai-erreur, le nombre moyen de calculs du symbole de Legendre est 2. Cela dit, on peut avoir de la chance dès le premier essai et il peut en falloir plus de deux. Dans le corps 𝐅p2, on a les deux égalités suivantes :

(x+yω)2=(x2+y2ω2)+((x+y)2−x2−y2)ω,

où ω2=a2−n est déjà connu. Ce calcul nécessite 4 multiplications et 4 additions ;

(x+yω)2(a+ω)=(ad2−b(x+d))+(d2−by)ω,

où d=(x+ya) et b=ny. Cette opération nécessite 6 multiplications et 4 sommes.

En supposant que p≡1(mod4), (dans le cas p≡3(mod4), le calcul de x≡±np+14 est plus rapide), l'expression binaire de (p+1)/2 a m−1 chiffres, dont k valent 1. Ainsi, pour calculer la puissance (p+1)/2-ième de (a+ω), la première formule doit être utilisée n−k−1 fois et la seconde k−1 fois.

Au bilan, l'algorithme de Cipolla est plus rapide que l'algorithme de Tonelli-Shanks si et seulement si S(S−1)>8m+20, où 2S est la plus grande puissance de 2 qui divise p−1[6].

Équation modulo une puissance d'un nombre premier

modifier

D'après Dickson dans son History of numbers, la formule suivante due à Cipolla permet de trouver les racines carrées modulo les puissances des nombres premiers[3],[7] :

2−1qt((k+k2−q)s+(k−k2−q)s)modpλ
où t=(pλ−2pλ−1+1)/2 et s=pλ−1(p+1)/2,
avec q=10, k=2 dans l'exemple précédent

En reprenant l'exemple ci-dessus, on peut vérifier que cette formule calcule bien des racines carrées modulo les puissances d'un nombre premier.

On va vérifier qu'une racine de 10 modulo 133 est :

10mod133≡1046.

On calcule d'abord 2−1qt :

2−110(133−2⋅132+1)/2mod133≡1086

On calcule maintenant (2+22−10)132⋅7mod133 et (2−22−10)132⋅7mod133 (on trouve ici (en) un code Mathematica qui effectue ce calcul, que l'on peut comprendre par analogie avec un calcul sur les nombres complexes avec des coefficients modulo 13 au lieu d'être réels.)

On trouve alors :

(2+22−10)132⋅7mod133≡1540 et (2−22−10)132⋅7mod133≡1540

et, finalement :

1086(1540+1540)mod133≡1046,

qui est la bonne réponse.

Notes et références

modifier
(en) Cet article est partiellement ou en totalité issu de l’article de Wikipédia en anglais intitulé « Cipolla's_algorithm » (voir la liste des auteurs).
  1. ↑ Cipolla (1903).
  2. ↑ Cipolla (1907).
  3. 1 2 Dickson (1919), p. 218.
  4. ↑ Richard Crandall et Carl Pomerance, Prime numbers : A computational perspective, New York, Springer, , 2e éd. (1re éd. 2001), xv + 597 p. (ISBN 978-0-387-25282-7, DOI 10.1007/0-387-28979-8), p. 157.
  5. ↑ Matt Baker, « Cipolla's Algorithm for finding square roots mod p », sur people.math.gatech.edu (version du sur archive.org).
  6. ↑ Gonzalo Tornaría, LATIN 2002: Theoretical Informatics, Springer, coll. « Lecture Notes in Computer Science » (no 2286), , xiii + 630 p. (ISBN 978-3-540-43400-9, DOI 10.1007/3-540-45995-2_38), p. 430-434.
  7. ↑ Michele Cipolla, « Applicatione della teoria delle funzioni numeriche del second'ordine alla risoluzione della congruenza di secondo grado », Rendiconto dell' Accademia delle Scienze Fisiche e Matematiche, Napoli, 3e série, vol. 10,‎ , p. 144-150 (lire en ligne).

Bibliographie

modifier

Articles connexes

modifier