Sz\303\241m\303\255t\303\263g\303\251pes sz\303\241melm\303\251letJ\303\241rai AntalEzek a programok csak szeml\303\251ltet\303\251sre szolg\303\241lnak1. A pr\303\255mek eloszl\303\241sa, szit\303\241l\303\241s2. Egyszer\305\261 faktoriz\303\241l\303\241si m\303\263dszerek3. Egyszer\305\261 pr\303\255mtesztel\303\251si m\303\263dszerekLUklbXJvd0c2Iy9JK21vZHVsZW5hbWVHNiJJLFR5cGVzZXR0aW5nR0koX3N5c2xpYkdGJzYjLUkjbWlHRiQ2JVEhRicvJSdpdGFsaWNHUSV0cnVlRicvJSxtYXRodmFyaWFudEdRJ2l0YWxpY0Yn4. Lucas-sorozatok5. Alkalmaz\303\241sok 6. Sz\303\241mok \303\251s polinomok7. Gyors Fourier-transzform\303\241ci\303\263restart;7.1. Polinomszorz\303\241s gyors Fourier-transzform\303\241ci\303\263val.7.2. Gyors Fourier-transzform\303\241ci\303\263 (FFT).#
# This procedure do the bit reversation of the
# number x which is k bit long.
#
reverse:=proc(x,k) local xx,i,y;
xx:=x; y:=0;
for i to k do
if type(xx,odd) then
y:=2*y+1; xx:=(xx-1)/2;
else
y:=2*y; xx:=xx/2;
fi;
od; y; end;#
# This procedure do the complex butterfly operation
# between the two terms A[i] and A[j] of the
# table A. The multiplier is w.
#
cbutterfly:=proc(A,i,j,w) local X,Y;
X:=A[i]; Y:=A[j]*w; A[i]:=X+Y; A[j]:=X-Y;
end;#
# This is a complex FFT procedure.
# It use the butterfly procedure to operate on the vector A.
# The number of rounds is k in the FFT.
# T is a table of the powers of primitive root of unity.
#
cfft:=proc(A,T,k) local l,s,w,t;
for l from 0 to k-1 do
for s from 0 to 2^l-1 do
w:=T[s];
for t from 0 to 2^(k-l-1)-1 do
cbutterfly(A,2^(k-l)*s+t,2^(k-l)*s+t+2^(k-l-1),w);
od;
od;
od; end;#
# The pre procedure do the preparation for the
# table T[0..2^k-1)] of powers of the primitive
# root of unity.
#
pre:=proc(T,k) local i,xx;
Digits:=2*Digits;
for i from 0 to 2^k-1 do
T[i]:=evalf(exp(-2*Pi*I*reverse(i,k)/2^(k+1)));
od;
Digits:=Digits/2;
end;k:=5;
A:=array(0..2^k-1); for i from 0 to 2^k-1 do A[i]:=0 od:
T:=array(0..2^(k-1)-1); pre(T,k-1):A[1]:=1+I; cfft(A,T,5): print(A);for i from 0 to 2^k-1 do
j:=reverse(i,k);
if i<j then x:=A[i]; A[i]:=A[j]; A[j]:=x; fi;
od: print(A);cfft(A,T,5): print(A);for i from 0 to 2^k-1 do
j:=reverse(i,k);
if i<j then x:=A[i]; A[i]:=A[j]; A[j]:=x; fi;
od: print(A);7.3. Inverz FFT.#
# This procedure do the inverse complex butterfly operation
# between the two terms A[i] and A[j] of the
# table A. The power of primitive unity is w.
#
icbutterfly:=proc(A,i,j,w) local X,Y,e;
X:=A[i]+A[j]; Y:=A[i]-A[j]; A[i]:=X; A[j]:=Y/w;
end;#
# This procedure is a complex IFFT procedure.
# It use the ibutterfly procedure to operate on the vector A.
# The number of round in the FFT is k and T is a table of the
# powers of primitive root of unity.
#
icfft:=proc(A,T,k) local l,s,w,t;
for l from k-1 to 0 by -1 do
for s from 0 to 2^l-1 do
w:=T[s];
for t from 0 to 2^(k-l-1)-1 do
icbutterfly(A,2^(k-l)*s+t,2^(k-l)*s+t+2^(k-l-1),w);
od;
od;
od; end;for i from 0 to 2^k-1 do A[i]:=0 od:
A[1]:=1+I; cfft(A,T,5): print(A);icfft(A,T,k): print(A);7.4. Szorz\303\241s komplex FFT-vel.#
# The cdigmul procedure do the digit-by-digit
# multiplication of the two numbers after the
# cfft's. The result will be in the first table.
#
cdigmul:=proc(T,S,k) local i;
for i from 0 to 2^k-1 do T[i]:=T[i]*S[i]; od;
end;A:=array(0..2^k-1); for i from 0 to 2^k -1 do A[i]:=0 od:
B:=array(0..2^k-1); for i from 0 to 2^k -1 do B[i]:=0 od:A[0]:=1: A[1]:=1: A[2]:=1: print(A);#
# This is the polynom multiplication, do multiplication or squaring.
# A and B are the two polynomials, the FFT and IFFT use k rounds.
#
polmulcfft:=proc(A,B,k) global T;
if A=B then
cfft(A,T,k);
cdigmul(A,A,k);
icfft(A,T,k);
else
cfft(A,T,k);
cfft(B,T,k);
cdigmul(A,B,k);
icfft(A,T,k);
fi; end;polmulcfft(A,A,k): print(map(x->x/2^k,A));#
# The cfftpre procedure do the preparation for the
# table for cfft, where x is the number, A is the
# table, m the modulus, and k is the number of
# rounds for the cfft, hence the table is 2^k long.
#
cfftpre:=proc(x,A,m,k) local i,xx;
xx:=x;
for i from 0 to 2^k-1 do A[i]:=irem(xx,m,'xx'); od;
end;#
# The cnorm procedure do the normalization
# after the icfft; A is the table, m the modulus,
# and k is the number of rounds for the cfft,
# hence the table is 2^k long. The fraction parts are
# left in the table A.
#
cnorm:=proc(A,m,k) local i,x;
x:=0;
for i from 2^k-1 to 0 by -1 do
A[i]:=A[i]/2^k;
x:=m*x+round(A[i]);
A[i]:=A[i]-round(A[i]);
od; x; end;#
# This is the main procedure, do the multiplication or the squaring.
# a and b are the two numbers, m is the modulus for the preparation.
# The complex FFT and IFFT use k rounds.
#
mulcfft:=proc(a,b,m,k) global A,B,T;
if a=b then
cfftpre(a,A,m,k);
cfft(A,T,k);
cdigmul(A,A,k);
icfft(A,T,k);
cnorm(A,m,k);
else
cfftpre(a,A,m,k);
cfft(A,T,k);
cfftpre(b,B,m,k);
cfft(B,T,k);
cdigmul(A,B,k);
icfft(A,T,k);
cnorm(A,m,k);
fi; end;mulcfft(123456789,987654321,20,5);123456789*987654321;print(A);7.5. Val\303\263s FFT.#
# The CtoR procedure do the conversion from complex
# representation to real representation.
# The result will be in the same table.
#
CtoR:=proc(A,T,k) local i,x,y;
x:=Re(A[0]); y:=Im(A[0]);
A[0]:=2*(x+y)+I*2*(x-y);
x:=Re(A[1]); y:=Im(A[1]);
A[1]:=2*x-I*2*y;
for i to k-1 do CtoRsteps(A,T,2^i); od;
end;#
# The CtoRstep procedure do the conversion from complex
# representation to real representation for one pair
# ll, uu with weight w.
#
CtoRstep:=proc(ll,uu,w) local al,be,ga,de,xi,et,a,b,x,y,u,v;
xi:=Re(w); et:=Im(w);
al:=Re(ll); be:=Im(ll);
ga:=Re(uu); de:=Im(uu);
x:=al+ga; y:=be-de;
a:=al-ga; b:=be+de;
u:=et*b-xi*a; v:=xi*b+et*a;
[x+v+I*(y+u),x-v+I*(u-y)]
end;#
# The CtoRsteps procedure do the conversion from complex
# representation to real representation for one series.
# The index i is the lower index for the first pair.
# The result will be in the same table.
#
CtoRsteps:=proc(A,T,i) local k,j,z;
k:=i; j:=2*i-1;
while j>k do
z:=CtoRstep(A[k],A[j],T[k]); A[k]:=z[1]; A[j]:=z[2]; k:=k+1; j:=j-1;
od; end;#
# The RtoC procedure do the conversion from real
# representation to complex representation.
# The result will be in the same table.
#
RtoC:=proc(A,T,k) local i,x,y;
x:=Re(A[0]); y:=Im(A[0]);
A[0]:=x+y+I*(x-y);
x:=Re(A[1]); y:=Im(A[1]);
A[1]:=2*x-I*2*y;
for i to k-1 do RtoCsteps(A,T,2^i); od;
end;#
# The RtoCstep procedure do the conversion from real representation
# to complex representation for one pair ll, uu using weight w.
#
RtoCstep:=proc(ll,uu,w) local al,be,ga,de,xi,et,a,b,x,y,u,v;
xi:=Re(w); et:=Im(w);
al:=Re(ll); be:=Im(ll);
ga:=Re(uu); de:=Im(uu);
x:=al+ga; y:=be-de;
a:=al-ga; b:=be+de;
u:=xi*a+et*b; v:=xi*b-et*a;
[x-v+I*(u+y),x+v+I*(u-y)]
end;#
# The RtoCsteps procedure do the conversion from real
# representation to complex representation for one series.
# The index i is the lower index for the first pair.
# The result will be in the same table.
#
RtoCsteps:=proc(A,T,i) local k,j,z;
k:=i; j:=2*i-1;
while j>k do
z:=RtoCstep(A[k],A[j],T[k]);
A[k]:=z[1]; A[j]:=z[2]; k:=k+1; j:=j-1; od;
end;7.6. Szorz\303\241s komplex FFT-vel a gyakorlatban.#
# The srfftpre procedure do the preparation for the
# signed table for rfft; x is the number, A is the
# table, m the even positive modulus, and k is the
# number of rounds for the rfft, hence the table is 2^k long.
# All number is multipled by the factor f.
#
srfftpre:=proc(x,A,m,k,f) local i,c,d,xx;
xx:=x; c:=0;
for i from 0 to 2^k-1 do
d:=irem(xx,m,'xx');
if d>=m/2 then d:=d-m+c; c:=1; else d:=d+c; c:=0; fi;
A[i]:=evalf(d*f);
d:=irem(xx,m,'xx');
if d>=m/2 then d:=d-m+c; c:=1; else d:=d+c; c:=0; fi;
A[i]:=A[i]+I*evalf(d*f);
od; end;#
# The rnorm procedure do the normalization after the irfft.
# A is the table, m the modulus, and k is the number of
# rounds for the rfft, hence the table is 2^k long.
# Before conversion, all entry in A multiplied by the factor f.
# The fraction parts are left in the table A.
#
rnorm:=proc(A,m,k,f) local i,x;
x:=0;
for i from 2^k-1 to 0 by -1 do
A[i]:=evalf(A[i]*f);
x:=m*x+round(Im(A[i]));
A[i]:=A[i]-I*round(Im(A[i]));
x:=m*x+round(Re(A[i]));
A[i]:=A[i]-round(Re(A[i]));
od; x; end;#
# The rdigmul procedure do the digit-by-digit
# multiplication of the two numbers after the
# rfft's. The result will be in the first table.
#
rdigmul:=proc(A,B,k) local i;
A[0]:=Re(A[0])*Re(B[0])+I*Im(A[0])*Im(B[0]);
for i from 1 to 2^k-1 do A[i]:=A[i]*B[i]; od;
end;#
# This is the main procedure, do the multiplication
# or the squaring using real FFT and IFFF.
# a and b are the two numbers, m is the modulus for
# the preparation. The FFT and IFFT use k rounds.
#
mulrfft:=proc(a,b,m,k) local f1,f2,r; global A,B,T;
if type(k,odd) then
f1:=2^(-(k+1)/2-HWS);
f2:=2^(2*HWS-2);
else
f1:=2^(-k/2-HWS);
f2:=2^(2*HWS-3);
fi;
if a=b then
srfftpre(a,A,m,k,f1); print(A);
cfft(A,T,k); print(A);
CtoR(A,T,k); print(A);
rdigmul(A,A,k); print(A);
RtoC(A,T,k); print(A);
icfft(A,T,k); print(A);
rnorm(A,m,k,f2);
else
srfftpre(a,A,m,k,f1);
cfft(A,T,k);
CtoR(A,T,k);
srfftpre(b,B,m,k,f1);
cfft(B,T,k);
CtoR(B,T,k);
rdigmul(A,B,k);
RtoC(A,T,k);
icfft(A,T,k);
rnorm(A,m,k,f2);
fi; end;HWS:=16; k:=5;
A:=array(0..2^k-1); B:=array(0..2^k-1);
T:=array(0..2^k-1); pre(T,k):mulrfft(123456789,987654321,18,5);123456789*987654321;print(A);7.7. P\303\251lda.HWS:=16; k:=15;
A:=array(0..2^k-1); B:=array(0..2^k-1);
T:=array(0..2^k-1); pre(T,k):mulrfft(123456789,987654321,16,5);123456789*987654321;7.8. FFT v\303\251ges testek felett.7.9. Fermat-sz\303\241m transzform\303\241ci\303\263.#
# This procedure adds 1 to the number represented by the
# bit vector b (used in reverse bit order) on length k.
#
incrementreverse:=proc(b,k) local i,c;
c:=b;
for i to k do if c[i]=0 then c[i]:=1; return c; else c[i]:=0 fi;
od; c; end;#
# This procedure convert the bits in interval II of the
# bit vector b. The bit b[1] represents the highest bit,
# 2^(m-2+op(1,II)), usually 2^(m-1).
#
convertreverse:=proc(b,m,II) local i,lw; lw:=0;
for i from op(1,II) to op(2,II) do
lw:=lw+b[i]*2^(m-1-i+op(1,II))
od; lw; end;#
# This procedure do a Fermat FFT round modulo 2^(2^m)+1 on
# array A having 2^n elements. The siccor size is 2^k and
# the weights are get from the conversion of bits in interval II
# from a counter starting with zero and incremented after
# each butterfly sequence.
#
ffftround:=proc(A,n,m,k,II) local i,j,x,y,w,b;
j:=2^k; b:=[0$i=1..m+1];
while j<2^n do
w:=2^convertreverse(b,m,II); b:=incrementreverse(b,m+1);
for i from j-2^k while i<j do
x:=A[i]; y:=A[i+2^k];
A[i]:=x+w*y mod (2^(2^m)+1); A[i+2^k]:=x-w*y mod (2^(2^m)+1);
od; j:=j+2^(k+1);
od; end;#
# This procedure do a Fermat IFFT round modulo 2^(2^m)+1 on
# array A having 2^n elements. The siccor size is 2^k and
# the weights are get from the conversion of bits in interval II
# from a counter starting with zero and incremented after
# each butterfly sequence.
#
iffftround:=proc(A,n,m,k,II) local i,j,x,y,w,b;
j:=2^k; b:=[0$i=1..m+1];
while j<2^n do
w:=2^convertreverse(b,m,II); b:=incrementreverse(b,m+1);
for i from j-2^k while i<j do
x:=A[i]; y:=A[i+2^k];
A[i]:=x+y mod (2^(2^m)+1); A[i+2^k]:=(x-y)/w mod (2^(2^m)+1);
od; j:=j+2^(k+1);
od; end;#
# This is the digit-by-digit multiplication modulo 2^(2^m)+1
# of arrays A and B having 2^n elements.
#
fdigmul:=proc(A,B,n,m) local i;
for i from 0 to 2^n-1 do A[i]:=A[i]*B[i] mod (2^(2^m)+1) od;
end;#
# This procedure divides by 2^k modulo 2^(2^m)+1
# all elements of array A having 2^n elements.
#
fshift:=proc(A,n,m,k) local i,r;
r:=1/2^k mod (2^(2^m)+1);
for i from 0 to 2^n-1 do A[i]:=A[i]*r mod (2^(2^m)+1) od;
end;#
# This procedure multiplies by sqrt(2) modulo 2^(2^m)+1
# all odd-indexed elements in the upper half of
# array A having 2^n elements.
#
mulsqrt:=proc(A,n,m) local i,sqrttwo;
sqrttwo:=2^(3*2^(m-2))-2^(2^(m-2));
for i from 2^(n-1)+1 to 2^n-1 by 2 do
A[i]:=A[i]*sqrttwo mod (2^(2^m)+1)
od; end;#
# This procedure divides by sqrt(2) modulo 2^(2^m)+1
# all odd-indexed elements in the upper half of
# array A having 2^n elements.
#
divsqrt:=proc(A,n,m) local i,sqrthalf;
sqrthalf:=1/(2^(3*2^(m-2))-2^(2^(m-2))) mod (2^(2^m)+1);
for i from 2^(n-1)+1 to 2^n-1 by 2 do
A[i]:=A[i]*sqrthalf mod (2^(2^m)+1)
od; end;#
# This procedure do Fermat FFT modulo 2^(2^m)+1
# for array A having 2^n elements.
#
ffft:=proc(A,n,m) local i;
for i from 0 to n-2 do ffftround(A,n,m,n-1-i,1..i) od;
if m>=n-1 then
ffftround(A,n,m,0,1..n-1)
else
mulsqrt(A,n,m); ffftround(A,n,m,0,1..n-2)
fi; end;#
# This procedure do Fermat IFFT modulo 2^(2^m)+1
# for array A having 2^n elements.
#
iffft:=proc(A,n,m) local i;
if m>=n-1 then
iffftround(A,n,m,0,1..n-1)
else
iffftround(A,n,m,0,1..n-2); divsqrt(A,n,m)
fi;
for i from n-2 to 0 by -1 do iffftround(A,n,m,n-1-i,1..i) od;
end;#
# This procedure do multiplication or squaring using Fermat FFT
# and IFFT modulo 2^(2^m)+1 for array having 2^n elements.
# 2^(m-1)-k bits is in one array element.
#
ffftmul:=proc(a,b,n,m) local i,c,A,B;
if a=b then
A:=Array(0..2^n-1,convert(a,base,2^(2^(m-1)-k)));
ffft(A,n,m);
fdigmul(A,A,n,m);
iffft(A,n,m);
fshift(A,n,m,n);
c:=0; for i from 0 to 2^n-1 do c:=c+(2^(2^(m-1)-k))^i*A[i] od;
else
A:=Array(0..2^n-1,convert(a,base,2^(2^(m-1)-k)));
ffft(A,n,m);
B:=Array(0..2^n-1,convert(b,base,2^(2^(m-1)-k)));
ffft(B,n,m);
fdigmul(A,B,n,m);
iffft(A,n,m);
fshift(A,n,m,n);
c:=0; for i from 0 to 2^n-1 do c:=c+(2^(2^(m-1)-k))^i*A[i] od;
fi; c; end;n:=6; m:=4; k:=4; ffftmul(123456789,987654321,n,m,k);123456789*987654321;7.10. Sch\303\266nhage-Strassen-f\303\251le gyorsszorz\303\263 algoritmus.7.11. P\303\251lda.7.12. Ritka polinomok es ritka sz\303\241mok.7.13. Feladat.7.14. Oszt\303\241s, polinomoszt\303\241s.7.15. Polinom ki\303\251rt\303\251kel\303\251se tetsz\305\221leges helyeken.7.16. Interpol\303\241ci\303\263.7.17. Feladat.7.18. Feladat.7.19. Feladat.8. Elliptikus f\303\274ggv\303\251nyek9. Sz\303\241mol\303\241s elliptikus g\303\266rb\303\251ken10. Faktoriz\303\241l\303\241s elliptikus g\303\266rb\303\251kkel11. Pr\303\255mteszt elliptikus g\303\266rb\303\251kkel12. Polinomfaktoriz\303\241l\303\241s13. Az AKS-teszt14. A szita m\303\263dszerek alapjaiLUklbXJvd0c2Iy9JK21vZHVsZW5hbWVHNiJJLFR5cGVzZXR0aW5nR0koX3N5c2xpYkdGJzYjLUkjbWlHRiQ2JVEhRicvJSdpdGFsaWNHUSV0cnVlRicvJSxtYXRodmFyaWFudEdRJ2l0YWxpY0Yn