• Aucun résultat trouvé

2.2 Corps finis premiers

2.2.1 Modular

L’implantation Modular est une implantation propre `a la biblioth`eque LinBox. Le principe de cette implantation est d’utiliser les m´ecanismes templates pour fournir une arithm´etique modulaire g´en´erique en fonction du type de repr´esentation des ´el´ements. Pour cela, il faut que les types d’instanciation de cette classe fournissent les op´erateurs arithm´etiques classiques (+, -,×, /) ainsi que l’op´eration de r´eduction modulo (%). De plus, le mod`ele de ces ´el´ements doit respecter l’arch´etype de la biblioth`eque LinBox (voir code 2.2). En particulier, cette classe d´efinit des implantations de corps premiers pour les types natifs entiers du langage (int, long). Le nombre premier d´efinissant les caract´eristiques de l’arithm´etique est encapsul´e dans la classe par un attribut prot´eg´e (protected _modulus). `A partir de maintenant, nous utilisons l’aliasElement encapsul´e dans l’arch´etype pour sp´ecifier le type g´en´erique des ´el´ements dans l’implantation.

te mpl ate < c l a s s Type >

c l a s s M o d u l a r { p u b l i c :

t y p e d e f Typ e E l e m e n t ; ...

};

A partir de cette classe, on peut d´` efinir l’ensemble des op´erations de fa¸con g´en´erique. Par exemple, la fonction d’addition est implant´ee par une addition classique suivie d’une phase de correction si la valeur calcul´ee n’appartient plus `a la repr´esentation.

E l e m e n t & add ( E l e m e n t & a , c o n s t E l e m e n t & b , c o n s t E l e m e n t & c ) c o n s t { a = b + c ;

if ( a > _ m o d u l u s ) a -= _ m o d u l u s ; r e t u r n a ;

}

22http://www.shoup.net/ntl

23http://www-apache.imag.fr/software/givaro

24http://www.informatik.tu-darmstadt.de/TI/LiDIA/

Pour la fonction de multiplication, la d´etection de correction ne peut se faire par de simples comparaisons car la valeur interm´ediaire est trop grande. Dans ce cas, on utilise la fonction de r´eduction modulaire (%). Cette fonction est directement disponible dans la biblioth`eque standard (libc) pour les entiers machines au travers d’algorithmes de division enti`ere.

E l e m e n t & mul ( E l e m e n t & a , c o n s t E l e m e n t & b , c o n s t E l e m e n t & c ) c o n s t { r e t u r n a = ( b * c ) % _ m o d u l u s ;

}

L’utilisation de ce type de r´eduction est coˆuteux en pratique car elle fait appel `a une op´eration de division. Nous essayons donc de limiter au maximum son utilisation. Par exemple, l’op´eration axpy qui correspond `a une multiplication et une addition combin´ees (i.e. axpy(r,a,x,y) =>

r =ax+y mod modulus) est implant´ee au travers d’une seule r´eduction modulaire apr`es le calcul entier exact.

Toutefois, ce choix d’implantation restreint la taille des corps premiers possibles du fait que les calculs interm´ediaires doivent rester exacts. Il faut donc assurer que la taille des corps premiers d´efinis au travers de cette classe permette de toujours effectuer les calculs interm´ediaires de fa¸con exacte. Pour cela, il suffit de limiter la taille du modulo en fonction des valeurs interm´ediaires maximales. L’op´eration la plus restrictive est la fonctionaxpy. Pour un type d’´el´ements ayant une pr´ecision de m bits, le modulop doit satisfaire

(p−1)2+p−1<2m. (2.1)

Cette restriction est somme toute importante car cela signifie que pour des entiers machine 32 bits non sign´es, le corps premier maximal sera d´efini pour p = 65521, soit 16 bits. Afin de fournir des implantations sur les entiers machine autorisant des corps premiers plus grands, nous proposons des sp´ecialisations de la classeModularpour les entiers machine sign´es et non sign´es 8, 16 et 32 bits.

Ces sp´ecialisations utilisent essentiellement des conversions de types dans les op´erations les plus restrictives : multiplication et axpy. L’implantation de ces fonctions est bas´ee sur une conversion des op´erandes dans un type autorisant une pr´ecision deux fois plus grande. Par exemple, l’implantation de la fonctionaxpy pour les entiers non sign´es 32 bits (uint32) se fait `a partir d’une conversion vers des entiers non sign´es 64 bits (uint64), de calcul sur 64 bits et d’une conversion sur 32 bits.

u i n t 3 2 & axp y ( u i n t 3 2 & r ,

c o n s t u i n t 3 2 & a , c o n s t u i n t 3 2 & x ,

c o n s t u i n t 3 2 & y ) c o n s t {

r e t u r n r = (( u i n t 6 4 ) a * ( u i n t 6 4 ) x + ( u i n t 6 4 ) y ) % ( u i n t 6 4 ) _ m o d u l u s ; }

2.2. Corps finis premiers 47 En utilisant cette implantation pour les uint32, on augmente la taille des corps possibles de p < 216 `a p < 231 avec une faible perte d’efficacit´e. En effet, cette implantation tire parti du fait que la plupart des processeurs proposent une instruction de multiplication 32 bits × 32 bits qui donne le r´esultat sur 64 bits stock´es dans deux registres 32 bits (instruction ”imul”

sur Intel [19]). Ainsi, le seul surcoˆut de cette m´ethode provient de l’utilisation d’une r´eduction modulo 64 bits `a la place d’une r´eduction 32 bits qui est intrins´equement moins performante du fait des algorithmes de division implant´es dans les biblioth`eques standard. Les conversions sont ici gratuites car le compilateur consid`ere uniquement les r´esultats de la multiplication et de la r´eduction comme des entiers 64 bits. Les entiers 64 bits ´etant en pratique deux registres 32 bits, la conversion vers des entiers 32 bits est imm´ediate. Ce sont maintenant les op´erations d’addition et de soustraction qui sont limitantes car elles n´ecessitent un bit suppl´ementaire pour stocker les valeurs interm´ediaires. L’utilisation de la mˆeme m´ethode pour ces op´erations n’est pas int´eressante car il n’existe pas d’instruction d’addition (32 + 32)→64 bits et de plus elle ne permettrait de gagner qu’un seul bit sur la taille des corps premiers.

Une autre possibilit´e propos´ee au travers d’une sp´ecialisation de cette classe g´en´erique est d’utiliser les nombres flottants machine pour atteindre des corps premiers plus grands. Les nombres flottants double pr´ecision poss`edent une mantisse cod´ee sur 53 bits qui permet de re-pr´esenter de fa¸con exacte des entiers strictement inf´erieurs `a 253. Bien que la norme IEEE-754 [1]

sp´ecifie qu’un des bits de la mantisse est implicite du fait d’une repr´esentation fractionnaire, le po-sitionnement de la virgule garantit les 53 bits de pr´ecision pour des valeurs enti`eres. L’utilisation de ces nombres flottants permet donc de d´efinir des corps premiers allant jusqu’`ap≤94906265, c’est-`a-dire de l’ordre de 26 bits. L’implantation des op´erations arithm´etiques est la mˆeme que dans le cas entier, sauf pour l’op´eration de r´eduction modulaire qui est ici effectu´ee en utilisant la fonctionfmoddes biblioth`eques standard. Cette fonction retourne le reste entier de la division de deux nombres flottants dans un format flottant.

Enfin, une derni`ere alternative propos´ee dans la biblioth`eque LinBox est d’utiliser des entiers en pr´ecision arbitraire. En particulier, nous utilisons l’interfaceinteger(voir§1.2.1) des entiers multipr´ecisions GMP25 pour instancier la classe Modular. L’utilisation d’entiers multipr´ecision permet de d´efinir des corps premiers de tr`es grande taille, les entiers GMP proposent une pr´ e-cision maximale de m2m o`u m est le nombre de bits d’un entier machine (32 ou 64 suivant l’architecture).

Nous avons vu que la plupart des op´erations de la classe Modular sont effectu´ees `a partir d’op´erations sur les entiers suivies d’une r´eduction modulo. N´eanmoins l’op´eration d’inversion des ´el´ements du corps ne peut se faire en suivant ce sch´ema. En effet, l’inverse modulaire y d’un entierx est la solution de l’´equation yx≡1 modp. Une fa¸con classique de r´esoudre cette

´equation est d’utiliser l’algorithme d’Euclide ´etendu [36, th´eoreme 4.1] qui calcule les coefficients de Bezouts, t∈Z tel quesx+tp= 1 et donc 1/x≡s modp.

En pratique, on utilise une version partielle de l’algorithme d’Euclide ´etendu [21,§1.4.5] qui permet de calculer uniquement le coefficient s de l’´equation de Bezout. Cette version permet d’´eviter un tiers des op´erations arithm´etiques de l’algorithme traditionnel. La fonction d’inversion modulaire peut alors s’´ecrire

E l e m e n t & inv ( E l e m e n t & x , c o n s t E l e m e n t & y ) c o n s t { E l e m e n t x_int , y_int , q , tx , ty , tmp ;

x _ i n t = _ m o d u l u s ;

25http ://www.swox.com/gmp/

y _ i n t = y ;

tx = 0;

ty = 1;

w h i l e ( y _ i n t != 0) { q = x _ i n t / y _ i n t ; tmp = y _ i n t ;

y _ i n t = x _ i n t - q * y _ i n t ; x _ i n t = t emp ;

tmp = ty ;

ty = tx - q * ty ;

tx = te mp ;

}

if ( x < 0) x += _ m o d u l u s ; r e t u r n x ;

}

Une remarque int´eressante par rapport `a l’algorithme d’Euclide ´etendu classique est qu’en pratique on pr´ef´erera utiliser la version partielle pour calculer un seul coefficient et d´eduire le deuxi`eme `a partir de l’´equation t = (sx−pgcd(x, p))/p. En particulier, ce calcul devient int´eressant quand l’un des deux op´erandes est une puissance de la base de repr´esentation des entiers car ce calcul se ram`ene `a une multiplication, une soustraction et un d´ecalage.