{递归试快速傅立叶变换(FFT)乘法} #include #include #include #define PI 3.1415926535897932384626 typedef struct ComplexTag { Real R,I; } Complex; long FFTLengthMax; Complex * OmegaFFT; Complex * ArrayFFT0, * ArrayFFT1; Complex * ComplexCoef; double FFTSquareWorstError; long AllocatedMemory; /*初始化*/ void InitializeFFT(long MaxLength) { long i; Real Step; FFTLengthMax = MaxLength; OmegaFFT = (Complex *) malloc(MaxLength/2*sizeof(Complex)); ArrayFFT0 = (Complex *) malloc(MaxLength*sizeof(Complex)); ArrayFFT1 = (Complex *) malloc(MaxLength*sizeof(Complex)); ComplexCoef = (Complex *) malloc(MaxLength*sizeof(Complex)); Step = 2.*PI/(double) MaxLength; for (i=0; 2*iFFTSquareWorstError) FFTSquareWorstError = (tmp-Coef[i])*(tmp-Coef[i]); } } void Convolution(Complex * A, Complex * B, long NFFT, Complex * C) { long i; Real tmpR, tmpI; for (i=0; iFFTLengthMax) { printf("Error, FFT Size is too big in MulWithFFT\n"); return; } FFT(ACoef, ASize, ArrayFFT0, NFFT); FFT(BCoef, BSize, ArrayFFT1, NFFT); Convolution(ArrayFFT0,ArrayFFT1,NFFT,ArrayFFT0); InverseFFT(ArrayFFT0,NFFT,CCoef, ASize+BSize-1); } {递推试快速傅立叶变换(FFT)乘法} Program FFTMul; Uses dos; Const MaxSize=1 shl 4; pi=3.141592653589793238; Bas=100000; LBas=5; invBas=1/Bas; type complex=record {复数类型} i,r:Extended; end; Var i, j, k, n, asize, bSize :Longint; WorstEr :Extended; aCoef, bCoef, ccoef :Array[0..Pred(MaxSize)] of LongInt; {系数} Time1,Time2,th2,tm2,ts2,tms2,th1,tm1,ts1,tms1:Word; {计时用数组} Procedure Initial(Var w:Array of Complex; Var lst:Array of word; n:LongInt); Var i, j, n2, m :LongInt; tmp :Extended; Begin {计算W^i (i=0--n)} i:=0; tmp:=2*pi/n; n2:=n shr 2; For i:=0 to n2 do Begin w[i].i:=sin(tmp*i); w[i].r:=Sqrt(1-sqr(w[i].i)); End; i:=Pred(n2); j:=succ(n2); While i>=0 do Begin w[j].i:= w[i].i; w[j].r:=-w[i].r; Dec(i); Inc(j); End; {计算排序用数组, 如n=8时,lst=(0,4,2,6,1,5,3,7)} n2:=n; lst[0]:=0; m:=1; i:=1; While n2<>1 do Begin n2:=n2 shr 1; m :=m shl 1; j:=0; While i WorstEr Then WorstEr:=Abs((num-TmpR*Bas)-CCoef[i]); End; CCoef[0]:=Round(TmpR); End; Procedure SquareFFT(Const ACoef:Array of LongInt; ASize:LongInt; Var CCoef:Array of LongInt); Var a, b :Array[0..MaxSize] of complex; lst :Array[0..pred(MaxSize)] of Word; w :Array[0..MaxSize shr 1] of complex; n, i :LongInt; logn :Byte; TmpR, num{,maxr,maxi }:Extended; Begin n:=1; logn:=0; while n<(aSize+aSize) do Begin n:=n shl 1; Inc(logn); End; Initial(w,lst,n); for i:=0 to Pred(ASize) do Begin a[i].r:=ACoef[i]; a[i].i:=0; End; for i:=asize to n do Begin a[i].r:=0; a[i].i:=0; End; FFT(a, b, w, lst, n); For i:=0 to pred(n) do Begin a[i].r:=b[i].r*b[i].r - b[i].i*b[i].i; a[i].i:=b[i].r*b[i].i + b[i].i*b[i].r; End; invFFT(a, b, w, lst, n); TmpR:=0; For i:=Pred(n) downto 1 do Begin num :=b[Pred(i)].r+TmpR; TmpR:=Int((num+0.001)*invBas); CCoef[i]:=Round(num-TmpR*Bas); If ABS(num-TmpR*Bas-CCoef[i]) > WorstEr Then WorstEr:=Abs((num-TmpR*Bas)-CCoef[i]); {记录最大误差} End; CCoef[0]:=Round(TmpR); End; Begin Assign(output,'D:\Mulout.txt'); Rewrite(output); Randomize; WorstEr:=0; fillchar(ACoef,sizeof(ACoef),0); fillchar(BCoef,sizeof(BCoef),0); asize:=Maxsize shr 1; BSize:=Maxsize shr 1; For i:=0 to pred(Asize) do ACoef[i]:={Round(Bas-1)}Trunc(random*Bas); Print(ACoef, Asize); Writeln; writeln('*'); For i:=0 to pred(Bsize) do BCoef[i]:={Round(Bas-1)}Trunc(random*Bas); Print(BCoef, BSize); Writeln; Writeln('='); Gettime(th1,tm1,ts1,tms1); SquareFFT(ACoef,ASize,CCoef);{MulFFT(ACoef, ASize, BCoef, BSize, CCoef);} Gettime(th2,tm2,ts2,tms2); Print(CCoef, Asize+BSize); Writeln; Writeln('Worst Error is ',WorstEr); time1:=60*(tm2-tm1)+ts2-ts1; If tms2