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

📄 zz_px.c

📁 密码大家Shoup写的数论算法c语言实现
💻 C
📖 第 1 页 / 共 4 页
字号:
      ZZ_pX P1;      mul(P1, a, b);      rem(x, P1, F);      return;   }   d = da + db + 1;   k = NextPowerOfTwo(d);   k = max(k, F.k);   FFTRep R1(INIT_SIZE, k), R2(INIT_SIZE, F.l);   ZZ_pX P1(INIT_SIZE, n);   ToFFTRep(R1, a, k);   ToFFTRep(R2, b, k);   mul(R1, R1, R2);   NDFromFFTRep(P1, R1, n, d-1, R2); // save R1 for future use      ToFFTRep(R2, P1, F.l);   mul(R2, R2, F.HRep);   FromFFTRep(P1, R2, n-2, 2*n-4);   ToFFTRep(R2, P1, F.k);   mul(R2, R2, F.FRep);   reduce(R1, R1, F.k);   sub(R1, R1, R2);   FromFFTRep(x, R1, 0, n-1);}void SqrMod(ZZ_pX& x, const ZZ_pX& a, const ZZ_pXModulus& F){   long  da, d, n, k;   da = deg(a);   n = F.n;   if (n < 0) Error("SqrMod: uninitailized modulus");   if (da >= n)       Error("bad args to SqrMod(ZZ_pX,ZZ_pX,ZZ_pXModulus)");   if (!F.UseFFT || da <= NTL_ZZ_pX_FFT_CROSSOVER) {      ZZ_pX P1;      sqr(P1, a);      rem(x, P1, F);      return;   }   d = 2*da + 1;   k = NextPowerOfTwo(d);   k = max(k, F.k);   FFTRep R1(INIT_SIZE, k), R2(INIT_SIZE, F.l);   ZZ_pX P1(INIT_SIZE, n);   ToFFTRep(R1, a, k);   mul(R1, R1, R1);   NDFromFFTRep(P1, R1, n, d-1, R2);  // save R1 for future use      ToFFTRep(R2, P1, F.l);   mul(R2, R2, F.HRep);   FromFFTRep(P1, R2, n-2, 2*n-4);   ToFFTRep(R2, P1, F.k);   mul(R2, R2, F.FRep);   reduce(R1, R1, F.k);   sub(R1, R1, R2);   FromFFTRep(x, R1, 0, n-1);}void PlainInvTrunc(ZZ_pX& x, const ZZ_pX& a, long m)   /* x = (1/a) % X^m, input not output, constant term a is nonzero */{   long i, k, n, lb;   static ZZ v, t;   ZZ_p s;   const ZZ_p* ap;   ZZ_p* xp;      n = deg(a);   if (n < 0) Error("division by zero");   inv(s, ConstTerm(a));   if (n == 0) {      conv(x, s);      return;   }   ap = a.rep.elts();   x.rep.SetLength(m);   xp = x.rep.elts();   xp[0] = s;   long is_one = IsOne(s);   for (k = 1; k < m; k++) {      clear(v);      lb = max(k-n, 0);      for (i = lb; i <= k-1; i++) {         mul(t, rep(xp[i]), rep(ap[k-i]));         add(v, v, t);      }      conv(xp[k], v);      negate(xp[k], xp[k]);      if (!is_one) mul(xp[k], xp[k], s);   }   x.normalize();}void trunc(ZZ_pX& x, const ZZ_pX& a, long m)// x = a % X^m, output may alias input {   if (m < 0) Error("trunc: bad args");   if (&x == &a) {      if (x.rep.length() > m) {         x.rep.SetLength(m);         x.normalize();      }   }   else {      long n;      long i;      ZZ_p* xp;      const ZZ_p* ap;      n = min(a.rep.length(), m);      x.rep.SetLength(n);      xp = x.rep.elts();      ap = a.rep.elts();      for (i = 0; i < n; i++) xp[i] = ap[i];      x.normalize();   }}void CyclicReduce(ZZ_pX& x, const ZZ_pX& a, long m)// computes x = a mod X^m-1{   long n = deg(a);   long i, j;   ZZ_p accum;   if (n < m) {      x = a;      return;   }   if (&x != &a)      x.rep.SetLength(m);   for (i = 0; i < m; i++) {      accum = a.rep[i];      for (j = i + m; j <= n; j += m)         add(accum, accum, a.rep[j]);      x.rep[i] = accum;   }   if (&x == &a)      x.rep.SetLength(m);   x.normalize();}void InvTrunc(ZZ_pX& x, const ZZ_pX& a, long m){   if (m < 0) Error("InvTrunc: bad args");   if (m == 0) {      clear(x);      return;   }   if (m >= (1L << (NTL_BITS_PER_LONG-4)))      Error("overflow in InvTrunc");   if (&x == &a) {      ZZ_pX la;      la = a;      if (m > NTL_ZZ_pX_NEWTON_CROSSOVER && deg(a) > 0)         NewtonInvTrunc(x, la, m);      else         PlainInvTrunc(x, la, m);   }   else {      if (m > NTL_ZZ_pX_NEWTON_CROSSOVER && deg(a) > 0)         NewtonInvTrunc(x, a, m);      else         PlainInvTrunc(x, a, m);   }}   void build(ZZ_pXModulus& x, const ZZ_pX& f){   x.f = f;   x.n = deg(f);   x.tracevec.SetLength(0);   if (x.n <= 0)      Error("build: deg(f) must be at least 1");   if (x.n <= NTL_ZZ_pX_FFT_CROSSOVER + 1) {      x.UseFFT = 0;      return;   }   x.UseFFT = 1;   x.k = NextPowerOfTwo(x.n);   x.l = NextPowerOfTwo(2*x.n - 3);   ToFFTRep(x.FRep, f, x.k);   ZZ_pX P1(INIT_SIZE, x.n+1), P2(INIT_SIZE, x.n);   CopyReverse(P1, f, 0, x.n);   InvTrunc(P2, P1, x.n-1);   CopyReverse(P1, P2, 0, x.n-2);   ToFFTRep(x.HRep, P1, x.l);}ZZ_pXModulus::ZZ_pXModulus(const ZZ_pX& ff){   build(*this, ff);}ZZ_pXMultiplier::ZZ_pXMultiplier(const ZZ_pX& b, const ZZ_pXModulus& F){   build(*this, b, F); }void build(ZZ_pXMultiplier& x, const ZZ_pX& b,                          const ZZ_pXModulus& F){   long db;   long n = F.n;   if (n < 0) Error("build ZZ_pXMultiplier: uninitialized modulus");   x.b = b;   db = deg(b);   if (db >= n) Error("build ZZ_pXMultiplier: deg(b) >= deg(f)");   if (!F.UseFFT || db <= NTL_ZZ_pX_FFT_CROSSOVER) {      x.UseFFT = 0;      return;   }   x.UseFFT = 1;   FFTRep R1(INIT_SIZE, F.l);   ZZ_pX P1(INIT_SIZE, n);      ToFFTRep(R1, b, F.l);   reduce(x.B2, R1, F.k);   mul(R1, R1, F.HRep);   FromFFTRep(P1, R1, n-1, 2*n-3);    ToFFTRep(x.B1, P1, F.l);}void MulMod(ZZ_pX& x, const ZZ_pX& a, const ZZ_pXMultiplier& B,                                      const ZZ_pXModulus& F){   long n = F.n;   long da;   da = deg(a);   if (da >= n)      Error(" bad args to MulMod(ZZ_pX,ZZ_pX,ZZ_pXMultiplier,ZZ_pXModulus)");   if (da < 0) {      clear(x);      return;   }   if (!B.UseFFT || !F.UseFFT || da <= NTL_ZZ_pX_FFT_CROSSOVER) {      ZZ_pX P1;      mul(P1, a, B.b);      rem(x, P1, F);      return;   }   ZZ_pX P1(INIT_SIZE, n), P2(INIT_SIZE, n);   FFTRep R1(INIT_SIZE, F.l), R2(INIT_SIZE, F.l);   ToFFTRep(R1, a, F.l);   mul(R2, R1, B.B1);   FromFFTRep(P1, R2, n-1, 2*n-3);   reduce(R1, R1, F.k);   mul(R1, R1, B.B2);   ToFFTRep(R2, P1, F.k);   mul(R2, R2, F.FRep);   sub(R1, R1, R2);   FromFFTRep(x, R1, 0, n-1);}   void PowerXMod(ZZ_pX& hh, const ZZ& e, const ZZ_pXModulus& F){   if (F.n < 0) Error("PowerXMod: uninitialized modulus");   if (IsZero(e)) {      set(hh);      return;   }   long n = NumBits(e);   long i;   ZZ_pX h;   h.SetMaxLength(F.n);   set(h);   for (i = n - 1; i >= 0; i--) {      SqrMod(h, h, F);      if (bit(e, i))         MulByXMod(h, h, F);   }   if (e < 0) InvMod(h, h, F);   hh = h;}void PowerXPlusAMod(ZZ_pX& hh, const ZZ_p& a, const ZZ& e, const ZZ_pXModulus& F){   if (F.n < 0) Error("PowerXPlusAMod: uninitialized modulus");   if (IsZero(e)) {      set(hh);      return;   }   ZZ_pX t1(INIT_SIZE, F.n), t2(INIT_SIZE, F.n);   long n = NumBits(e);   long i;   ZZ_pX h;   h.SetMaxLength(F.n);   set(h);   for (i = n - 1; i >= 0; i--) {      SqrMod(h, h, F);      if (bit(e, i)) {         MulByXMod(t1, h, F);         mul(t2, h, a);         add(h, t1, t2);      }   }   if (e < 0) InvMod(h, h, F);   hh = h;}void PowerMod(ZZ_pX& h, const ZZ_pX& g, const ZZ& e, const ZZ_pXModulus& F){   if (deg(g) >= F.n)      Error("PowerMod: bad args");   if (IsZero(e)) {      set(h);      return;   }   ZZ_pXMultiplier G;   ZZ_pX res;   long n = NumBits(e);   long i;   build(G, g, F);   res.SetMaxLength(F.n);   set(res);   for (i = n - 1; i >= 0; i--) {      SqrMod(res, res, F);      if (bit(e, i))         MulMod(res, res, G, F);   }   if (e < 0) InvMod(res, res, F);   h = res;}#if 0void NewtonInvTrunc(ZZ_pX& x, const ZZ_pX& a, long m){   x.SetMaxLength(m);   long i;   long t;   t = NextPowerOfTwo(2*m-1);   FFTRep R1(INIT_SIZE, t), R2(INIT_SIZE, t);   ZZ_pX P1(INIT_SIZE, m);   long log2_newton = NextPowerOfTwo(NTL_ZZ_pX_NEWTON_CROSSOVER)-1;   PlainInv(x, a, 1L << log2_newton);   long k = 1L << log2_newton;   long a_len = min(m, a.rep.length());   while (k < m) {      long l = min(2*k, m);      t = NextPowerOfTwo(2*k);      ToFFTRep(R1, x, t);      mul(R1, R1, R1);      FromFFTRep(P1, R1, 0, l-1);      t = NextPowerOfTwo(deg(P1) + min(l, a_len));      ToFFTRep(R1, P1, t);      ToFFTRep(R2, a, t, 0, min(l, a_len)-1);      mul(R1, R1, R2);      FromFFTRep(P1, R1, k, l-1);            x.rep.SetLength(l);      long y_len = P1.rep.length();      for (i = k; i < l; i++) {         if (i-k >= y_len)            clear(x.rep[i]);         else            negate(x.rep[i], P1.rep[i-k]);      }      x.normalize();      k = l;   }}#elsevoid NewtonInvTrunc(ZZ_pX& x, const ZZ_pX& a, long m){   x.SetMaxLength(m);   long i, t, k;   long log2_newton = NextPowerOfTwo(NTL_ZZ_pX_NEWTON_CROSSOVER)-1;   PlainInvTrunc(x, a, 1L << log2_newton);   t = NextPowerOfTwo(m);   FFTRep R1(INIT_SIZE, t), R2(INIT_SIZE, t);   ZZ_pX P1(INIT_SIZE, m/2);   long a_len = min(m, a.rep.length());   ZZ_pXModRep a_rep;   ToZZ_pXModRep(a_rep, a, 0, a_len-1);   k = 1L << log2_newton;    t = log2_newton;   while (k < m) {      long l = min(2*k, m);      ToFFTRep(R1, x, t+1);      ToFFTRep(R2, a_rep, t+1, 0, l-1);       mul(R2, R2, R1);      FromFFTRep(P1, R2, k, l-1);            ToFFTRep(R2, P1, t+1);      mul(R2, R2, R1);      FromFFTRep(P1, R2, 0, l-k-1);      x.rep.SetLength(l);      long y_len = P1.rep.length();      for (i = k; i < l; i++) {         if (i-k >= y_len)            clear(x.rep[i]);         else            negate(x.rep[i], P1.rep[i-k]);      }      x.normalize();      t++;      k = l;   }}#endifvoid FFTDivRem(ZZ_pX& q, ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b){   long n = deg(b);   long m = deg(a);   long k, l;   if (m < n) {      clear(q);      r = a;      return;   }   if (m >= 3*n) {      ZZ_pXModulus B;      build(B, b);      DivRem(q, r, a, B);      return;   }   ZZ_pX P1, P2, P3;   CopyReverse(P3, b, 0, n);   InvTrunc(P2, P3, m-n+1);   CopyReverse(P1, P2, 0, m-n);   k = NextPowerOfTwo(2*(m-n)+1);   long k1 = NextPowerOfTwo(n);   long mx = max(k1, k);   FFTRep R1(INIT_SIZE, mx), R2(INIT_SIZE, mx);   ToFFTRep(R1, P1, k);   ToFFTRep(R2, a, k, n, m);   mul(R1, R1, R2);   FromFFTRep(P3, R1, m-n, 2*(m-n));      l = 1L << k1;      ToFFTRep(R1, b, k1);   ToFFTRep(R2, P3, k1);   mul(R1, R1, R2);   FromFFTRep(P1, R1, 0, n-1);   CyclicReduce(P2, a, l);   trunc(r, P2, n);   sub(r, r, P1);   q = P3;}void FFTDiv(ZZ_pX& q, const ZZ_pX& a, const ZZ_pX& b){   long n = deg(b);   long m = deg(a);   long k;   if (m < n) {      clear(q);      return;   }   if (m >= 3*n) {      ZZ_pXModulus B;      build(B, b);      div(q, a, B);      return;   }   ZZ_pX P1, P2, P3;   CopyReverse(P3, b, 0, n);   InvTrunc(P2, P3, m-n+1);   CopyReverse(P1, P2, 0, m-n);   k = NextPowerOfTwo(2*(m-n)+1);   FFTRep R1(INIT_SIZE, k), R2(INIT_SIZE, k);   ToFFTRep(R1, P1, k);   ToFFTRep(R2, a, k, n, m);   mul(R1, R1, R2);   FromFFTRep(q, R1, m-n, 2*(m-n));}void FFTRem(ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b){   long n = deg(b);   long m = deg(a);   long k, l;   if (m < n) {      r = a;      return;   }   if (m >= 3*n) {      ZZ_pXModulus B;      build(B, b);      rem(r, a, B);      return;   }   ZZ_pX P1, P2, P3;   CopyReverse(P3, b, 0, n);   InvTrunc(P2, P3, m-n+1);   CopyReverse(P1, P2, 0, m-n);   k = NextPowerOfTwo(2*(m-n)+1);   long k1 = NextPowerOfTwo(n);   long mx = max(k, k1);   FFTRep R1(INIT_SIZE, mx), R2(INIT_SIZE, mx);   ToFFTRep(R1, P1, k);   ToFFTRep(R2, a, k, n, m);   mul(R1, R1, R2);   FromFFTRep(P3, R1, m-n, 2*(m-n));      l = 1L << k1;      ToFFTRep(R1, b, k1);   ToFFTRep(R2, P3, k1);   mul(R1, R1, R2);   FromFFTRep(P3, R1, 0, n-1);   CyclicReduce(P2, a, l);   trunc(r, P2, n);   sub(r, r, P3);}void DivRem(ZZ_pX& q, ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b){   if (deg(b) > NTL_ZZ_pX_DIV_CROSSOVER && deg(a) - deg(b) > NTL_ZZ_pX_DIV_CROSSOVER)      FFTDivRem(q, r, a, b);   else      PlainDivRem(q, r, a, b);}void div(ZZ_pX& q, const ZZ_pX& a, const ZZ_pX& b){   if (deg(b) > NTL_ZZ_pX_DIV_CROSSOVER && deg(a) - deg(b) > NTL_ZZ_pX_DIV_CROSSOVER)      FFTDiv(q, a, b);   else      PlainDiv(q, a, b);}void div(ZZ_pX& q, const ZZ_pX& a, const ZZ_p& b){   ZZ_pTemp TT; ZZ_p& T = TT.val();   inv(T, b);   mul(q, a, T);}void div(ZZ_pX& q, const ZZ_pX& a, long b){   ZZ_pTemp TT; ZZ_p& T = TT.val();   T = b;   inv(T, T);   mul(q, a, T);}void rem(ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b){   if (deg(b) > NTL_ZZ_pX_DIV_CROSSOVER && deg(a) - deg(b) > NTL_ZZ_pX_DIV_CROSSOVER)      FFTRem(r, a, b);   else      PlainRem(r, a, b);}long operator==(const ZZ_pX& a, long b){   if (b == 0)      return IsZero(a);   if (b == 1)      return IsOne(a);   long da = deg(a);   if (da > 0)      return 0;   ZZ_pTemp TT; ZZ_p& bb = TT.val();   bb = b;   if (da < 0)      return IsZero(bb);   return a.rep[0] == bb;}long operator==(const ZZ_pX& a, const ZZ_p& b){   if (IsZero(b))      return IsZero(a);   long da = deg(a);   if (da != 0)      return 0;   return a.rep[0] == b;}void power(ZZ_pX& x, const ZZ_pX& a, long e){   if (e < 0) {      Error("power: negative exponent");   }   if (e == 0) {      x = 1;      return;   }   if (a == 0 || a == 1) {      x = a;      return;   }   long da = deg(a);   if (da == 0) {      x = power(ConstTerm(a), e);      return;   }   if (da > (NTL_MAX_LONG-1)/e)      Error("overflow in power");   ZZ_pX res;   res.SetMaxLength(da*e + 1);   res = 1;      long k = NumBits(e);   long i;   for (i = k - 1; i >= 0; i--) {      sqr(res, res);      if (bit(e, i))         mul(res, res, a);   }   x = res;}void reverse(ZZ_pX& x, const ZZ_pX& a, long hi){   if (hi < -1) Error("reverse: bad args");   if (hi >= (1L << (NTL_BITS_PER_LONG-4)))      Error("overflow in reverse");   if (&x == &a) {      ZZ_pX tmp;      CopyReverse(tmp, a, 0, hi);      x = tmp;   }   else      CopyReverse(x, a, 0, hi);}NTL_END_IMPL

⌨️ 快捷键说明

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