...

Introduzione a PARI / GP - Dipartimento di Matematica

by user

on
Category: Documents
19

views

Report

Comments

Transcript

Introduzione a PARI / GP - Dipartimento di Matematica
Università degli studi di
Milano
Dipartimento di Matematica «F. Enriques»
Progetto lauree scientifiche
Laboratorio di crittografia
Introduzione a PARI / GP
pari / gp è una libreria per linguaggi ad alto livello (ad es. C, C++, Pascal, Fortran) ed
una sofisticata calcolatrice programmabile. Le sue caratteristiche principali sono l’essere
un programma libero, la rapidità (da  a  volte più rapido di altri programmi), la
possibilità di usare tipi di dati comuni nell’uso matematico, e l’esteso supporto per la
teoria dei numeri. pari / gp funziona su molte versioni di Unix (inclusi Linux e OS-X) ed
ha un supporto sperimentale per Windows; può essere scaricato liberamente da http:
//pari.math.u-bordeaux.fr
 Iniziamo!
Dopo aver acceso il computer, al prompt, digitiamo gnome e premiamo <invio>. [rimosse le istruzioni su nome utente e password da utilizzare sui terminali del laboratorio del
dipartimento] Una volta finito di caricare l’ambiente grafico, aprite il terminale, digitate
gp e poi di nuovo <invio>. Dovrebbe comparirvi un ?
Scrivete 2+2 e poi premete <invio> (questa è l’ultima volta che lo specificherò). Dovreste vedere:
? 2+2
%1 = 4
?
%1 significa che questo è il primo risultato, e che è uguale a . Forse siete abituati a
terminare ogni riga col ;
? 2+2;
?
Cos’è successo?!? Qui il segno ; serve per separare due istruzioni, e come effetto collaterale non stampa il risultato: è utile se abbiamo dei numeri giganteschi, ma vedremo più
avanti. . .
Proviamo ora qualche altra operazione
? 12-3
%3 = 9
? 1-7*4+2
%4 = -25
? 8/2
%5 = 4
Progetto lauree scientifiche
Laboratorio di crittografia
? 3/2
%6 = 3/2
Notiamo che pari / gp usa tranquillamente le frazioni.
? 2^5
%7 = 32
? (-1/2)^3
%8 = -1/8
? %^(1/3)
%9 = 0.2500000000000000000000000000 + 0.4330127018922193233818615853*I
?
La prima operazione è un elevamento a potenza. Nel secondo caso è necessario usare le
parentesi. Il terzo caso è un po’ strano: il segno % indica l’ultimo risultato, in questo caso
−/. L’elevamento alla potenza /, come sapete, corrisponde all’estrazione di radice
cubica: ma cos’è il risultato? Be’, se provate ad elevarlo alla terza otteniamo:
? %^3
%10 = -0.1250000000000000000000000000 + 4.73316542 E-30*I
Se guardate attentamente, noterete che questo risultato è un’approssimazione reale di
−/ più un numero molto piccolo per I: pari / gp ha calcolato una radice complessa di
−/, la cui terza potenza è ancora un numero complesso. Ma procediamo oltre: il resto
della divisione fra a e b è indicato così:
? 13%3
%11 = 1
? 13%5
%12 = 3
divrem
Se vogliamo conoscere sia il quoziente che il resto, usiamo la funzione divrem
? divrem(13,5)
%13 = [2, 3]~
gcd
bezout
Per aiutarci a comprendere il significato del risultato, scriviamo ?divrem. Scopriamo così
che [2,3]~ è un vettore colonna (la tilde indica che è stato scritto come riga). Per verificare provate a calcolare: ∗+. Altre funzioni utili sono gcd e bezout: provate a scoprire
cosa fanno.
Esercizio . Calcolate: ( −)/; +  ; MCD(, ); MCD(, ); trovate ora x, y ∈ Z tali
che MCD(, ) = x + y; idem per MCD(, ) = x + y.
 Moduli
Se vogliamo calcolare  mod , cioè la classe di resto di  modulo , possiamo fare
così:

Introduzione a PARI / GP
? 3^123
%14 = 48519278097689642681155855396759336072749841943521979872827
? % %17
%15 = 7
Proviamo con numeri ancora più grossi:  mod 
? 1435^467
%16 = 1777615382246166178183410278313640776056638142669953819537560638
4440658254724148151873065978590741557038852046453447172605903966524399
3282526617824036893640611161880745082059189693057609522158693080432443
9998398836975623428194912933179425712057461415130444524580749980805005
8509867127417336379682306411510441154004626826306562934477025796842756
6122648440668126135687775339293954033451823669552803135626101640029821
6739165699202497760856493541256340994201027150885944297925893515077793
7150399397095459918937650074934176426881767936613106102510426319567001
0994996371452394390119908181445633782348077580430491526771051683640672
4971264931807444956409070109368165019674558692845735859148710514555170
4827720056862222151684171697723531459399418362761150767740201368452163
3098976436853213188768138997862446878783257000042344671019537172694332
9829289524670282277082018477544775532337203726689402339317171851051173
1888675886503564085228875554538859323656362277372494014604537852664463
5722523401406637257509915035234834445920788182674320824257475653017329
3786580558425511337908137272201426637018341483418690947751236778336073
8670206740415366955901542770191159203252282313353796838073742788507484
7935413477057905621326271496461158235016122932938889520896833009552098
6616174185149395675553335866572964314749067105608434617808430924522024
3935739714650595444706938780982421686356526341266574945028849139621682
1878672534002731178309209364946031679431334704410971880861325189471244
81201171875
? %%147
%17 = 49
Umph! Forse era meglio usare il ;
? 1435^467;
? % %147
%19 = 49
Meglio, ma se usassimo numeri ancora un poco più grandi, inizieremmo a trovare cose troppo grandi, e avremmo dei problemi. D’altro canto a noi non serve veramente
calcolare  come numero intero: sarebbe sufficiente ridurre modulo  ad ogni
passaggio.
? Mod(1435,147)
%20 = Mod(112, 147)

Progetto lauree scientifiche
Laboratorio di crittografia
? %^467
%21 = Mod(49, 147)
Mod
nextprime
Mod crea un intero modulare: Mod(1435,147) è la classe di resto di  mod . Notiamo che  ≡  mod , cioè Mod(1435,147) e Mod(112,147) sono la stessa classe di
resto.
Vediamo un altro esempio. Attiviamo ora il timer dando l’istruzione #, cerchiamo un
primo grande con nextprime, e poi confrontiamo i due modi per svolgere un elevamento a potenza.
? #
timer = 1 (on)
? p=nextprime(10^5)
time = 0 ms.
%22 = 100003
? e=8234325
time = 0 ms.
%23 = 8234325
? 2^e %p
time = 16 ms.
%24 = 6033
? Mod(2,p)^e
time = 0 ms.
? #
timer = 0 (off)
lift
Variabili
Un’ultra istruzione utile è lift: dato una classe di resto modulo n, restituisce l’unico
intero nell’intervallo [, n) della classe:provate a giocarci.
Vediamo ora come assegnare un nome agli oggetti
? a=Mod(1435,147)
%25 = Mod(112, 147)
a può ora essere usato al posto di Mod(1435,147)
? a+Mod(3,147)
%26 = Mod(115, 147)
? a+3
%27 = Mod(115, 147)
? 2*a
%28 = Mod(77, 147)
? a^2
%29 = Mod(49, 147)
? a^(-1)
*** impossible inverse modulo: Mod(7, 147).
? (a+3)^(-1)
%30 = Mod(124, 147)

Introduzione a PARI / GP
Non siamo riusciti a calcolare a − : infatti MCD(a, ) = , per cui non può esistere b tale
che ab ≡  mod . Se volessimo sapere quante sono le classi di resto invertibili mod ,
basterebbe usare la funzione eulerphi, che calcola la φ di Eulero:
eulerphi
? eulerphi(147)
%31 = 84
 Programmazione
Abbiamo visto come creare delle variabili. Vediamo ora qualche semplice modo per programmare pari / gp.
Il modo più semplice per definire una funzione è il seguente: f(x)=x^2-1. Ora possiamo calcolare f (x) per un qualsiasi x
Funzioni
? f(1)
%32 = 0
? f(-2/3)
%33 = -5/9
? f(4.3)
%34 = 17.48999999999999999999999999
? f(a)
%35 = Mod(48, 147)
Funzioni più complicate vengono definite in modo simile: ogni istruzione è separata da
; e il risultato della funzione è il risultato dell’ultima assegnazione
? modinv(a,n)=local(phi);phi=eulerphi(n);Mod(a,n)^(phi-1)
? modinv(115,147)
%36 = Mod(124, 147)
? modinv(112,147)
%37 = Mod(49, 147)
? %*112
%38 = Mod(49, 147)
L’istruzione local serve per segnalare che phi è una variabile locale; le variabili a ed n lo
sono automaticamente per come è definita la funzione modinv. Ricordiamo che a φ(n) ≡
 mod n per ogni a relativamente primo ad n, e che quindi a φ(n)− ≡ a − mod n. Sopra
verifichiamo come questo non sia vero se a ed n non sono relativamente primi.
Supponiamo ora di voler vedere com’è fatta la funzione inversa: prendiamo n = : è un
numero primo, per cui ogni classe di resto — tranne quella nulla — è invertibile.
? n=5
%39 = 5
? for(i=1,n-1,a=Mod(i,n);b=a^-1;print(a,"\t",b))
Mod(1, 5)
Mod(1, 5)
Mod(2, 5)
Mod(3, 5)

local
Progetto lauree scientifiche
Mod(3, 5)
Mod(4, 5)
for
print
Laboratorio di crittografia
Mod(2, 5)
Mod(4, 5)
Vi consiglio di controllare la definizione di for e di print. L’istruzione "\t" rappresenta
un tabulatore. Analogamente
? for(i=1,n-1,a=Mod(i,n);b=f(a);print(a,"\t",b))
Mod(1, 5)
Mod(0, 5)
Mod(2, 5)
Mod(3, 5)
Mod(3, 5)
Mod(3, 5)
Mod(4, 5)
Mod(0, 5)
if
Supponiamo di voler trovare, se esiste, un x tale che f (x) ≡  mod : stampare l’intera
tabella porterebbe via troppo spazio, e poi sarebbe scomodo scorrerla alla ricerca del
valore cercato. Usiamo un test condizionale: l’istruzione if
? n=147;for(i=0,n-1,a=Mod(i,n);b=f(a);if(b==Mod(1,n),print(a,"\t",b)))
Non esiste un tale x! Proviamo a risolvere l’equazione f (x) = :
? n=147;for(i=0,n-1,a=Mod(i,n);b=f(a);if(b==Mod(3,n),print(a,"\t",b)))
Mod(2, 147)
Mod(3, 147)
Mod(47, 147)
Mod(3, 147)
Mod(100, 147)
Mod(3, 147)
Mod(145, 147)
Mod(3, 147)
Notiamo come ci siano quattro soluzioni ad un’equazione di secondo grado!
Esercizio . Sia f (x) = x  − x  + . Calcolate il valore di f per ogni classe di resto modulo
. Cercate poi eventuali soluzioni alle equazioni f (x) ≡ , f (x) ≡ −, f (x) ≡  mod .

Fly UP