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

📄 gf2ex.c

📁 密码大家Shoup写的数论算法c语言实现
💻 C
📖 第 1 页 / 共 4 页
字号:
#include <NTL/GF2EX.h>#include <NTL/vec_vec_GF2.h>#include <NTL/new.h>NTL_START_IMPLconst GF2EX& GF2EX::zero(){   static GF2EX z;   return z;}istream& operator>>(istream& s, GF2EX& x){   s >> x.rep;   x.normalize();   return s;}ostream& operator<<(ostream& s, const GF2EX& a){   return s << a.rep;}void GF2EX::normalize(){   long n;   const GF2E* p;   n = rep.length();   if (n == 0) return;   p = rep.elts() + (n-1);   while (n > 0 && IsZero(*p)) {      p--;       n--;   }   rep.SetLength(n);}long IsZero(const GF2EX& a){   return a.rep.length() == 0;}long IsOne(const GF2EX& a){    return a.rep.length() == 1 && IsOne(a.rep[0]);}void GetCoeff(GF2E& x, const GF2EX& a, long i){   if (i < 0 || i > deg(a))      clear(x);   else      x = a.rep[i];}void SetCoeff(GF2EX& x, long i, const GF2E& a){   long j, m;   if (i < 0)       Error("SetCoeff: negative index");   if (i >= (1L << (NTL_BITS_PER_LONG-4)))      Error("overflow in SetCoeff");   m = deg(x);   if (i > m) {      long pos = x.rep.position(a);      x.rep.SetLength(i+1);      if (pos != -1)         x.rep[i] = x.rep.RawGet(pos);      else         x.rep[i] = a;      for (j = m+1; j < i; j++)         clear(x.rep[j]);   }   else      x.rep[i] = a;   x.normalize();}void SetCoeff(GF2EX& x, long i, GF2 a){   if (i < 0)      Error("SetCoeff: negative index");   if (a == 1)      SetCoeff(x, i);   else      SetCoeff(x, i, GF2E::zero());}void SetCoeff(GF2EX& x, long i, long a){   if (i < 0)      Error("SetCoeff: negative index");   if ((a & 1) == 1)      SetCoeff(x, i);   else      SetCoeff(x, i, GF2E::zero());}void SetCoeff(GF2EX& x, long i){   long j, m;   if (i < 0)       Error("coefficient index out of range");   if (i >= (1L << (NTL_BITS_PER_LONG-4)))      Error("overflow in SetCoeff");   m = deg(x);   if (i > m) {      x.rep.SetLength(i+1);      for (j = m+1; j < i; j++)         clear(x.rep[j]);   }   set(x.rep[i]);   x.normalize();}void SetX(GF2EX& x){   clear(x);   SetCoeff(x, 1);}long IsX(const GF2EX& a){   return deg(a) == 1 && IsOne(LeadCoeff(a)) && IsZero(ConstTerm(a));}            const GF2E& coeff(const GF2EX& a, long i){   if (i < 0 || i > deg(a))      return GF2E::zero();   else      return a.rep[i];}const GF2E& LeadCoeff(const GF2EX& a){   if (IsZero(a))      return GF2E::zero();   else      return a.rep[deg(a)];}const GF2E& ConstTerm(const GF2EX& a){   if (IsZero(a))      return GF2E::zero();   else      return a.rep[0];}void conv(GF2EX& x, const GF2E& a){   if (IsZero(a))      x.rep.SetLength(0);   else {      x.rep.SetLength(1);      x.rep[0] = a;   }}void conv(GF2EX& x, long a){   if (a & 1)      set(x);   else      clear(x);}void conv(GF2EX& x, GF2 a){   if (a == 1)      set(x);   else      clear(x);}void conv(GF2EX& x, const ZZ& a){   if (IsOdd(a))      set(x);   else      clear(x);}void conv(GF2EX& x, const GF2X& aa){   GF2X a = aa; // in case a aliases the rep of a coefficient of x      long n = deg(a)+1;   long i;   x.rep.SetLength(n);   for (i = 0; i < n; i++)      conv(x.rep[i], coeff(a, i));}void conv(GF2EX& x, const vec_GF2E& a){   x.rep = a;   x.normalize();}void add(GF2EX& x, const GF2EX& a, const GF2EX& b){   long da = deg(a);   long db = deg(b);   long minab = min(da, db);   long maxab = max(da, db);   x.rep.SetLength(maxab+1);   long i;   const GF2E *ap, *bp;    GF2E* xp;   for (i = minab+1, ap = a.rep.elts(), bp = b.rep.elts(), xp = x.rep.elts();        i; i--, ap++, bp++, xp++)      add(*xp, (*ap), (*bp));   if (da > minab && &x != &a)      for (i = da-minab; i; i--, xp++, ap++)         *xp = *ap;   else if (db > minab && &x != &b)      for (i = db-minab; i; i--, xp++, bp++)         *xp = *bp;   else      x.normalize();}void add(GF2EX& x, const GF2EX& a, const GF2E& b){   long n = a.rep.length();   if (n == 0) {      conv(x, b);   }   else if (&x == &a) {      add(x.rep[0], a.rep[0], b);      x.normalize();   }   else if (x.rep.MaxLength() == 0) {      x = a;      add(x.rep[0], a.rep[0], b);      x.normalize();   }   else {      // ugly...b could alias a coeff of x      GF2E *xp = x.rep.elts();      add(xp[0], a.rep[0], b);      x.rep.SetLength(n);      xp = x.rep.elts();      const GF2E *ap = a.rep.elts();      long i;      for (i = 1; i < n; i++)         xp[i] = ap[i];      x.normalize();   }}void add(GF2EX& x, const GF2EX& a, GF2 b){   if (a.rep.length() == 0) {      conv(x, b);   }   else {      if (&x != &a) x = a;      add(x.rep[0], x.rep[0], b);      x.normalize();   }}void add(GF2EX& x, const GF2EX& a, long b){   if (a.rep.length() == 0) {      conv(x, b);   }   else {      if (&x != &a) x = a;      add(x.rep[0], x.rep[0], b);      x.normalize();   }}void PlainMul(GF2EX& x, const GF2EX& a, const GF2EX& b){   long da = deg(a);   long db = deg(b);   if (da < 0 || db < 0) {      clear(x);      return;   }   if (&a == &b) {      sqr(x, a);      return;   }   long d = da+db;   const GF2E *ap, *bp;   GF2E *xp;      GF2EX la, lb;   if (&x == &a) {      la = a;      ap = la.rep.elts();   }   else      ap = a.rep.elts();   if (&x == &b) {      lb = b;      bp = lb.rep.elts();   }   else      bp = b.rep.elts();   x.rep.SetLength(d+1);   xp = x.rep.elts();   long i, j, jmin, jmax;   GF2X t, accum;   for (i = 0; i <= d; i++) {      jmin = max(0, i-db);      jmax = min(da, i);      clear(accum);      for (j = jmin; j <= jmax; j++) {	 mul(t, rep(ap[j]), rep(bp[i-j]));	 add(accum, accum, t);      }      conv(xp[i], accum);   }   x.normalize();}void sqr(GF2EX& x, const GF2EX& a){   long da = deg(a);   if (da < 0) {      clear(x);      return;   }   x.rep.SetLength(2*(da+1));   long i;   for (i = da; i > 0; i--) {      sqr(x.rep[2*i], a.rep[i]);      clear(x.rep[2*i-1]);   }   sqr(x.rep[0], a.rep[0]);   x.normalize();}#if 0staticvoid PlainMul(GF2X *xp, const GF2X *ap, long sa, const GF2X *bp, long sb){   if (sa == 0 || sb == 0) return;   long sx = sa+sb-1;   long i, j, jmin, jmax;   static GF2X t, accum;   for (i = 0; i < sx; i++) {      jmin = max(0, i-sb+1);      jmax = min(sa-1, i);      clear(accum);      for (j = jmin; j <= jmax; j++) {         mul(t, ap[j], bp[i-j]);         add(accum, accum, t);      }      xp[i] = accum;   }}#endifstatic void PlainMul1(GF2X *xp, const GF2X *ap, long sa, const GF2X& b){   long i;   for (i = 0; i < sa; i++)      mul(xp[i], ap[i], b);}inlinevoid q_add(GF2X& x, const GF2X& a, const GF2X& b)// This is a quick-and-dirty add rotine used by the karatsuba routine.// It assumes that the output already has enough space allocated,// thus avoiding any procedure calls.// WARNING: it also accesses the underlying WordVector representation// directly...that is dirty!.// It shaves a few percent off the running time.{   _ntl_ulong *xp = x.xrep.elts();   const _ntl_ulong *ap = a.xrep.elts();   const _ntl_ulong *bp = b.xrep.elts();   long sa = ap[-1];   long sb = bp[-1];   long i;   if (sa == sb) {      for (i = 0; i < sa; i++)         xp[i] = ap[i] ^ bp[i];      i = sa-1;      while (i >= 0 && !xp[i]) i--;      xp[-1] = i+1;   }   else if (sa < sb) {      for (i = 0; i < sa; i++)         xp[i] = ap[i] ^ bp[i];      for (; i < sb; i++)         xp[i] = bp[i];      xp[-1] = sb;   }   else { // sa > sb      for (i = 0; i < sb; i++)         xp[i] = ap[i] ^ bp[i];      for (; i < sa; i++)         xp[i] = ap[i];      xp[-1] = sa;   }}inlinevoid q_copy(GF2X& x, const GF2X& a)// see comments for q_add above{   _ntl_ulong *xp = x.xrep.elts();   const _ntl_ulong *ap = a.xrep.elts();   long sa = ap[-1];   long i;   for (i = 0; i < sa; i++)      xp[i] = ap[i];   xp[-1] = sa;}staticvoid KarFold(GF2X *T, const GF2X *b, long sb, long hsa){   long m = sb - hsa;   long i;   for (i = 0; i < m; i++)      q_add(T[i], b[i], b[hsa+i]);   for (i = m; i < hsa; i++)      q_copy(T[i], b[i]);}staticvoid KarAdd(GF2X *T, const GF2X *b, long sb){   long i;   for (i = 0; i < sb; i++)      q_add(T[i], T[i], b[i]);}staticvoid KarFix(GF2X *c, const GF2X *b, long sb, long hsa){   long i;   for (i = 0; i < hsa; i++)      q_copy(c[i], b[i]);   for (i = hsa; i < sb; i++)      q_add(c[i], c[i], b[i]);}staticvoid KarMul(GF2X *c, const GF2X *a,             long sa, const GF2X *b, long sb, GF2X *stk){   if (sa < sb) {      { long t = sa; sa = sb; sb = t; }      { const GF2X *t = a; a = b; b = t; }   }   if (sb == 1) {        if (sa == 1)          mul(*c, *a, *b);      else         PlainMul1(c, a, sa, *b);      return;   }   if (sb == 2 && sa == 2) {      mul(c[0], a[0], b[0]);      mul(c[2], a[1], b[1]);      q_add(stk[0], a[0], a[1]);      q_add(stk[1], b[0], b[1]);      mul(c[1], stk[0], stk[1]);      q_add(c[1], c[1], c[0]);      q_add(c[1], c[1], c[2]);            return;   }   long hsa = (sa + 1) >> 1;   if (hsa < sb) {      /* normal case */      long hsa2 = hsa << 1;      GF2X *T1, *T2, *T3;      T1 = stk; stk += hsa;      T2 = stk; stk += hsa;      T3 = stk; stk += hsa2 - 1;      /* compute T1 = a_lo + a_hi */      KarFold(T1, a, sa, hsa);      /* compute T2 = b_lo + b_hi */      KarFold(T2, b, sb, hsa);      /* recursively compute T3 = T1 * T2 */      KarMul(T3, T1, hsa, T2, hsa, stk);      /* recursively compute a_hi * b_hi into high part of c */      /* and subtract from T3 */      KarMul(c + hsa2, a+hsa, sa-hsa, b+hsa, sb-hsa, stk);      KarAdd(T3, c + hsa2, sa + sb - hsa2 - 1);      /* recursively compute a_lo*b_lo into low part of c */      /* and subtract from T3 */      KarMul(c, a, hsa, b, hsa, stk);      KarAdd(T3, c, hsa2 - 1);      clear(c[hsa2 - 1]);      /* finally, add T3 * X^{hsa} to c */      KarAdd(c+hsa, T3, hsa2-1);   }   else {      /* degenerate case */      GF2X *T;      T = stk; stk += hsa + sb - 1;      /* recursively compute b*a_hi into high part of c */      KarMul(c + hsa, a + hsa, sa - hsa, b, sb, stk);      /* recursively compute b*a_lo into T */      KarMul(T, a, hsa, b, sb, stk);      KarFix(c, T, hsa + sb - 1, hsa);   }}void ExtractBits(_ntl_ulong *cp, const _ntl_ulong *ap, long k, long n)// extract k bits from a at position n{   long sc = (k + NTL_BITS_PER_LONG-1)/NTL_BITS_PER_LONG;   long wn = n/NTL_BITS_PER_LONG;   long bn = n - wn*NTL_BITS_PER_LONG;   long i;   if (bn == 0) {      for (i = 0; i < sc; i++)         cp[i] = ap[i+wn];   }   else {      for (i = 0; i < sc-1; i++)         cp[i] = (ap[i+wn] >> bn) | (ap[i+wn+1] << (NTL_BITS_PER_LONG - bn));      if ((k + n) % NTL_BITS_PER_LONG != 0)         cp[sc-1] = (ap[sc+wn-1] >> bn)|(ap[sc+wn] << (NTL_BITS_PER_LONG - bn));      else         cp[sc-1] = ap[sc+wn-1] >> bn;   }   long p = k % NTL_BITS_PER_LONG;   if (p != 0)       cp[sc-1] &= ((1UL << p) - 1UL);}void KronSubst(GF2X& aa, const GF2EX& a){   long sa = a.rep.length();   long blocksz = 2*GF2E::degree() - 1;   long saa = sa*blocksz;   long wsaa = (saa + NTL_BITS_PER_LONG-1)/NTL_BITS_PER_LONG;   aa.xrep.SetLength(wsaa+1);   _ntl_ulong *paa = aa.xrep.elts();   long i;   for (i = 0; i < wsaa+1; i++)      paa[i] = 0;   for (i = 0; i < sa; i++)       ShiftAdd(paa, rep(a.rep[i]).xrep.elts(), rep(a.rep[i]).xrep.length(),               blocksz*i);   aa.normalize(); }void KronMul(GF2EX& x, const GF2EX& a, const GF2EX& b){   if (a == 0 || b == 0) {      clear(x);      return;   }   GF2X aa, bb, xx;   long sx = deg(a) + deg(b) + 1;   long blocksz = 2*GF2E::degree() - 1;   if (blocksz >= (1L << (NTL_BITS_PER_LONG-4))/sx)      Error("overflow in GF2EX KronMul");   KronSubst(aa, a);   KronSubst(bb, b);   mul(xx, aa, bb);   GF2X c;   long wc = (blocksz + NTL_BITS_PER_LONG-1)/NTL_BITS_PER_LONG;   x.rep.SetLength(sx);   long i;   for (i = 0; i < sx-1; i++) {      c.xrep.SetLength(wc);      ExtractBits(c.xrep.elts(), xx.xrep.elts(), blocksz, i*blocksz);      c.normalize();      conv(x.rep[i], c);   }   long last_blocksz = deg(xx) - (sx-1)*blocksz + 1;   wc = (last_blocksz + NTL_BITS_PER_LONG-1)/NTL_BITS_PER_LONG;   c.xrep.SetLength(wc);   ExtractBits(c.xrep.elts(), xx.xrep.elts(), last_blocksz, (sx-1)*blocksz);   c.normalize();   conv(x.rep[sx-1], c);   x.normalize();}void mul(GF2EX& c, const GF2EX& a, const GF2EX& b){   if (IsZero(a) || IsZero(b)) {      clear(c);      return;   }   if (&a == &b) {      sqr(c, a);      return;   }   long sa = a.rep.length();   long sb = b.rep.length();   if (sa == 1) {      mul(c, b, a.rep[0]);      return;   }   if (sb == 1) {      mul(c, a, b.rep[0]);      return;   }   if (sa < GF2E::KarCross() || sb < GF2E::KarCross()) {      PlainMul(c, a, b);      return;   }   if (GF2E::WordLength() <= 1) {      KronMul(c, a, b);      return;   }      /* karatsuba */   long n, hn, sp;   n = max(sa, sb);   sp = 0;   do {      hn = (n+1) >> 1;      sp += (hn << 2) - 1;      n = hn;   } while (n > 1);   GF2XVec stk;   stk.SetSize(sp + 2*(sa+sb)-1, 2*GF2E::WordLength());    long i;   for (i = 0; i < sa; i++)      stk[i+sa+sb-1] = rep(a.rep[i]);   for (i = 0; i < sb; i++)      stk[i+2*sa+sb-1] = rep(b.rep[i]);   KarMul(&stk[0], &stk[sa+sb-1], sa, &stk[2*sa+sb-1], sb,           &stk[2*(sa+sb)-1]);   c.rep.SetLength(sa+sb-1);   for (i = 0; i < sa+sb-1; i++)      conv(c.rep[i], stk[i]);   c.normalize();}void MulTrunc(GF2EX& x, const GF2EX& a, const GF2EX& b, long n){   GF2EX t;   mul(t, a, b);   trunc(x, t, n);}void SqrTrunc(GF2EX& x, const GF2EX& a, long n){   GF2EX t;   sqr(t, a);   trunc(x, t, n);}void PlainDivRem(GF2EX& q, GF2EX& r, const GF2EX& a, const GF2EX& b){   long da, db, dq, i, j, LCIsOne;   const GF2E *bp;   GF2E *qp;   GF2X *xp;   GF2E LCInv, t;   GF2X s;   da = deg(a);   db = deg(b);   if (db < 0) Error("GF2EX: division by zero");   if (da < db) {      r = a;      clear(q);      return;   }   GF2EX lb;   if (&q == &b) {      lb = b;      bp = lb.rep.elts();   }   else      bp = b.rep.elts();   if (IsOne(bp[db]))      LCIsOne = 1;   else {      LCIsOne = 0;      inv(LCInv, bp[db]);   }   GF2XVec x(da + 1, 2*GF2E::WordLength());

⌨️ 快捷键说明

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