⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lzz_px.cpp

📁 数值算法库for Windows
💻 CPP
📖 第 1 页 / 共 5 页
字号:
      for (i = m+1; i >= 1; i--)
         hh[i] = aa[i-1];
      clear(hh[0]);
   }
   else {
      h.rep.SetLength(n);
      hh = h.rep.elts();
      aa = a.rep.elts();
      ff = f.rep.elts();
      negate(z, aa[n-1]);
      if (!IsOne(ff[n]))
         div(z, z, ff[n]);
      for (i = n-1; i >= 1; i--) {
         mul(t, z, ff[i]);
         add(hh[i], aa[i-1], t);
      }
      mul(hh[0], z, ff[0]);
      h.normalize();
   }
}

void MulByXMod(zz_pX& h, const zz_pX& a, const zz_pX& f)
{
   if (&h == &f) {
      zz_pX hh;
      MulByXModAux(hh, a, f);
      h = hh;
   }
   else
      MulByXModAux(h, a, f);
}


void random(zz_pX& x, long n)
{
   long i;

   x.rep.SetLength(n);

   for (i = 0; i < n; i++)
      random(x.rep[i]); 

   x.normalize();
}





void fftRep::SetSize(long NewK)
{
   if (NewK < -1 || NewK >= NTL_BITS_PER_LONG-1)
      Error("bad arg to fftRep::SetSize()");

   if (NewK <= MaxK) {
      k = NewK;
      return;
   }

   if (NumPrimes != zz_pInfo->NumPrimes)
      Error("fftRep: inconsistent use");

   long i, n;
 
   if (MaxK != -1) 
      for (i = 0; i < zz_pInfo->NumPrimes; i++) 
         free(tbl[i]);

   n = 1L << NewK;

   for (i = 0; i < zz_pInfo->NumPrimes; i++) {
      if ( !(tbl[i] = (long *) malloc(n * (sizeof (long)))) )
         Error("out of space in fftRep::SetSize()");
   }

   k = MaxK = NewK;
}

fftRep::fftRep(const fftRep& R)
{
   k = MaxK = R.k;
   NumPrimes = R.NumPrimes;

   if (k < 0) return;

   long i, j, n;

   n = 1L << k;

   for (i = 0; i < NumPrimes; i++) {
      if ( !(tbl[i] = (long *) malloc(n * (sizeof (long)))) )
         Error("out of space in fftRep");

      for (j = 0; j < n; j++)
         tbl[i][j] = R.tbl[i][j];
   }
}

fftRep& fftRep::operator=(const fftRep& R)
{
   if (this == &R) return *this;

   if (NumPrimes != R.NumPrimes)
      Error("fftRep: inconsistent use");

   if (R.k < 0) {
      k = -1;
      return *this;
   }

   if (R.k > MaxK) {
      long i, n;

      if (MaxK != -1) {
         for (i = 0; i < NumPrimes; i++)
            free(tbl[i]);
      }
  
      n = 1L << R.k;
  
      for (i = 0; i < NumPrimes; i++) {
         if ( !(tbl[i] = (long *) malloc(n * (sizeof (long)))) )
            Error("out of space in fftRep");
      }

      k = MaxK = R.k;
   }
   else {
      k = R.k;
   }

   long i, j, n;

   n = 1L << k;

   for (i = 0; i < NumPrimes; i++)
      for (j = 0; j < n; j++)
         tbl[i][j] = R.tbl[i][j];

   return *this;
}



fftRep::~fftRep()
{
   if (MaxK == -1)
      return;

   for (long i = 0; i < NumPrimes; i++)
      free(tbl[i]);
}



static vec_long FFTBuf;




void FromModularRep(zz_p& x, long *a)
{
   long n = zz_pInfo->NumPrimes;
   long p = zz_pInfo->p;
   double pinv = zz_pInfo->pinv;
   long q, s, t;
   long i;
   double y;

#if QUICK_CRT
   y = 0;
   for (i = 0; i < n; i++)
      y = y + ((double) a[i])*zz_pInfo->x[i];

   y = y - long(y*pinv)*p;
   y = y + 0.5;
   while (y >= p) y -= p;
   while (y < 0) y += p;
   q = long(y);
#else
   long Q, r;
   double qq;

   y = 0;
   qq = 0;

   for (i = 0; i < n; i++) {
      r = MulDivRem(Q, a[i], zz_pInfo->u[i], FFTPrime[i], zz_pInfo->x[i]);
      qq = qq + Q;
      y = y + r*FFTPrimeInv[i];
   }

   y = qq + long(y + 0.5);
   y = y - long(y*pinv)*p;
   while (y >= p) y -= p;
   while (y < 0) y += p;
   q = long(y); 

#endif

   t = 0;
   for (i = 0; i < n; i++) {
      s = MulMod(a[i], zz_pInfo->CoeffModP[i], p, pinv);
      t = AddMod(t, s, p);
   }
      

   s = MulMod(q, zz_pInfo->MinusMModP, p, pinv);
   t = AddMod(t, s, p);
   x.LoopHole() = t;
}


void TofftRep(fftRep& y, const zz_pX& x, long k, long lo, long hi)
// computes an n = 2^k point convolution.
// if deg(x) >= 2^k, then x is first reduced modulo X^n-1.
{
   long n, i, j, m, j1;
   vec_long& s = FFTBuf;;
   zz_p accum;
   long NumPrimes = zz_pInfo->NumPrimes;


   if (k > zz_pInfo->MaxRoot) 
      Error("Polynomial too big for FFT");

   if (lo < 0)
      Error("bad arg to TofftRep");

   hi = min(hi, deg(x));

   y.SetSize(k);

   n = 1L << k;

   m = max(hi-lo + 1, 0);

   const zz_p *xx = x.rep.elts();

   long index = zz_pInfo->index;

   if (index >= 0) {
      for (j = 0; j < n; j++) {
         if (j >= m) {
            y.tbl[0][j] = 0;
         }
         else {
            accum = xx[j+lo];
            for (j1 = j + n; j1 < m; j1 += n)
               add(accum, accum, xx[j1+lo]);
            y.tbl[0][j] = rep(accum);
         }
      }
   }
   else {
      for (j = 0; j < n; j++) {
         if (j >= m) {
            for (i = 0; i < NumPrimes; i++)
               y.tbl[i][j] = 0;
         }
         else {
            accum = xx[j+lo];
            for (j1 = j + n; j1 < m; j1 += n)
               add(accum, accum, xx[j1+lo]);
            for (i = 0; i < NumPrimes; i++) {
               long q = FFTPrime[i];
               long t = rep(accum);
               if (t >= q) t -= q;
               y.tbl[i][j] = t;
            }
         }
      }
   }
   

   s.SetLength(n);
   long *sp = s.elts();

   if (index >= 0) {
      long *Root = &RootTable[index][0];
      long *yp = &y.tbl[0][0];
      FFT(sp, yp, y.k, FFTPrime[index], Root);
      for (j = 0; j < n; j++)
         yp[j] = sp[j];
   } 
   else {
      for (i = 0; i < zz_pInfo->NumPrimes; i++) {
         long *Root = &RootTable[i][0];
         long *yp = &y.tbl[i][0];
         FFT(sp, yp, y.k, FFTPrime[i], Root);
         for (j = 0; j < n; j++)
            yp[j] = sp[j];
      }
   }
}



void RevTofftRep(fftRep& y, const vec_zz_p& x, 
                 long k, long lo, long hi, long offset)
// computes an n = 2^k point convolution of X^offset*x[lo..hi] mod X^n-1
// using "inverted" evaluation points.

{
   long n, i, j, m, j1;
   vec_long& s = FFTBuf;
   zz_p accum;
   long NumPrimes = zz_pInfo->NumPrimes;

   if (k > zz_pInfo->MaxRoot) 
      Error("Polynomial too big for FFT");

   if (lo < 0)
      Error("bad arg to TofftRep");

   hi = min(hi, x.length()-1);

   y.SetSize(k);

   n = 1L << k;

   m = max(hi-lo + 1, 0);

   const zz_p *xx = x.elts();

   long index = zz_pInfo->index;

   offset = offset & (n-1);

   if (index >= 0) {
      for (j = 0; j < n; j++) {
         if (j >= m) {
            y.tbl[0][offset] = 0;
         }
         else {
            accum = xx[j+lo];
            for (j1 = j + n; j1 < m; j1 += n)
               add(accum, accum, xx[j1+lo]);
               y.tbl[0][offset] = rep(accum);
         }
         offset = (offset + 1) & (n-1);
      }
   }
   else {
      for (j = 0; j < n; j++) {
         if (j >= m) {
            for (i = 0; i < NumPrimes; i++)
               y.tbl[i][offset] = 0;
         }
         else {
            accum = xx[j+lo];
            for (j1 = j + n; j1 < m; j1 += n)
               add(accum, accum, xx[j1+lo]);
            for (i = 0; i < NumPrimes; i++) {
               long q = FFTPrime[i];
               long t = rep(accum);
               if (t >= q) t -= q;
               y.tbl[i][offset] = t;
            }
         }
         offset = (offset + 1) & (n-1);
      }
   }


   s.SetLength(n);
   long *sp = s.elts();

   if (index >= 0) {
      long *Root = &RootInvTable[index][0];
      long *yp = &y.tbl[0][0];
      long w = TwoInvTable[index][k];
      long q = FFTPrime[index];
      double qinv = ((double) 1)/((double) q);
      FFT(sp, yp, y.k, q, Root);
      for (j = 0; j < n; j++)
         yp[j] = MulMod(sp[j], w, q, qinv);
   }
   else {
      for (i = 0; i < zz_pInfo->NumPrimes; i++) {
         long *Root = &RootInvTable[i][0];
         long *yp = &y.tbl[i][0];
         long w = TwoInvTable[i][k];
         long q = FFTPrime[i];
         double qinv = ((double) 1)/((double) q);
         FFT(sp, yp, y.k, q, Root);
         for (j = 0; j < n; j++)
            yp[j] = MulMod(sp[j], w, q, qinv);
      }
   }
}

void FromfftRep(zz_pX& x, fftRep& y, long lo, long hi)

   // converts from FFT-representation to coefficient representation
   // only the coefficients lo..hi are computed
   

{
   long k, n, i, j, l;
   long NumPrimes = zz_pInfo->NumPrimes;

   long t[4];
   vec_long& s = FFTBuf;;

   k = y.k;
   n = (1L << k);

   s.SetLength(n);
   long *sp = s.elts();

   long index = zz_pInfo->index;

   if (index >= 0) {
      long *yp = &y.tbl[0][0];
      long q = FFTPrime[index];
      double qinv = FFTPrimeInv[index];
      long w = TwoInvTable[index][k];
      long *Root = &RootInvTable[index][0];

      FFT(sp, yp, k, q, Root);

      for (j = 0; j < n; j++) yp[j] = MulMod(sp[j], w, q, qinv);
   }
   else {
      for (i = 0; i < NumPrimes; i++) {
         long *yp = &y.tbl[i][0];
         long q = FFTPrime[i];
         double qinv = FFTPrimeInv[i];
         long w = TwoInvTable[i][k];
         long *Root = &RootInvTable[i][0];
   
         FFT(sp, yp, k, q, Root);
   
         for (j = 0; j < n; j++) yp[j] = MulMod(sp[j], w, q, qinv);
      }
   }

   hi = min(hi, n-1);
   l = hi-lo+1;
   l = max(l, 0);
   x.rep.SetLength(l);

   if (index >= 0) {
      zz_p *xp = x.rep.elts();
      long *yp = &y.tbl[0][0];
      for (j = 0; j < l; j++) 
         xp[j].LoopHole() = yp[j+lo];
   }
   else {
      for (j = 0; j < l; j++) {
         for (i = 0; i < NumPrimes; i++) 
            t[i] = y.tbl[i][j+lo]; 
   
         FromModularRep(x.rep[j], t);
      }
   }

   x.normalize();
}

void RevFromfftRep(vec_zz_p& x, fftRep& y, long lo, long hi)

   // converts from FFT-representation to coefficient representation
   // using "inverted" evaluation points.
   // only the coefficients lo..hi are computed
   

{
   long k, n, i, j, l;
   long NumPrimes = zz_pInfo->NumPrimes;

   long t[4];
   vec_long& s = FFTBuf;

   k = y.k;
   n = (1L << k);

   s.SetLength(n);
   long *sp = s.elts();

   long index = zz_pInfo->index;

   if (index >= 0) {
      long *yp = &y.tbl[0][0];
      long q = FFTPrime[index];
      long *Root = &RootTable[index][0];

      FFT(sp, yp, k, q, Root);
      for (j = 0; j < n; j++)
         yp[j] = sp[j];
   }
   else {
      for (i = 0; i < NumPrimes; i++) {
         long *yp = &y.tbl[i][0];
         long q = FFTPrime[i];
         long *Root = &RootTable[i][0];
   
         FFT(sp, yp, k, q, Root);
         for (j = 0; j < n; j++)
            yp[j] = sp[j];
      }
   }

   hi = min(hi, n-1);
   l = hi-lo+1;
   l = max(l, 0);
   x.SetLength(l);

   if (index >= 0) {
      zz_p *xp = x.elts();
      long *yp = &y.tbl[0][0];
      for (j = 0; j < l; j++) 
         xp[j].LoopHole() = yp[j+lo];
   }
   else {
      for (j = 0; j < l; j++) {
         for (i = 0; i < NumPrimes; i++) 
            t[i] = y.tbl[i][j+lo]; 
   
         FromModularRep(x[j], t);
      }
   }
}

void NDFromfftRep(zz_pX& x, const fftRep& y, long lo, long hi, fftRep& z)
{
   long k, n, i, j, l;
   long NumPrimes = zz_pInfo->NumPrimes;

   long t[4];

   k = y.k;
   n = (1L << k);

   z.SetSize(k);

   long index = zz_pInfo->index;

   if (index >= 0) {
      long *zp = &z.tbl[0][0];
      long q = FFTPrime[index];
      double qinv = FFTPrimeInv[index];
      long w = TwoInvTable[index][k];
      long *Root = &RootInvTable[index][0];

      FFT(zp, &y.tbl[0][0], k, q, Root);

      for (j = 0; j < n; j++) zp[j] = MulMod(zp[j], w, q, qinv);
   }
   else {
      for (i = 0; i < NumPrimes; i++) {
         long *zp = &z.tbl[i][0];
         long q = FFTPrime[i];
         double qinv = FFTPrimeInv[i];
         long w = TwoInvTable[i][k];
         long *Root = &RootInvTable[i][0];
   
         FFT(zp, &y.tbl[i][0], k, q, Root);
   
         for (j = 0; j < n; j++) zp[j] = MulMod(zp[j], w, q, qinv);
      }
   }

   hi = min(hi, n-1);
   l = hi-lo+1;
   l = max(l, 0);
   x.rep.SetLength(l);

   if (index >= 0) {
      zz_p *xp = x.rep.elts();
      long *zp = &z.tbl[0][0];
      for (j = 0; j < l; j++) 
         xp[j].LoopHole() = zp[j+lo];
   }
   else {
      for (j = 0; j < l; j++) {
         for (i = 0; i < NumPrimes; i++) 
            t[i] = z.tbl[i][j+lo]; 
   
         FromModularRep(x.rep[j], t);
      }
   }

   x.normalize();
}

void NDFromfftRep(zz_pX& x, fftRep& y, long lo, long hi)
{
   fftRep z;
   NDFromfftRep(x, y, lo, hi, z);
}

void FromfftRep(zz_p* x, fftRep& y, long lo, long hi)

   // converts from FFT-representation to coefficient representation
   // only the coefficients lo..hi are computed
   

{
   long k, n, i, j;
   long NumPrimes = zz_pInfo->NumPrimes;

   long t[4];
   vec_long& s = FFTBuf;

   k = y.k;
   n = (1L << k);

   s.SetLength(n);
   long *sp = s.elts();

   long index = zz_pInfo->index;
   if (index >= 0) {
      long *yp = &y.tbl[0][0];
      long q = FFTPrime[index];
      double qinv = FFTPrimeInv[index];
      long w = TwoInvTable[index][k];
      long *Root = &RootInvTable[index][0];

      FFT(sp, yp, k, q, Root);

      for (j = 0; j < n; j++) yp[j] = MulMod(sp[j], w, q, qinv);

      for (j = lo; j <= hi; j++) {
         if (j >= n)
            clear(x[j-lo]);
         else {
            x[j-lo].LoopHole() = y.tbl[0][j];
         }
      }
   }
   else {
      for (i = 0; i < NumPrimes; i++) {
         long *yp = &y.tbl[i][0];
         long q = FFTPrime[i];
         double qinv = FFTPrimeInv[i];
         long w = TwoInvTable[i][k];
         long *Root = &RootInvTable[i][0];
   
         FFT(sp, yp, k, q, Root);
   
         for (j = 0; j < n; j++) yp[j] = MulMod(sp[j], w, q, qinv);
      }
   
      for (j = lo; j <= hi; j++) {
         if (j >= n)
            clear(x[j-lo]);
         else {
            for (i = 0; i < zz_pInfo->NumPrimes; i++) 
               t[i] = y.tbl[i][j]; 
   
            FromModularRep(x[j-lo], t);
         }
      }
   }
}


void mul(fftRep& z, const fftRep& x, const fftRep& y)
{
   long k, n, i, j;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -