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

📄 zz_px.c

📁 密码大家Shoup写的数论算法c语言实现
💻 C
📖 第 1 页 / 共 4 页
字号:
}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   {   ZZ_pInfo->check();   long k, n, i, j, l;   vec_long& t = ModularRepBuf;   vec_long& s = FFTBuf;;   t.SetLength(ZZ_pInfo->NumPrimes);   k = y.k;   n = (1L << k);   s.SetLength(n);   long *sp = s.elts();   for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {      long *yp = &y.tbl[i][0];      long q = FFTPrime[i];      double qinv = ((double) 1)/((double) q);      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);   for (j = 0; j < l; j++) {      for (i = 0; i < ZZ_pInfo->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   {   ZZ_pInfo->check();   long k, n, i, j, l;   vec_long& t = ModularRepBuf;   vec_long& s = FFTBuf;   k = y.k;   n = (1L << k);   t.SetLength(ZZ_pInfo->NumPrimes);   s.SetLength(n);   long *sp = s.elts();   for (i = 0; i < ZZ_pInfo->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);   for (j = 0; j < l; j++) {      for (i = 0; i < ZZ_pInfo->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){   ZZ_pInfo->check();   long k, n, i, j, l;   vec_long& t = ModularRepBuf;   t.SetLength(ZZ_pInfo->NumPrimes);   k = y.k;   n = (1L << k);   z.SetSize(k);   for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {      long *zp = &z.tbl[i][0];      long q = FFTPrime[i];      double qinv = ((double) 1)/((double) q);      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);   for (j = 0; j < l; j++) {      for (i = 0; i < ZZ_pInfo->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   {   ZZ_pInfo->check();   long k, n, i, j;   vec_long& t = ModularRepBuf;   vec_long& s = FFTBuf;   k = y.k;   n = (1L << k);   t.SetLength(ZZ_pInfo->NumPrimes);   s.SetLength(n);   long *sp = s.elts();   for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {      long *yp = &y.tbl[i][0];      long q = FFTPrime[i];      double qinv = ((double) 1)/((double) q);      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){   ZZ_pInfo->check();   long k, n, i, j;   if (x.k != y.k) Error("FFT rep mismatch");   k = x.k;   n = 1L << k;   z.SetSize(k);   for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {      long *zp = &z.tbl[i][0];      const long *xp = &x.tbl[i][0];      const long *yp = &y.tbl[i][0];      long q = FFTPrime[i];      double qinv = ((double) 1)/((double) q);      for (j = 0; j < n; j++)         zp[j] = MulMod(xp[j], yp[j], q, qinv);   }}void sub(FFTRep& z, const FFTRep& x, const FFTRep& y){   ZZ_pInfo->check();   long k, n, i, j;   if (x.k != y.k) Error("FFT rep mismatch");   k = x.k;   n = 1L << k;   z.SetSize(k);   for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {      long *zp = &z.tbl[i][0];      const long *xp = &x.tbl[i][0];      const long *yp = &y.tbl[i][0];      long q = FFTPrime[i];      for (j = 0; j < n; j++)         zp[j] = SubMod(xp[j], yp[j], q);   }}void add(FFTRep& z, const FFTRep& x, const FFTRep& y){   ZZ_pInfo->check();   long k, n, i, j;   if (x.k != y.k) Error("FFT rep mismatch");   k = x.k;   n = 1L << k;   z.SetSize(k);   for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {      long *zp = &z.tbl[i][0];      const long *xp = &x.tbl[i][0];      const long *yp = &y.tbl[i][0];      long q = FFTPrime[i];      for (j = 0; j < n; j++)         zp[j] = AddMod(xp[j], yp[j], q);   }}void reduce(FFTRep& x, const FFTRep& a, long k)  // reduces a 2^l point FFT-rep to a 2^k point FFT-rep  // input may alias output{   ZZ_pInfo->check();   long i, j, l, n;   long* xp;   const long* ap;   l = a.k;   n = 1L << k;   if (l < k) Error("reduce: bad operands");   x.SetSize(k);   for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {      ap = &a.tbl[i][0];         xp = &x.tbl[i][0];      for (j = 0; j < n; j++)          xp[j] = ap[j << (l-k)];   }}void AddExpand(FFTRep& x, const FFTRep& a)//  x = x + (an "expanded" version of a){   ZZ_pInfo->check();   long i, j, l, k, n;   l = x.k;   k = a.k;   n = 1L << k;   if (l < k) Error("AddExpand: bad args");   for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {      long q = FFTPrime[i];      const long *ap = &a.tbl[i][0];      long *xp = &x.tbl[i][0];      for (j = 0; j < n; j++) {         long j1 = j << (l-k);         xp[j1] = AddMod(xp[j1], ap[j], q);      }   }}void ToZZ_pXModRep(ZZ_pXModRep& y, const ZZ_pX& x, long lo, long hi){   ZZ_pInfo->check();   long n, i, j;   vec_long& t = ModularRepBuf;   t.SetLength(ZZ_pInfo->NumPrimes);   if (lo < 0)      Error("bad arg to ToZZ_pXModRep");   hi = min(hi, deg(x));   n = max(hi-lo+1, 0);   y.SetSize(n);   const ZZ_p *xx = x.rep.elts();   for (j = 0; j < n; j++) {      ToModularRep(t, xx[j+lo]);      for (i = 0; i < ZZ_pInfo->NumPrimes; i++)         y.tbl[i][j] = t[i];   }}void ToFFTRep(FFTRep& x, const ZZ_pXModRep& a, long k, long lo, long hi){   ZZ_pInfo->check();   vec_long s;   long n, m, i, j;   if (k < 0 || lo < 0)      Error("bad args to ToFFTRep");   if (hi > a.n-1) hi = a.n-1;   n = 1L << k;   m = max(hi-lo+1, 0);   if (m > n)      Error("bad args to ToFFTRep");   s.SetLength(n);   long *sp = s.elts();   x.SetSize(k);   long NumPrimes = ZZ_pInfo->NumPrimes;   for (i = 0; i < NumPrimes; i++) {      long *Root = &RootTable[i][0];      long *xp = &x.tbl[i][0];      long *ap = (m == 0 ? 0 : &a.tbl[i][0]);      for (j = 0; j < m; j++)         sp[j] = ap[lo+j];      for (j = m; j < n; j++)         sp[j] = 0;            FFT(xp, sp, k, FFTPrime[i], Root);   }}void FFTMul(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b){   long k, d;   if (IsZero(a) || IsZero(b)) {      clear(x);      return;   }   d = deg(a) + deg(b);   k = NextPowerOfTwo(d+1);   FFTRep R1(INIT_SIZE, k), R2(INIT_SIZE, k);   ToFFTRep(R1, a, k);   ToFFTRep(R2, b, k);   mul(R1, R1, R2);   FromFFTRep(x, R1, 0, d);}void FFTSqr(ZZ_pX& x, const ZZ_pX& a){   long k, d;   if (IsZero(a)) {      clear(x);      return;   }   d = 2*deg(a);   k = NextPowerOfTwo(d+1);   FFTRep R1(INIT_SIZE, k);   ToFFTRep(R1, a, k);   mul(R1, R1, R1);   FromFFTRep(x, R1, 0, d);}void CopyReverse(ZZ_pX& x, const ZZ_pX& a, long lo, long hi)   // x[0..hi-lo] = reverse(a[lo..hi]), with zero fill   // input may not alias output{   long i, j, n, m;   n = hi-lo+1;   m = a.rep.length();   x.rep.SetLength(n);   const ZZ_p* ap = a.rep.elts();   ZZ_p* xp = x.rep.elts();   for (i = 0; i < n; i++) {      j = hi-i;      if (j < 0 || j >= m)         clear(xp[i]);      else         xp[i] = ap[j];   }   x.normalize();} void copy(ZZ_pX& x, const ZZ_pX& a, long lo, long hi)   // x[0..hi-lo] = a[lo..hi], with zero fill   // input may not alias output{   long i, j, n, m;   n = hi-lo+1;   m = a.rep.length();   x.rep.SetLength(n);   const ZZ_p* ap = a.rep.elts();   ZZ_p* xp = x.rep.elts();   for (i = 0; i < n; i++) {      j = lo + i;      if (j < 0 || j >= m)         clear(xp[i]);      else         xp[i] = ap[j];   }   x.normalize();} void rem21(ZZ_pX& x, const ZZ_pX& a, const ZZ_pXModulus& F){   long i, da, ds, n, kk;   da = deg(a);   n = F.n;   if (da > 2*n-2)      Error("bad args to rem(ZZ_pX,ZZ_pX,ZZ_pXModulus)");   if (da < n) {      x = a;      return;   }   if (!F.UseFFT || da - n <= NTL_ZZ_pX_FFT_CROSSOVER) {      PlainRem(x, a, F.f);      return;   }   FFTRep R1(INIT_SIZE, F.l);   ZZ_pX P1(INIT_SIZE, n);   ToFFTRep(R1, a, F.l, n, 2*(n-1));   mul(R1, R1, F.HRep);   FromFFTRep(P1, R1, n-2, 2*n-4);   ToFFTRep(R1, P1, F.k);   mul(R1, R1, F.FRep);   FromFFTRep(P1, R1, 0, n-1);   ds = deg(P1);   kk = 1L << F.k;   x.rep.SetLength(n);   const ZZ_p* aa = a.rep.elts();   const ZZ_p* ss = P1.rep.elts();   ZZ_p* xx = x.rep.elts();   for (i = 0; i < n; i++) {      if (i <= ds)         sub(xx[i], aa[i], ss[i]);      else         xx[i] = aa[i];      if (i + kk <= da)         add(xx[i], xx[i], aa[i+kk]);   }   x.normalize();}void DivRem21(ZZ_pX& q, ZZ_pX& x, const ZZ_pX& a, const ZZ_pXModulus& F){   long i, da, ds, n, kk;   da = deg(a);   n = F.n;   if (da > 2*n-2)      Error("bad args to rem(ZZ_pX,ZZ_pX,ZZ_pXModulus)");   if (da < n) {      x = a;      clear(q);      return;   }   if (!F.UseFFT || da - n <= NTL_ZZ_pX_FFT_CROSSOVER) {      PlainDivRem(q, x, a, F.f);      return;   }   FFTRep R1(INIT_SIZE, F.l);   ZZ_pX P1(INIT_SIZE, n), qq;   ToFFTRep(R1, a, F.l, n, 2*(n-1));   mul(R1, R1, F.HRep);   FromFFTRep(P1, R1, n-2, 2*n-4);   qq = P1;   ToFFTRep(R1, P1, F.k);   mul(R1, R1, F.FRep);   FromFFTRep(P1, R1, 0, n-1);   ds = deg(P1);   kk = 1L << F.k;   x.rep.SetLength(n);   const ZZ_p* aa = a.rep.elts();   const ZZ_p* ss = P1.rep.elts();   ZZ_p* xx = x.rep.elts();   for (i = 0; i < n; i++) {      if (i <= ds)         sub(xx[i], aa[i], ss[i]);      else         xx[i] = aa[i];      if (i + kk <= da)         add(xx[i], xx[i], aa[i+kk]);   }   x.normalize();   q = qq;}void div21(ZZ_pX& x, const ZZ_pX& a, const ZZ_pXModulus& F){   long da, n;   da = deg(a);   n = F.n;   if (da > 2*n-2)      Error("bad args to rem(ZZ_pX,ZZ_pX,ZZ_pXModulus)");   if (da < n) {      clear(x);      return;   }   if (!F.UseFFT || da - n <= NTL_ZZ_pX_FFT_CROSSOVER) {      PlainDiv(x, a, F.f);      return;   }   FFTRep R1(INIT_SIZE, F.l);   ZZ_pX P1(INIT_SIZE, n);   ToFFTRep(R1, a, F.l, n, 2*(n-1));   mul(R1, R1, F.HRep);   FromFFTRep(x, R1, n-2, 2*n-4);}void rem(ZZ_pX& x, const ZZ_pX& a, const ZZ_pXModulus& F){   long da = deg(a);   long n = F.n;   if (n < 0) Error("rem: unitialized modulus");   if (da <= 2*n-2) {      rem21(x, a, F);      return;   }   else if (!F.UseFFT || da - n <= NTL_ZZ_pX_FFT_CROSSOVER) {      PlainRem(x, a, F.f);      return;   }   ZZ_pX buf(INIT_SIZE, 2*n-1);   long a_len = da+1;   while (a_len > 0) {      long old_buf_len = buf.rep.length();      long amt = min(2*n-1-old_buf_len, a_len);      buf.rep.SetLength(old_buf_len+amt);      long i;      for (i = old_buf_len+amt-1; i >= amt; i--)         buf.rep[i] = buf.rep[i-amt];      for (i = amt-1; i >= 0; i--)         buf.rep[i] = a.rep[a_len-amt+i];      buf.normalize();      rem21(buf, buf, F);      a_len -= amt;   }   x = buf;}void DivRem(ZZ_pX& q, ZZ_pX& r, const ZZ_pX& a, const ZZ_pXModulus& F){   long da = deg(a);   long n = F.n;   if (n < 0) Error("uninitialized modulus");   if (da <= 2*n-2) {      DivRem21(q, r, a, F);      return;   }   else if (!F.UseFFT || da - n <= NTL_ZZ_pX_FFT_CROSSOVER) {      PlainDivRem(q, r, a, F.f);      return;   }   ZZ_pX buf(INIT_SIZE, 2*n-1);   ZZ_pX qbuf(INIT_SIZE, n-1);   ZZ_pX qq;   qq.rep.SetLength(da-n+1);   long a_len = da+1;   long q_hi = da-n+1;   while (a_len > 0) {      long old_buf_len = buf.rep.length();      long amt = min(2*n-1-old_buf_len, a_len);      buf.rep.SetLength(old_buf_len+amt);      long i;      for (i = old_buf_len+amt-1; i >= amt; i--)         buf.rep[i] = buf.rep[i-amt];      for (i = amt-1; i >= 0; i--)         buf.rep[i] = a.rep[a_len-amt+i];      buf.normalize();      DivRem21(qbuf, buf, buf, F);      long dl = qbuf.rep.length();      a_len = a_len - amt;      for(i = 0; i < dl; i++)         qq.rep[a_len+i] = qbuf.rep[i];      for(i = dl+a_len; i < q_hi; i++)         clear(qq.rep[i]);      q_hi = a_len;   }   r = buf;   qq.normalize();   q = qq;}void div(ZZ_pX& q, const ZZ_pX& a, const ZZ_pXModulus& F){   long da = deg(a);   long n = F.n;   if (n < 0) Error("uninitialized modulus");   if (da <= 2*n-2) {      div21(q, a, F);      return;   }   else if (!F.UseFFT || da - n <= NTL_ZZ_pX_FFT_CROSSOVER) {      PlainDiv(q, a, F.f);      return;   }   ZZ_pX buf(INIT_SIZE, 2*n-1);   ZZ_pX qbuf(INIT_SIZE, n-1);   ZZ_pX qq;   qq.rep.SetLength(da-n+1);   long a_len = da+1;   long q_hi = da-n+1;   while (a_len > 0) {      long old_buf_len = buf.rep.length();      long amt = min(2*n-1-old_buf_len, a_len);      buf.rep.SetLength(old_buf_len+amt);      long i;      for (i = old_buf_len+amt-1; i >= amt; i--)         buf.rep[i] = buf.rep[i-amt];      for (i = amt-1; i >= 0; i--)         buf.rep[i] = a.rep[a_len-amt+i];      buf.normalize();      a_len = a_len - amt;      if (a_len > 0)         DivRem21(qbuf, buf, buf, F);      else         div21(qbuf, buf, F);      long dl = qbuf.rep.length();      for(i = 0; i < dl; i++)         qq.rep[a_len+i] = qbuf.rep[i];      for(i = dl+a_len; i < q_hi; i++)         clear(qq.rep[i]);      q_hi = a_len;   }   qq.normalize();   q = qq;}void MulMod(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b, const ZZ_pXModulus& F){   long  da, db, d, n, k;   da = deg(a);   db = deg(b);   n = F.n;   if (n < 0) Error("MulMod: uninitialized modulus");   if (da >= n || db >= n)      Error("bad args to MulMod(ZZ_pX,ZZ_pX,ZZ_pX,ZZ_pXModulus)");   if (da < 0 || db < 0) {      clear(x);      return;   }   if (!F.UseFFT || da <= NTL_ZZ_pX_FFT_CROSSOVER || db <= NTL_ZZ_pX_FFT_CROSSOVER) {

⌨️ 快捷键说明

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