void Cmodulus::FFT(vec_long &y, const ZZX& x) const { FHE_TIMER_START; zz_pBak bak; bak.save(); context.restore(); zz_pX& tmp = Cmodulus::getScratch_zz_pX(); { FHE_NTIMER_START(FFT_remainder); conv(tmp,x); // convert input to zpx format } if (!ALT_CRT && zMStar->getPow2()) { // special case when m is a power of 2 long k = zMStar->getPow2(); long phim = (1L << (k-1)); long dx = deg(tmp); long p = zz_p::modulus(); const zz_p *powers_p = (*powers).rep.elts(); const mulmod_precon_t *powers_aux_p = powers_aux.elts(); y.SetLength(phim); long *yp = y.elts(); zz_p *tmp_p = tmp.rep.elts(); for (long i = 0; i <= dx; i++) yp[i] = MulModPrecon(rep(tmp_p[i]), rep(powers_p[i]), p, powers_aux_p[i]); for (long i = dx+1; i < phim; i++) yp[i] = 0; FFTFwd(yp, yp, k-1, *zz_pInfo->p_info); return; } zz_p rt; conv(rt, root); // convert root to zp format BluesteinFFT(tmp, getM(), rt, *powers, powers_aux, *Rb); // call the FFT routine // copy the result to the output vector y, keeping only the // entries corresponding to primitive roots of unity y.SetLength(zMStar->getPhiM()); long i,j; long m = getM(); for (i=j=0; i<m; i++) if (zMStar->inZmStar(i)) y[j++] = rep(coeff(tmp,i)); }
void Cmodulus::FFT_aux(vec_long &y, zz_pX& tmp) const { if (zMStar->getPow2()) { // special case when m is a power of 2 long k = zMStar->getPow2(); long phim = (1L << (k-1)); long dx = deg(tmp); long p = zz_p::modulus(); const zz_p *powers_p = (*powers).rep.elts(); const mulmod_precon_t *powers_aux_p = powers_aux.elts(); y.SetLength(phim); long *yp = y.elts(); zz_p *tmp_p = tmp.rep.elts(); for (long i = 0; i <= dx; i++) yp[i] = MulModPrecon(rep(tmp_p[i]), rep(powers_p[i]), p, powers_aux_p[i]); for (long i = dx+1; i < phim; i++) yp[i] = 0; #ifdef FHE_OPENCL AltFFTFwd(yp, yp, k-1, *altFFTInfo); #else FFTFwd(yp, yp, k-1, *zz_pInfo->p_info); #endif return; } zz_p rt; conv(rt, root); // convert root to zp format BluesteinFFT(tmp, getM(), rt, *powers, powers_aux, *Rb); // call the FFT routine // copy the result to the output vector y, keeping only the // entries corresponding to primitive roots of unity y.SetLength(zMStar->getPhiM()); long i,j; long m = getM(); for (i=j=0; i<m; i++) if (zMStar->inZmStar(i)) y[j++] = rep(coeff(tmp,i)); }
/*! Forward real FFT */ void Fft::FftRealCcs(audio_real *X, audio_real *Sp) { FFTFwd(X, Sp, m_Spec, m_Buf); }
int main() { #ifdef NTL_SPMM_ULL if (sizeof(NTL_ULL_TYPE) < 2*sizeof(long)) { printf("999999999999999 "); print_flag(); return 0; } #endif long n, k; n = 200; k = 10*NTL_ZZ_NBITS; ZZ p; RandomLen(p, k); ZZ_p::init(p); // initialization ZZ_pX f, g, h, r1, r2, r3; random(g, n); // g = random polynomial of degree < n random(h, n); // h = " " random(f, n); // f = " " SetCoeff(f, n); // Sets coefficient of X^n to 1 // For doing arithmetic mod f quickly, one must pre-compute // some information. ZZ_pXModulus F; build(F, f); PlainMul(r1, g, h); // this uses classical arithmetic PlainRem(r1, r1, f); MulMod(r2, g, h, F); // this uses the FFT MulMod(r3, g, h, f); // uses FFT, but slower // compare the results... if (r1 != r2) { printf("999999999999999 "); print_flag(); return 0; } else if (r1 != r3) { printf("999999999999999 "); print_flag(); return 0; } double t; long i, j; long iter; const int nprimes = 30; const long L = 12; const long N = 1L << L; long r; for (r = 0; r < nprimes; r++) UseFFTPrime(r); vec_long aa[nprimes], AA[nprimes]; for (r = 0; r < nprimes; r++) { aa[r].SetLength(N); AA[r].SetLength(N); for (i = 0; i < N; i++) aa[r][i] = RandomBnd(GetFFTPrime(r)); FFTFwd(AA[r].elts(), aa[r].elts(), L, r); FFTRev1(AA[r].elts(), AA[r].elts(), L, r); } iter = 1; do { t = GetTime(); for (j = 0; j < iter; j++) { for (r = 0; r < nprimes; r++) { long *AAp = AA[r].elts(); long *aap = aa[r].elts(); long q = GetFFTPrime(r); mulmod_t qinv = GetFFTPrimeInv(r); FFTFwd(AAp, aap, L, r); FFTRev1(AAp, aap, L, r); for (i = 0; i < N; i++) AAp[i] = NormalizedMulMod(AAp[i], aap[i], q, qinv); } } t = GetTime() - t; iter = 2*iter; } while(t < 1); iter = iter/2; iter = long((1.5/t)*iter) + 1; double tvec[5]; long w; for (w = 0; w < 5; w++) { t = GetTime(); for (j = 0; j < iter; j++) { for (r = 0; r < nprimes; r++) { long *AAp = AA[r].elts(); long *aap = aa[r].elts(); long q = GetFFTPrime(r); mulmod_t qinv = GetFFTPrimeInv(r); FFTFwd(AAp, aap, L, r); FFTRev1(AAp, aap, L, r); for (i = 0; i < N; i++) AAp[i] = NormalizedMulMod(AAp[i], aap[i], q, qinv); } } t = GetTime() - t; tvec[w] = t; } t = clean_data(tvec); t = floor((t/iter)*1e13); if (t < 0 || t >= 1e15) printf("999999999999999 "); else printf("%015.0f ", t); printf(" [%ld] ", iter); print_flag(); return 0; }