n étant un entier naturel, la condition pour que cos(Pi/
n) soit calculable par radicaux est bien connue : il faut et il suffit que
n soit le produit d'une puissance de deux et de nombres de Fermat premiers distincts. Je ne sais pas démontrer que cette condition est nécesssaire. La théorie de Galois montre qu'elle est suffisante et fournit un algorithme de calcul qu'on implémente ici sous la forme d'une procédure Maple
Cos
, qui s'utilise à la place de la procédure
cos
habituelle.
La procédure calcule toutes les valeurs de la fonction cosinus lorsque cela est possible. Dans le cas contraire elle simplifie le plus possible le résultat.
Un petit aperçu pour commencer :
(
pdf, 36 Ko, 1 p. Créé le 21 avril 2005, modifié le 14 février 2008.)
Le résultat de l'évaluation de
Cos(Pi/257)
fournit une formule longue de 38 pages...
(
pdf, 524 Ko, 39 p. Créé le 21 avril 2005.)
(temps de calcul 12 secondes sous Maple 9/iMac G5)
Pour comprendre l'algorithme : rien ne vaut un bon exercice...
(
pdf, 48 Ko, 1 p. Créé le 15 février 2008.)
La procédure
Cos
permet en théorie de traiter également le cas
n=65537, plus grand nombre de Fermat premier connu, mais en pratique il faudra attendre que la technologie informatique connaisse quelques progrès conséquents, la longueur de la formule étant à vue de nez de quelques millions de pages...
Le code de la procédure
Cos
:
(testé en Maple V 5 et Maple 9. Fonctionne probablement sous toutes les versions à partir de la V 5.
Ne fonctionne probablement pas sous Maple V 4.)
Cos:=proc()
local a,n,c,p,k,d:
global `Cos/e`,`Cos/t`,`Cos/l`,`Cos/i`, `Cos/V`,`Cos/F`,`Cos/C`:
option `Paul Barbaroux, 2005-2008.`:
if not(assigned(`Cos/F`))
then
for d in {5,17,257,65537} do
p:=1:
for k from 0 to (d-1)/2-1 do
`Cos/e`[d,k]:=p: `Cos/l`[d,p]:=k:
p:=3*p mod 2*d: if p>d then p:= 2*d-p fi
od
od:
`Cos/F`:=proc(n,l,p)
local t,s,q,r,m,k,k1,l1,s1,s2,somme,produit:
option remember: q:=(n-1)/4/p: r:=2*q: s:=(n-1)/2:
if p=s then [1/2,0]
else
l1:=min(l+q mod s,l-q mod s):
somme:=`Cos/F`(n,min(l,l1),2*p):
for k from 0 to q-1 do `Cos/t`[p,k]:=0 od:
for k from 0 to p-1 do
for k1 from 0 to p-1 do
m:=(`Cos/e`[n,(l+k*r) mod s]
-`Cos/e`[n,(l1+k1*r) mod s]) mod (2*n):
if m>n then m:= 2*n-m fi: m:=n-m:
if `Cos/l`[n,m]<q
then `Cos/t`[p,`Cos/l`[n,m]]
:= `Cos/t`[p,`Cos/l`[n,m]] -1 fi:
m:=(`Cos/e`[n,(l+k*r) mod s]
+`Cos/e`[n,(l1+k1*r) mod s]) mod (2*n):
if m>n then m:= 2*n-m fi: m:=n-m:
if `Cos/l`[n,m]<q
then `Cos/t`[p,`Cos/l`[n,m]]
:= `Cos/t`[p,`Cos/l`[n,m]] -1 fi
od
od:
produit:=add(`if`(`Cos/t`[p,k]<>0,
`Cos/t`[p,k]*convert(`Cos/F`(n,k,2*p),`+`),0),k=0..q-1)/2:
s1:=evalf(`+`(seq('cos'(`Cos/e`[n,(l+k*r) mod s]*Pi/n), k=1..p))):
s2:=evalf(`+`(seq('cos'(`Cos/e`[n,(l1+k*r) mod s]*Pi/n), k=1..p))):
t:= sqrt(expand(op(1,somme)^ 2)+op(2,somme)^ 2
+2*op(1,somme*(n-1)/2/p)*2*p/(n-1)*op(2,somme)-4*produit):
if s1>s2 then [convert(somme,`+`)/2,t/2]
else [convert(somme,`+`)/2,-t/2] fi
fi
end:
`Cos/V`:=proc()
local t,s,x:
t:=op(4,eval(cos)):
if t<>NULL then t:=op(op(eval(t))) fi:
s:=op(4,eval(Cos)):
if s<>NULL then s:=op(op(eval(s))) fi:
map(proc(x) if type(lhs(x),complexcons)
then print('Cos'(lhs(x))=rhs(x)) fi
end,
{t,s}):
t:=op(4,eval(`Cos/F`)):
if t<>NULL
then seq(print(add('Cos'(`Cos/e`[
op(1,[lhs(x)]),
(op(2,[lhs(x)])+s*(op(1,[lhs(x)])-1)/2/op(3,[lhs(x)]))
mod ((op(1,[lhs(x)])-1)/2)]
*Pi/op(1,[lhs(x)])),
s=0..op(3,[lhs(x)])-1) =convert(rhs(x),`+`)),
x=op(op(eval(t))))
fi: NULL
end:
`Cos/C`:= proc(a)
eval(subs(
{cos=proc(x) if member(op(2,x/Pi),{5,17,257,65537})
then Cos(x)
else cos(x) fi end,
sin=proc(x) Cos(Pi/2-x) end},
eval(subs(`Cos/i`=proc(x) x end,
expand('cos'(`+`(op(map(`Cos/i`,
map(proc(t) ((op(1,t)^op(2,t))*a/Pi/2
mod (op(1,t)^op(2,t)))*Pi*2/(op(1,t)^op(2,t)) end,
map(proc (x) [op(x[1]), x[2]] end,
convert(ifactor(op(2,a/Pi/2)), multiset))))))))))))
end
fi:
a:=args:
if a=NULL
then `Cos/V`()
else
c:=cos(a):
if not(has(c,cos)) or not(type(a/Pi,fraction))
then Cos(a) := c
else
d:=op(2,a/Pi): n:=op(1,a/Pi):
if not( n>0 and n<d ) then
n:=n mod (2*d): if n>d then n:= 2*d-n fi: Cos(a) := Cos(n*Pi/d)
elif type(d/2,integer) then
if n<d/2 then Cos(a) := sqrt((1+Cos(2*a))/2)
else Cos(a) := -sqrt((1+Cos(2*a))/2) fi
elif member(d,{5,17,257,65537}) then
n:=n mod (2*d): if n>d then n:= 2*d-n fi:
if type(n/2,integer)
then RETURN(-convert(`Cos/F`(d,`Cos/l`[d,d-n],1),`+`))
else RETURN(convert(`Cos/F`(d,`Cos/l`[d,n],1),`+`))
fi
elif isprime(d) then Cos(a) := c
else Cos(a) := `Cos/C`(a)
fi
fi
fi:
end:
Note : Lorsque la procédure
Cos
a été exécutée au moins une fois, l'appel sans paramètre
Cos()
renvoie le détail des calculs intermédiaires précédemment effectués. Plus précisément, l'affichage produit sous une forme lisible la fusion des tables de valeurs particulières (
remember table) des procédures
cos, Cos, et également de la sous-procédure `Cos/F` qui gère les cas des nombres de Fermat : on peut ainsi voir les
étapes intermédiaires générées par le calcul de Cos(
p Pi/
q) où
q est un nombre de Fermat
premier.
Il est déconseillé d'utiliser cette fonctionnalité après l'appel Cos(Pi/257)
pour cause de longueur démesurée de l'affichage.