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

📄 c_lip.c

📁 密码大家Shoup写的数论算法c语言实现
💻 C
📖 第 1 页 / 共 5 页
字号:
#define KARSX (36)#else#define KARSX (32) #endifstaticvoid kar_sq(long *c, long *a, long *stk){   long sa, sc;   sa = *a;   sc = sa << 1;   if (sa < KARSX) {      /* classic algorithm */      long carry, i, j, *pc;      pc = c;      for (i = sc; i; i--) {         pc++;         *pc = 0;      }      carry = 0;      i = 0;      for (j = 1; j <= sa; j++) {         unsigned long uncar;         long t;         i += 2;         uncar = ((unsigned long) carry) + (((unsigned long) c[i-1]) << 1);         t = uncar & NTL_RADIXM;         zaddmulpsq(t, a[j], carry);         c[i-1] = t;         zaddmulsq(sa-j, c+i, a+j);         uncar = (c[i] << 1) + (uncar >> NTL_NBITS);         uncar += carry;         carry = uncar >> NTL_NBITS;         c[i] = uncar & NTL_RADIXM;      }   }   else {      long hsa = (sa + 1) >> 1;      long *T1, *T2, olda;      T1 = stk;  stk += hsa + 2;      T2 = stk;  stk += (hsa << 1) + 3;      if (stk-kmem > max_kmem) zhalt("internal error: kmem overflow");      kar_fold(T1, a, hsa);      kar_sq(T2, T1, stk);      olda = a[hsa];  a[hsa] = sa - hsa;      kar_sq(c + (hsa << 1), a + hsa, stk);      kar_sub(T2, c + (hsa << 1));      a[hsa] = olda;      *a = hsa;      kar_sq(c, a, stk);      kar_sub(T2, c);      *a = sa;      kar_add(c, T2, hsa);   }   while (c[sc] == 0 && sc > 1) sc--;   *c = sc;}void _ntl_zmul(_ntl_verylong a, _ntl_verylong b, _ntl_verylong *cc){   static _ntl_verylong mem = 0;   _ntl_verylong c = *cc;   if (!a || (a[0] == 1 && a[1] == 0) || !b || (b[0] == 1 && b[1] == 0)) {      _ntl_zzero(cc);      return;   }   if (a == b) {      if (a == c) {         _ntl_zcopy(a, &mem);         a = mem;      }      _ntl_zsq(a, cc);   }   else {      long aneg, bneg, sa, sb, sc;      if (a == c) {         _ntl_zcopy(a, &mem);         a = mem;      }      else if (b == c) {         _ntl_zcopy(b, &mem);         b = mem;      }      sa = *a;      if (sa < 0) {         *a = sa = -sa;         aneg = 1;      }      else         aneg = 0;      sb = *b;      if (*b < 0) {         *b = sb =  -sb;         bneg = 1;      }      else         bneg = 0;      sc = sa + sb;      if (MustAlloc(c, sc)) {         _ntl_zsetlength(&c, sc);         *cc = c;      }      /* we optimize for *very* small numbers,       * avoiding all function calls and loops */      if (sa <= 3 && sb <= 3) {         long carry, d;         switch (sa) {         case 1:            switch (sb) {            case 1:               carry = 0;               zxmulp(c[1], a[1], b[1], carry);               c[2] = carry;               break;            case 2:               carry = 0;               d = a[1];               zxmulp(c[1], b[1], d, carry);               zxmulp(c[2], b[2], d, carry);               c[3] = carry;               break;            case 3:               carry = 0;               d = a[1];               zxmulp(c[1], b[1], d, carry);               zxmulp(c[2], b[2], d, carry);               zxmulp(c[3], b[3], d, carry);               c[4] = carry;               break;            }            break;         case 2:            switch (sb) {            case 1:               carry = 0;               d = b[1];               zxmulp(c[1], a[1], d, carry);               zxmulp(c[2], a[2], d, carry);               c[3] = carry;               break;            case 2:               carry = 0;               d = b[1];               zxmulp(c[1], a[1], d, carry);               zxmulp(c[2], a[2], d, carry);               c[3] = carry;               carry = 0;               d = b[2];               zaddmulp(c[2], a[1], d, carry);               zaddmulp(c[3], a[2], d, carry);               c[4] = carry;               break;             case 3:               carry = 0;               d = a[1];               zxmulp(c[1], b[1], d, carry);               zxmulp(c[2], b[2], d, carry);               zxmulp(c[3], b[3], d, carry);               c[4] = carry;               carry = 0;               d = a[2];               zaddmulp(c[2], b[1], d, carry);               zaddmulp(c[3], b[2], d, carry);               zaddmulp(c[4], b[3], d, carry);               c[5] = carry;               break;            }            break;         case 3:            switch (sb) {            case 1:               carry = 0;               d = b[1];               zxmulp(c[1], a[1], d, carry);               zxmulp(c[2], a[2], d, carry);               zxmulp(c[3], a[3], d, carry);               c[4] = carry;               break;            case 2:               carry = 0;               d = b[1];               zxmulp(c[1], a[1], d, carry);               zxmulp(c[2], a[2], d, carry);               zxmulp(c[3], a[3], d, carry);               c[4] = carry;               carry = 0;               d = b[2];               zaddmulp(c[2], a[1], d, carry);               zaddmulp(c[3], a[2], d, carry);               zaddmulp(c[4], a[3], d, carry);               c[5] = carry;               break;            case 3:               carry = 0;               d = b[1];               zxmulp(c[1], a[1], d, carry);               zxmulp(c[2], a[2], d, carry);               zxmulp(c[3], a[3], d, carry);               c[4] = carry;               carry = 0;               d = b[2];               zaddmulp(c[2], a[1], d, carry);               zaddmulp(c[3], a[2], d, carry);               zaddmulp(c[4], a[3], d, carry);               c[5] = carry;               carry = 0;               d = b[3];               zaddmulp(c[3], a[1], d, carry);               zaddmulp(c[4], a[2], d, carry);               zaddmulp(c[5], a[3], d, carry);               c[6] = carry;               break;            }         }         if (c[sc] == 0) sc--;         if (aneg != bneg) sc = -sc;         *c = sc;         if (aneg) *a = -sa;         if (bneg) *b = -sb;         return;               }#ifdef NTL_GMP_HACK      if (_ntl_gmp_hack && sa >= NTL_GMP_MUL_CROSS && sb >= NTL_GMP_MUL_CROSS) {         long gsa = L_TO_G(sa);          long gsb = L_TO_G(sb);         mp_limb_t *a_p, *b_p, *c_p, *end_p;;         NTL_GSPACE((gsa + gsb) << 1);         a_p = gspace_data;         b_p = a_p + gsa;         c_p = b_p + gsb;         end_p = c_p + (gsa + gsb);         lip_to_gmp(a+1, a_p, sa);         lip_to_gmp(b+1, b_p, sb);          if (!a_p[gsa-1]) gsa--;         if (!b_p[gsb-1]) gsb--;         end_p[-1] = 0;         end_p[-2] = 0;         if (gsa >= gsb)            mpn_mul(c_p, a_p, gsa, b_p, gsb);         else            mpn_mul(c_p, b_p, gsb, a_p, gsa);         gmp_to_lip(c+1, c_p, sc);         if (!c[sc]) sc--;          if (aneg != bneg) sc = -sc;         c[0] = sc;         if (aneg) *a = - *a;         if (bneg) *b = - *b;         return;      }#endif      if (*a < KARX || *b < KARX) {         /* classic algorithm */         long i, *pc;         pc = c;         for (i = sc; i; i--) {            pc++;            *pc = 0;         }            pc = c;            if (*a >= *b) {            long *pb = b;            for (i = *pb; i; i--) {               pb++;               pc++;               zaddmul(*pb, pc, a);            }         }         else {            long *pa = a;            for (i = *pa; i; i--) {               pa++;                pc++;               zaddmul(*pa, pc, b);            }         }            while (c[sc] == 0 && sc > 1) sc--;         if (aneg != bneg && (sc != 1 || c[1] != 0)) sc = -sc;         c[0] = sc;         if (aneg) *a = - *a;         if (bneg) *b = - *b;      }      else {         /* karatsuba */         long n, hn, sp;         if (*a < *b)            n = *b;         else            n = *a;         sp = 0;         do {            hn = (n + 1) >> 1;            sp += (hn << 2) + 7;            n = hn+1;         } while (n >= KARX);         if (sp > max_kmem) {            if (max_kmem == 0)                kmem = (long *) malloc(sp * sizeof(long));            else               kmem = (long *) realloc(kmem, sp * sizeof(long));            max_kmem = sp;            if (!kmem) zhalt("out of memory in karatsuba");         }         kar_mul(c, a, b, kmem);         if (aneg != bneg && (*c != 1 || c[1] != 0)) *c = - *c;         if (aneg) *a = - *a;         if (bneg) *b = - *b;      }   }}void _ntl_zsq(_ntl_verylong a, _ntl_verylong *cc){   static _ntl_verylong mem = 0;   _ntl_verylong c = *cc;   long sa, aneg, sc;   if (!a || (a[0] == 1 && a[1] == 0)) {      _ntl_zzero(cc);      return;   }   if (a == c) {      _ntl_zcopy(a, &mem);      a = mem;   }   sa = *a;   if (*a < 0) {      *a = sa = -sa;      aneg = 1;   }   else      aneg = 0;   sc = (sa) << 1;   if (MustAlloc(c, sc)) {      _ntl_zsetlength(&c, sc);      *cc = c;   }   if (sa <= 3) {      long carry, d;      switch (sa) {      case 1:         carry = 0;         zxmulp(c[1], a[1], a[1], carry);         c[2] = carry;         break;      case 2:         carry = 0;         d = a[1];         zxmulp(c[1], a[1], d, carry);         zxmulp(c[2], a[2], d, carry);         c[3] = carry;         carry = 0;         d = a[2];         zaddmulp(c[2], a[1], d, carry);         zaddmulp(c[3], a[2], d, carry);         c[4] = carry;         break;      case 3:         carry = 0;         d = a[1];         zxmulp(c[1], a[1], d, carry);         zxmulp(c[2], a[2], d, carry);         zxmulp(c[3], a[3], d, carry);         c[4] = carry;         carry = 0;         d = a[2];         zaddmulp(c[2], a[1], d, carry);         zaddmulp(c[3], a[2], d, carry);         zaddmulp(c[4], a[3], d, carry);         c[5] = carry;         carry = 0;         d = a[3];         zaddmulp(c[3], a[1], d, carry);         zaddmulp(c[4], a[2], d, carry);         zaddmulp(c[5], a[3], d, carry);         c[6] = carry;         break;      }      if (c[sc] == 0) sc--;      *c = sc;      if (aneg) *a = -sa;      return;   }#ifdef NTL_GMP_HACK      if (_ntl_gmp_hack && sa >= NTL_GMP_SQR_CROSS) {         long gsa = L_TO_G(sa);          mp_limb_t *a_p, *c_p, *end_p;;         NTL_GSPACE(gsa + gsa + gsa);         a_p = gspace_data;         c_p = a_p + gsa;         end_p = c_p + (gsa + gsa);         lip_to_gmp(a+1, a_p, sa);         if (!a_p[gsa-1]) gsa--;         end_p[-1] = 0;         end_p[-2] = 0;         mpn_mul(c_p, a_p, gsa, a_p, gsa);         gmp_to_lip(c+1, c_p, sc);         if (!c[sc]) sc--;          c[0] = sc;         if (aneg) *a = - *a;         return;      }#endif   if (sa < KARSX) {      /* classic algorithm */      long carry, i, j, *pc;      pc = c;      for (i = sc; i; i--) {         pc++;         *pc = 0;      }      carry = 0;      i = 0;      for (j = 1; j <= sa; j++) {         unsigned long uncar;         long t;         i += 2;         uncar = ((unsigned long) carry) + (((unsigned long) c[i-1]) << 1);         t = uncar & NTL_RADIXM;         zaddmulpsq(t, a[j], carry);         c[i-1] = t;         zaddmulsq(sa-j, c+i, a+j);         uncar = (c[i] << 1) + (uncar >> NTL_NBITS);         uncar += carry;         carry = uncar >> NTL_NBITS;         c[i] = uncar & NTL_RADIXM;      }      while (c[sc] == 0 && sc > 1) sc--;      c[0] = sc;      if (aneg) *a = - *a;   }   else {      /* karatsuba */      long n, hn, sp;      n = *a;      sp = 0;      do {         hn = (n + 1) >> 1;         sp += hn + hn + hn + 5;         n = hn+1;      } while (n >= KARSX);      if (sp > max_kmem) {         if (max_kmem == 0)             kmem = (long *) malloc(sp * sizeof(long));         else            kmem = (long *) realloc(kmem, sp * sizeof(long));         max_kmem = sp;         if (!kmem) zhalt("out of memory in karatsuba");      }      kar_sq(c, a, kmem);      if (aneg) *a = - *a;   }}long _ntl_zsdiv(_ntl_verylong a, long d, _ntl_verylong *bb){   long sa;   _ntl_verylong b = *bb;   if (!d) {      zhalt("division by zero in _ntl_zsdiv");   }   if (!a) {      _ntl_zzero(bb);      return (0);   }   if (d == 2) {      long is_odd = a[1] & 1;      long fix = (a[0] < 0) & is_odd;      _ntl_zrshift(a, 1, bb);      if (fix) _ntl_zsadd(*bb, -1, bb);      return is_odd;   }    if ((sa = a[0]) < 0)      sa = (-sa);   _ntl_zsetlength(&b, sa);   if (a == *bb) a = b;   *bb = b;   if ((d >= NTL_RADIX) || (d <= -NTL_RADIX)) {      static _ntl_verylong zd = 0;      static _ntl_verylong zb = 0;      _ntl_zintoz(d, &zb);      _ntl_zdiv(a, zb, &b, &zd);      *bb = b;      return (_ntl_ztoint(zd));   }   else {      long den = d;      double deninv;      long carry = 0;      long i;      long flag = (*a < 0 ? 2 : 0) | (den < 0 ? 1 : 0);      if (den < 0)         den = -den;      deninv = (double)1/den;      if (a[sa] < den && sa > 1)         carry = a[sa--];      for (i = sa; i; i--) {         zdiv21(carry, a[i], den, deninv, b[i]);      }      while ((sa > 1) && (!(b[sa])))         sa--;      b[0] = sa;      if (flag) {         if (flag <= 2) {            if (!carry)               _ntl_znegate(&b);            else {               _ntl_zsadd(b, 1, &b);               b[0] = -b[0];               if (flag == 1)                  carry = carry - den;               else                  carry = den - carry;               *bb = b;            }         }         else            carry = -carry;      }      return (carry);   }}long _ntl_zsmod(_ntl_verylong a, long d){   long sa;   if (!a) {      return (0);   }   if (d == 2) return (a[1] & 1);   if (!d) {      zhalt("division by zero in _ntl_zsdiv");   }   if ((sa = a[0]) < 0)      sa = (-sa);   if ((d >= NTL_RADIX) || (d <= -NTL_RADIX)) {      static _ntl_verylong zd = 0;      static _ntl_verylong zb = 0;      _ntl_zintoz(d, &zb);      _ntl_zmod(a, zb, &zd);      return (_ntl_ztoint(zd));   }   else {      long den = d;      double deninv;      long carry = 0;      long i;      long flag = (*a < 0 ? 2 : 0) | (den < 0 ? 1 : 0);      if (den < 0)         den = -den;      deninv = (double)1/den;      if (a[sa] < den && sa > 1)         carry = a[sa--];      for (i = sa; i; i--) {         zrem21(carry, a[i], den, deninv);      }      

⌨️ 快捷键说明

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