\chapterimage{wiles}
\chaptertext{En  1995, le  mathématicien  anglais Andrew  \textsc{Wiles}
  fit   sensation   en   démontrant   enfin   le   grand   théorème   de
  \textsc{Fermat},  trois siècles  après  sa formulation,  à l'aide  des
  courbes elliptiques ce qui surprit  les spécialistes de la théorie des
  nombres. Elles jouent actuellement  un rôle essentiel dans la sécurité
  informatique mais  on les retrouve  en géométrie, en  mécanique. Elles
  vont  nous permettre  aujourd'hui de  mettre un  pied dans  un domaine
  mathématique encore tout chaud...}
%\setcounter{chapter}{4}
\maple
\chapter{Courbes elliptiques}


\section{Un peu de lecture...}

Nous  ne pouvons,  à notre  niveau,  que parcourir  rapidement ce  riche
domaine des mathématiques en admettant la plupart des résultats que vous
démontrerez peut-être un jour. Pour  les plus curieux, vous pourrez lire
le  très  bel ouvrage  de  Marc  \textsc{Hendry} \textit{Arithmétique  :
  Primalité  et   codes,  Théorie  analytique   des  nombres,  Equations
  diophantiennes,  Courbes elliptiques }  paru en  2008 chez  Calvage \&
Mounet  ainsi que  l'\textit{Introduction élémentaire  à la  théorie des
  courbes  elliptiques}   \footnote{\href{http://sciences.ows.ch/mathematiques/CourbesElliptiques.pdf}{http://sciences.ows.ch/mathematiques/CourbesElliptiques.pdf}}  Marc  \textsc{Joye}   de  l'Université  de
Louvain\footnote{\href{http://www.uclouvain.be/crypto/publications/latest}{http://www.uclouvain.be/crypto/publications/latest}},
un  des  hauts  lieux  de  la  cryptographie,  où  vous  retrouverez  de
nombreuses démonstrations de beaux résultats sur le sujet.

Les ouvrages suivants proposent des activités pratiques:

\begin{itemize}
\item \textit{Initiation à la cryptographie} de Gilles \textsc{Dubernet}
  (Vuibert 2002);
\item   \textit{Algèbre,   arithmétique    et   maple}   de   Bernadette
  \textsc{Perrin-Riou} (Cassini 2000);
\item \textit{Mathématiques \& informatique} de François \textsc{Morain}
  et Jean-Louis \textsc{Nicolas} (Vuibert 1995).
\end{itemize}





\section{Quelques résultats préliminaires}



La méthode de la tangente et  de la sécante dont nous allons parler n'est
pas  nouvelle.  \textsc{Fermat},  voire  \textsc{Diophante}  ont  tourné
autour   puis   \textsc{Newton},   \textsc{Lagrange},   \textsc{Cauchy},
\textsc{Sylvester},  \textsc{Poincaré}. Il  faut  pourtant attendre  les
années  1920  et  André  \textsc{Weil} pour  qu'elle  soit  parfaitement
maîtrisée même si un article 
 publié en allemand en 1896 par le Danois \textsc{Juel} donne une
description complète de la loi de  groupe sur une cubique mais semble ne
pas avoir été lu par ses contemporains\footnote{Voir l'article de Norbert
  \textsc{Schappacher}
  \href{www-irma.u-strasbg.fr/~schappa/NSch/Publications\_files/DPP.pdf}{www-irma.u-strasbg.fr/~schappa/NSch/Publications\_files/DPP.pdf}}...  

Il a cependant fallu attendre la
fin du  XX\up{e} siècle pour  l'utiliser en arithmétique avec  le succès
que  l'on sait  car ces  courbes permettent  d'obtenir  efficacement des
factorisations  d'entiers  comme   le  montra  le  néerlandais  Hendrik
\textsc{Lenstra}. 

 Nous aurons besoin  de connaître quelques résultats sur  les groupes et
 les     corps     finis     que     vous    avez     découvert     avec
 M.  \textsc{Sauvageot}\footnote{Qui,  comme   vous  le  savez,  est  le
   traducteur-auteur  d'une  des  \og  bibles\fg{}  de  la  théorie  des
   nombres: \textit{Introduction à la  théorie des nombres} paru en 2006
   chez Vuibert...}.

Nous  aurons également  besoin de  parler de  manière intuitive  du plan
projectif $\bbp_2(\mathbf{K})$ que vous avez découvert lors du chapitre sur les 
 quadriques et de polynômes homogènes sur $\mathbf{K}[X,Y,Z]$.
 

Disons     qu'en    gros,     on     définit    sur     $\mathbf{K}^3\setminus
\bigl\{(0,0,0)\bigr\}$ une relation d'équivalence: 

$$(X,Y,Z)\equiv   (X',Y',Z')\Leftrightarrow    \exists   t\in\mathbf{K}^*,   \
(X',Y',Z')=t(X,Y,Z)$$

et que $\bbp_2(\mathbf{K})$ est l'ensemble des classes d'équivalence.


On   établit   une  \og   correspondance\fg{}   entre  l'espace   affine
$\mathbb{A}_2(\mathbf{K})$  et $\bbp_2(\mathbf{K})$:  au point  de coordonnées
$(x,y)$ du  plan affine,  on fait correspondre  le point  de coordonnées
$(X:Y:Z)$  dans   le  plan   projectif  en  posant   $x=\frac{X}{Z}$  et
$y=\frac{Y}{Z}$. 
Se pose alors le problème du cas $Z=0$. Ce cas correspond au \og point à
l'infini\fg{} où deux droites parallèles du plan projectif se croisent.
Nous  en  distinguerons  par  la  suite un  particulier  de  coordonnées
$(0:1:0)$ que nous noterons $\OR$.

\section{Loi de groupe sur une cubique}


On  peut montrer  que dans  le plan  projectif, toute  droite  coupe une
cubique d'équation $Y^2Z=X^3+aXZ^2+bZ^3$  en exactement trois points, en
tenant compte de 
l'ordre de  multiplicité, lorsque $a$ et  $b$ remplissent certaines
conditions qui rendent la courbe \og lisse\fg{} et sans racine double. 

En   fait,   quand  on   repasse   \og   en   affine\fg{},  on   obtient
$y^2=x^3+ax+b$. Vous  avez évoqué le discriminant de  $x^3+ax+b$ lors de
l'étude de la méthode de  \textsc{Cardan} pour résoudre les équations de
degré  3. En  fait,  il faut  que  ce discriminant  soit  non nul:  nous
supposerons donc par la suite que $4a^3+27b^2\neq 0$.

Il faut aussi que la caractéristique  du corps soit différente de 2 ou 3
mais cela ne nous inquiète pas car nous allons travailler dans des corps
finis  de très  grande  caractéristique (factoriser  des petits  nombres
ne nécessite pas de sortir l'artillerie lourde...).

Bon, regardons les points à  l'infini: $Z=0 \Longrightarrow X=0$. Il n'y
a  donc qu'un  seul  qui  est dans  la  direction $x=0$  et  qui a  pour
coordonnées dans $\bbp_2$ $\OR(0:1:0)$.


\medskip

Par la suite, nous considérerons donc une cubique $\ER$ d'équation
$y^2=x^3+ax+b$ de discriminant non nul.


 On notera $\ER(\mathbf{K})$ les
solutions  $(x,y)$  de   l'équation  $y^2=x^3+ax+b$  sur  $\mathbf{K}^2$
auxquelles on ajoute $\OR$.


Par exemple, on peut visualiser ce que cela donne sur $\bbr$:

\begin{lstlisting}[caption={}]
> anim_elliptic:=proc()
   local P,a,b;
   P:=NULL;
   for a from -10 to 5 by 2 do
     for b from -10 to 5 by 2  do
       if (4*a^3+27*b^2)<>0 then
        P:=P,plots[implicitplot](y^2=x^3+a*x+b,x=-10..10,y=-10..10);
   fi;od;od;
   plots[display]([P],insequence=true,view=[-10..10,-10..10]);
  end:
\end{lstlisting}

Soit  P un point  quelconque. Une  droite $(P\OR)$  est donc  une droite
passant par P et parallèle à l'axe $x=0$.

On  a admis  que toute  droite coupait  $\ER$ en  un troisième  point en
tenant  compte de  la multiplicité.  On peut  donc définir  une  loi sur
$\ER(\mathbf{K})$: 

\begin{itemize}
\item si P et Q sont deux points distincts de $\ER(\mathbf{K})$, alors
  la droite (PQ) recoupe la courbe en un unique troisième point que nous 
  noterons $P\star Q$. La droite joignant $P\star Q$ et $\OR$ recoupe la
  courbe en un troisième point que nous noterons $P+ R$.
\item si $P=Q$,  le point $P\star P$ sera  l'intersection de la tangente
  avec la  courbe.
\end{itemize}


On  peut  vérifier que  cette  loi est  commutative,  que  $\OR$ en  est
l'élément neutre. et  que le symétrique de P par  rapport à l'axe $(0x)$
est le symétrique de P pour la loi $+$ et qu'il appartient à la courbe.

Il resterait à vérifier  l'associativité mais cela nécessiterait pas mal
de travail  et nous  n'en avons  pas le temps:  vous pourrez  étudier la
littérature pour vous en convaincre.

\begin{enumerate}
\item Soit $P_1(x_1,y_1)$  et $P_2(x_2,y_2)$. Déterminez les coordonnées
  $(x_3,y_3)$  de  la  somme  $P_1+P_2$ en  distinguant  les  différents
  cas. On prendra $\mathbf{K}=\mathbf{R}$

Déduisez-en une procédure \lstinline+somme := proc(P1,P2,a,b)+ qui 
calcule les coordonnées de la somme $P_1+P_2$ pour une courbe elliptique
donnée  dépendant  des  paramètres  $a$  et $b$.  On  pourra  créer  une
procédure intermédiaire  qui vérifie qu'un point appartient  à la courbe
elliptique de paramètres  $a$ et $b$. On symbolisera  le point $\OR$ par
\lstinline+[O]+ (à ne pas confondre avec \lstinline+0+ ...). 

Vous pourrez ensuite visualiser la construction:

\begin{lstlisting}[caption={}]
> dessin_elliptic:=proc(P1,P2,a,b)
    local P3,P4,y2,E,x,L1;
    P3 := somme(P1,P2,a,b);
    if P1 = [O] or P2 = [O] or P3 = [O] 
       then RETURN(`Point à l infini`);fi;
    P4 := [P3[1],-P3[2]];
    E := [];
    for x from -5 to 5 by 0.01 do
      y2 := evalf(x^3 + a*x + b);
      if y2  = 0 then
        E := [op(E),[x,sqrt(y2)],[x,-sqrt(y2)]];
      fi;
    od;
    E := plot(E,style=point,color=green);
    L1 := plot([P1,P3,P4],color=blue,thickness=3);
    plots[display]([E,L1]);
  end:
  
> point_courbe:=proc(x,a,b)
    RETURN([(x),(sqrt(x^3+a*x+b))]);
  end:
  
> dessin_elliptic(point_courbe(-2,-5,3),point_courbe(-1,-5,3),-5,3);
\end{lstlisting}

\item On veut  maintenant tracer la courbe en  travaillant dans $\bbf_p$
  avec bien sûr $p$ un 
  nombre premier. Qu'est-ce qui  va changer dans nos procédures? 

La recherche d'une racine carrée dans $\mathbf{Z}/n\mathbf{Z}$ n'est pas
tout à fait évident. Pendant vos temps libres, vous pourrez vérifier que
si $p$ est un nombre premier congru à 3 modulo 4, alors on arrive à s'en
sortir  mais si  $p$ est  congru à  1, alors  on passe  par l'algorithme
probabiliste  de   \textsc{Shank}.  Nous  n'avaons   pas  besoin  d'être
efficace  ici car il  s'agit seulement  de dessiner  la courbe  avec une
valeur de $p$ petite donc une recherche exhaustive suffira. 

Pour ce qui  est de la recherche  de l'inverse, on a déjà  traité ce cas
dans les TD précédents et Maple sait d'ailleurs se débrouiller:
\lstinline+16^(-1)mod 29+ renvoie bien 20 car $16\times 20 \equiv 1[29]$
mais \lstinline+15^(-1)mod 27+ renvoie une erreur.

Voici  par exemple la  courbe elliptique  dans $\mathbf{Z}/31\mathbf{Z}$
d'équation  $y^2=x^3+26x+3$  où  les  points sont  représentés  par  des
losanges ainsi qu'une  droite passant par deux points  de la courbe dont
les points ont été représentés par des cercles...


%\begin{figure}
\begin{center}
  \includegraphics[height=11cm,angle=270]{ellipt04}
\end{center}
%\end{figure}

Voilà qui perturbe un peu nos habitudes! 

\item Que  se passe-t-il  dans $\mathbf{Z}/n\mathbf{Z}$ lorsque  $n$ est
  composé? Nous allons voir plus loin que ce n'est pas un problème et qu'il s'agit
  plutôt de la clé du succès des courbes elliptiques.

\item  Déterminez une  procédure donnant  les différents  multiples d'un
  point dans le groupe associé à une courbe elliptique donnée.
  \begin{lstlisting}[caption={}]
> multiples(point_courbe_p(1,26,3,31),33,26,3,31);

[O], [2, 1], [16, 12], [22, 1], [7, 30], [11, 15], [12, 11], 
[18, 14],[5, 14], [29, 6], [19, 28], [24, 6], [21, 13], [9, 6],
[30, 10],[8, 17], [4, 4], [4, 27], [8, 14], [30, 21], [9, 25], 
[21, 18],[24, 25], [19, 3], [29, 25], [5, 17], [18, 17],
[12, 20],[11, 16], [7, 1], [22, 30], [16, 19], [2, 30], [O]
  \end{lstlisting}

\item Déterminez une procédure \lstinline+k_multiple_p:=proc(P,k,a,b,p)+
  qui calcule le  $k$\up{e} multiple du point P.  Vous pourrez améliorer
  votre procédure en utilisant  un algorithme d'exponentiation rapide en
  pensant à la décomposition en base 2 de $k$.




\end{enumerate}

\section{Factorisation d'entiers: méthode de \textsc{Lenstra}}



\begin{enumerate}
\item Nous cherchons à factoriser un entier impair donné que nous savons
composé (par exemple pour casser une clé RSA). 

Dans notre  procédure de calcul de  somme dans $\mathbf{Z}/n\mathbf{Z}$,
des divisions  peuvent ne  pas être effectuées.  Maple renvoie  alors un
message d'erreur:

\begin{lstlisting}[caption={}]
> 7/3 mod 21;
'Error, the modular inverse does not exist'
\end{lstlisting}

Pourquoi ? Si tel est le  cas, que pouvons-nous dire de la factorisation
de $n$?  Comment modifier alors la procédure d'addition sur 
$\ER(\mathbf{Z}/n\mathbf{Z})$ pour obtenir un facteur de $n$?


\item 
On dit qu'un nombre $n$  est B-friable si toutes les puissances entières
divisant $n$ sont inférieures à B.

Par exemple, $2^4\times 3^2\times 11$ est 16-friable.



\item  Si le mathématicien  allemand Helmut  \textsc{Hasse} n'a  pas été
  très  inspiré  dans  ses  choix  politiques  en  soutenant  le  régime
  nazi\footnote{Il avait  pourtant un nom de famille  pouvant plaire aux
    nazis mais ceux-ci ont toujours  refusé son adhésion au parti car on
    le  suspectait d'avoir  des origines  juives...}, il  a été  un très
  grand  algébriste  et théoricien  des  nombres.  Il  a en  particulier
  démontré le théorème suivant:

$$\left|\#\ER(\bbf_p)-(p+1)\right|\leqslant 2 \sqrt{p}$$

Sa   démonstration   fait   référence   à   la   fonction   $\zeta$   de
\textsc{Riemann} qui est  a priori un outil d'analyse mais  qui a eu une
énorme influence  en théorie des nombres  comme nous le  verrons dans un
prochain TP.


\item Soit  $p$ un diviseur premier  de $n$. On suppose  que le cardinal
  $c_p$ de
  $\ER(\bbf_p)$    soit    B-friable.     Soit    P    un    point    de
  $\ER(\mathbf{Z}/n\mathbf{Z})$ différent  de $\OR$ et soit  $k$ le PPCM
  de $(1,2,..,B)$. Comme $c_p$ divise  $k$ et que $P\in \ER(\bbf_p)$ car
  $p$ divise  $n$, alors, d'après  le théorème de  \textsc{Lagrange}, on
  sait que $kP=\OR$ dans $\ER(\bbf_p)$.


Cependant,  on  ne  connaît  pas  $p$  donc on  va  calculer  $kP$  dans
$\ER(\mathbf{Z}/n\mathbf{Z})$. Or  des problèmes peuvent  apparaître car
il va  y avoir  des diviseurs de  0: le  point précédent nous  permet de
trouver un facteur  de $n$. Si c'est un facteur  trivial, on choisit une
autre courbe. Sinon,  on a un diviseur  de $n$! Si le calcul  de $kP$ ne
pose pas  de problème, on choisit un  autre point P ou  une autre courbe
elliptique.

Le problème est dans le choix du bon point et de la bonne courbe...

Voici un exemple proposé par Marc \textsc{Joye}.

On   veut   factoriser   $n=\numprint{540143}$   par   la   méthode   de
\textsc{Lenstra}. On va travailler sur les courbes elliptiques 
$$\ER_a: y^2=x^3+ax+1$$


Le  point  $P(0,1)\neq  \OR$  appartient  toujours  à  $\ER_a$.  Prenons
$a=1$. On vérifie que le discriminant est non nul modulo $n$. 

On   sait  qu'un   diviseur  premier   $p$   de  $n$   est  majoré   par
$\sqrt{n}\approx 735$

Le nombre  de points  de la  courbe est majoré,  d'après le  théorème de
\textsc{Hasse}, par $735+1+2 \sqrt{735}<792$. On choisit donc $B=792$.

On choisit un nombre 792-friable, par exemple $k=2^9\times 3^6$.

Si le calcul n'aboutit  pas, on a gagné, sinon, on augmente  $a$ de 1 ou
on augmente $B$ (par exemple $B=2^9\times 3^6\times 5^4$).

Il  a  été montré  que  la  complexité de  cet  algorithme  est en  $\OR
\left(\mathrm{e}^{(1+\varepsilon)\log  p\log\log p}\right)$, où  $p$ est
le plus petit facteur premier de $n$: c'est bien 
plus efficace que les méthodes classiques.

Aidez-vous de Maple pour factoriser $n$ avec cette méthode.


\begin{lstlisting}[caption={}]
> facto_p(nextprime(123456789)*nextprime(98765432));

12193264407559831 = 98765441 * 123456791 avec a = 49
\end{lstlisting}

On notera cependant  qu'un concurrent est arrivé récemment  est a remisé
la méthode de factorisation par courbes elliptiques au deuxième rang: il
s'agit   du    crible   algébrique    dont   la   complexité    est   en
$\OR\left(\mathrm{e}^{\left({64\over9}\log n\right)^{1\over3} (\log \log
    n)^{2\over3}}\right)$.

Cependant, la  méthode \og elliptique\fg{} est plus  rapide pour trouver
de petits facteurs.


\section{Cryptographie}

En  fait,  on reprend  des  méthodes  introduites  ces dernières  années
(\textsc{El Gamal}) sur
$(\bbf_p^\star,\times$ 
mais en travaillant sur des  courbes elliptiques. La difficulté tient au
fait  qu'il est  difficile de  calculer  un logarithme  discret. Or  les
groupes définis sur des courbes elliptiques sont très divers, on ne sait
même pas trouver rapidement leur  ordre et encore moins la structure: le
problème  du  logarithme  discret  devient beaucoup  plus  compliqué  et
inversement  les calculs  du  codeur  se font  très  rapidement sur  des
courbes elliptiques définies sur $\bbf_{2^m}$. 

Par  exemple, on estime  actuellement qu'une  clé de  256 bits  avec des
courbes 
elliptiques assure la même sécurité qu'une clé de 3072 bits avec RSA...

Cela  permet   donc  d'assurer  une  grande  sécurité   sur  les  petits
processeurs des cartes à puces.

Un problème extra-mathématique existe  cependant: les algorithmes liés à
ces méthodes  sont cachés  sous d'horribles brevet  qui rend le  coût de
leur utilisation exorbitant...

\vfill

\eject
\section{Jokers}

Si vous éprouvez quelques difficultés...

\begin{lstlisting}[caption={}]
> proc1 := proc(x,p)
  local i,r;
  r:=NULL;
  for i from 0 to p-1 do 
    if i^2 mod p = x 
    then r := r,i;
    fi;
  od;
  RETURN([r]);
  end:
\end{lstlisting}

\begin{lstlisting}[caption={}]
> proc2 := proc(P1,P2,a,b,p)
   local x1,x2,y1,y2,x3,y3,lambda;
   if (4*a^3+27*b^2) mod p = 0  then RETURN(`Delta nul`);fi;
   if  (P1=[O] or appart_p(a,b,P1,p)) and (P2=[O] or appart_p(a,b,P2,p))   then
     if P1 = [O] then RETURN(P2); fi;
     if P2 = [O] then RETURN(P1); fi;
     x1:=P1[1] mod p;y1:=P1[2] mod p;x2:=P2[1] mod p;y2:=P2[2] mod p;
     if x1 = x2 mod p and y1 = -y2 mod p then RETURN([O]);fi;
     if P1 = P2 then 
        if y1 = 0 mod p then RETURN([O]);fi;
           if igcd(y1,p) <  1 then RETURN([`Diviseur`,igcd(y1,p)]);fi; 
        lambda := (3*x1^2+a)/(2*y1) mod p;
     else
        if igcd(x1-x2,p) <  1 then RETURN([`Diviseur`,igcd(x1-x2,p)]);fi; 
        lambda := (y1-y2)/(x1-x2) mod p;
     fi;
     x3 := (lambda^2-x1-x2) mod p;
     y3 := (-y1 +lambda*(x1-x3)) mod p;
     RETURN([x3,y3]):
   else RETURN(`Mauvais points`);
   fi;
 end:
\end{lstlisting}

\begin{lstlisting}[caption={}]
> proc3 := proc(x,a,b,p)
    local X;
    X := x;
    while sqrt_p((X^3+a*X+b) mod p,p) = [] and X < p do
      X := X+1;
    od;
    RETURN([X,sqrt_p((X^3+a*X+b) mod p,p)[1]]);
  end:
\end{lstlisting}


\begin{lstlisting}[caption={}]
> proc4 := proc(x1,x2,a,b,p)
    local y2,E,x,i,P1,P2,P,lambda;
    if (4*a^3+27*b^2) mod p = 0 then RETURN(`Delta nul`);fi;
    P1 := point_courbe_p(x1,a,b,p);
    P2 := point_courbe_p(x2,a,b,p);
    E := []; P:= [P1,P2]; 
    lambda := (P2[2]-P1[2])/(P2[1]-P1[1]) mod p;
    for x from 0 to p-1 do
      y2 := (x^3 + a*x + b) mod p;
      for i in sqrt_p(y2,p) do
        E := [op(E),[x,i]];
        P := [op(P),[x,(lambda*(x-P1[1])-P1[2]) mod p]];
      od;
    od;
    E := plot(E,style=point,symbol=diamond,color=red);
    P := plot(P,style=point,symbol=circle,color=blue);
    plots[display]([E,P]);
   end:
\end{lstlisting}


\begin{lstlisting}[caption={}]
> proc5 := proc(P,k,a,b,p)
  local K,M,Q,r;
  K:=k; M:=[O]; Q := P mod p;
  while K   0 do
    r := K mod 2; 
    if r = 1 then M := somme_p(M,Q,a,b,p); fi; 
    if member(`Diviseur`,M) then RETURN(M);fi;   
    Q := somme_p(Q,Q,a,b,p);
    if member(`Diviseur`,Q) then RETURN(Q);fi;
    K := iquo(K,2);
    od;
  RETURN(M);
  end:
\end{lstlisting}


\begin{lstlisting}[caption={}]
> proc6 := proc(n)
  local deux,trois,sept,onze,h;
  deux:=2;trois:=3;sept:=7;onze:=11;
  h:=rand(n);
  while deux <= h() do deux := deux*2;od;
  while trois <= h() do trois := trois*3;od;
  while sept <= h() do sept := sept*7;od;
  while onze <= h() do onze := onze*11;od;
  RETURN(deux*trois*sept*onze/462);
  end:
\end{lstlisting}


\begin{lstlisting}[caption={}]
> proc7 := proc(n)
  local kP,a,b,P,B,s,k;
  if isprime(n) then RETURN(`premier!`);fi;
  P:=[0,1];
  s := ceil(sqrt(n)):
  B:=s+1+2*ceil(sqrt(s));
  k:=friable(B);
  a:=1;b:=1;
  kP:=k_multiple_p(P,k,a,b,n);
  while not member(`Diviseur`,kP) do
    a := a+1; # on peut choisir de jouer aussi sur B
    # k := friable(B);
    kP:=k_multiple_p(P,k,a,b,n);
    od;
  printf(`%a = %a * %a avec a = %a`,n,kP[2],n/kP[2],a);
  end:
\end{lstlisting}

\end{enumerate}
%%% Local Variables: 
%%% TeX-master: "PolyMapleMPstar"
%%% End: 
