Реализация БПФ в поле вычетов по модулю p (А.Ворожцов)
Здесь приведён код быстрого преобразование Фурье (функция fft2) в поле вычетов по некоторому модулю MOD. Этот код может быть использован для
- Быстрого умножения длинных чисел
- Умножения многочленов с целыми коэффициентами.
Artem Voroztsov - 11 Mar 2005
#define LT unsigned long
const LT N = 0x00000100; // длина вектора
const LT NX = 0x000000ff; // N - 1
const LT MOD = 0x00000101; // модуль
LT Z = 5; // Z^n должно пробегать все не нулевые остатки по модулю MOD
LT *ZI; // ZI[n] = (z^n) mod MOD
// Долгий вариант прямого преобразования Фурье
void ft(LT* y, LT* c)
{
long i, j;
for(i = 0; i < N ; i++)
for(c[i] = 0, j = 0; j < N ; j++ )
c[i] = (c[i] + ZI[( i * j) & NX ] * y[j] ) % MOD;
}
// Долгий вариант обратного преобразования Фурье
void ift(LT* c, LT* y)
{
long i,j;
for(i = 0 ; i < N ; i++)
for(y[i] = 0, j = 0; j < N ; j++)
y[i] = (y[i] + MOD * MOD - ZI[ (-i*j) & NX ] * c[j]) % MOD;
}
// Быстрое преобразование фурье
// I == 1 — прямое
// I == -1 — обратное
void fft2(LT *x, int I)
{
register LT t1,t2,u;
register long i,j,p,l,zl,L,BL;
L = N; BL = I;
while(L >= 2){
l = L/2; u = ZI[0]; zl = 0;
for(j = 0; j < l; j++, u = ZI[ (zl += BL) & NX])
for(i = j; i < N ; i += L){
p = i+l;
t1 = (x[i] + x[p]) % MOD;
t2 = (MOD + x[i] - x[p]) % MOD;
x[p] = (t2 * u) % MOD;
x[i] = t1 % MOD;
}
L /= 2; BL *= 2;
}
// Далее делаем перестановку элементов массива x
// x[i] --> x[ REVERSEBITS(i) ]
j = 0;
for(i=0; i < NX ; i++){
if(i > j){ t1=x[j]; x[j]=x[i]; x[i]=t1;}
l = N/2;
while(j >=l){ j-=l; l /= 2;}
j+=l;
}
}
int main()
{
int i;
ZI = (LT*) malloc(N * sizeof(LT));
for(ZI[0]=1,i=1 ; i < N ; i++)
ZI[i] = ( Z * ZI[i-1] ) % MOD;
free(ZI);
}