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

📄 g_lip.c

📁 密码大家Shoup写的数论算法c语言实现
💻 C
📖 第 1 页 / 共 5 页
字号:
         _ntl_gsmul(inv, got11, &x);         _ntl_gsmul(w, got12, &y);         _ntl_gsmul(inv, got21, &z);         _ntl_gsmul(w, got22, &w);         _ntl_gadd(x, y, &inv);         _ntl_gadd(z, w, &w);         _ntl_gsmul(a, got11, &x);         _ntl_gsmul(n, got12, &y);         _ntl_gsmul(a, got21, &z);         _ntl_gsmul(n, got22, &n);         _ntl_gsub(x, y, &a);         _ntl_gsub(n, z, &n);      }      else      {         _ntl_gdiv(a, n, &q, &a);         _ntl_gmul(q, w, &x);         _ntl_gadd(inv, x, &inv);         if (!ZEROP(a))         {            _ntl_gdiv(n, a, &q, &n);            _ntl_gmul(q, inv, &x);            _ntl_gadd(w, x, &w);         }         else         {            _ntl_gcopy(n, &a);            _ntl_gzero(&n);            _ntl_gcopy(w, &inv);            _ntl_gnegate(&inv);         }      }   }   if (_ntl_gscompare(a, 1) == 0)      e = 0;   else       e = 1;   _ntl_gcopy(a, &u);   *invv = inv;   *uu = u;   return (e);}#if 0void_ntl_gexteucl(	_ntl_gbigint aa,	_ntl_gbigint *xa,	_ntl_gbigint bb,	_ntl_gbigint *xb,	_ntl_gbigint *d	){   static _ntl_gbigint modcon = 0;   static _ntl_gbigint a=0, b=0;   long anegative = 0;   long bnegative = 0;   _ntl_gcopy(aa, &a);   _ntl_gcopy(bb, &b);   if (a && SIZE(a) < 0) {      anegative = 1;      SIZE(a) = -SIZE(a);   }   else      anegative = 0;   if (b && SIZE(b) < 0) {      bnegative = 1;      SIZE(b) = -SIZE(b);   }   else      bnegative = 0;   if (ZEROP(b))   {      _ntl_gone(xa);      _ntl_gzero(xb);      _ntl_gcopy(a, d);      goto done;   }   if (ZEROP(a))   {      _ntl_gzero(xa);      _ntl_gone(xb);      _ntl_gcopy(b, d);      goto done;   }   gxxeucl(a, b, xa, d);   _ntl_gmul(a, *xa, xb);   _ntl_gsub(*d, *xb, xb);   _ntl_gdiv(*xb, b, xb, &modcon);   if (!ZEROP(modcon))   {      ghalt("non-zero remainder in _ntl_gexteucl   BUG");   }done:   if (anegative)   {      _ntl_gnegate(xa);   }   if (bnegative)   {      _ntl_gnegate(xb);   }}#endifvoid_ntl_gexteucl(	_ntl_gbigint ain,	_ntl_gbigint *xap,	_ntl_gbigint bin,	_ntl_gbigint *xbp,	_ntl_gbigint *dp	){   if (ZEROP(bin)) {      long asign = _ntl_gsign(ain);      _ntl_gcopy(ain, dp);      _ntl_gabs(dp);      _ntl_gintoz( (asign >= 0 ? 1 : -1), xap);      _ntl_gzero(xbp);   }   else if (ZEROP(ain)) {      long bsign = _ntl_gsign(bin);      _ntl_gcopy(bin, dp);      _ntl_gabs(dp);      _ntl_gzero(xap);      _ntl_gintoz(bsign, xbp);    }   else {      static _ntl_gbigint a = 0, b = 0, xa = 0, xb = 0, d = 0, tmp = 0;      long sa, aneg, sb, bneg, rev;      mp_limb_t *adata, *bdata, *ddata, *xadata;      mp_size_t sxa, sd;      GET_SIZE_NEG(sa, aneg, ain);      GET_SIZE_NEG(sb, bneg, bin);      _ntl_gsetlength(&a, sa+1); /* +1 because mpn_gcdext may need it */      _ntl_gcopy(ain, &a);      _ntl_gsetlength(&b, sb+1); /* +1 because mpn_gcdext may need it */      _ntl_gcopy(bin, &b);      adata = DATA(a);      bdata = DATA(b);      if (sa < sb || (sa == sb && mpn_cmp(adata, bdata, sa) < 0)) {         SWAP_BIGINT(ain, bin);         SWAP_LONG(sa, sb);         SWAP_LONG(aneg, bneg);         SWAP_LIMB_PTR(adata, bdata);         rev = 1;      }      else          rev = 0;      _ntl_gsetlength(&d, sa+1); /* +1 because mpn_gcdext may need it...                                    documentation is unclear, but this is                                    what is done in mpz_gcdext */      _ntl_gsetlength(&xa, sa+1); /* ditto */      ddata = DATA(d);      xadata = DATA(xa);      sd = mpn_gcdext(ddata, xadata, &sxa, adata, sa, bdata, sb);      SIZE(d) = sd;      SIZE(xa) = sxa;      if (aneg) _ntl_gnegate(&xa);      _ntl_gmul(ain, xa, &tmp);      _ntl_gsub(d, tmp, &tmp);      _ntl_gdiv(tmp, bin, &xb, &tmp);      if (!ZEROP(tmp)) ghalt("internal bug in _ntl_gexteucl");      if (rev) SWAP_BIGINT(xa, xb);      _ntl_gcopy(xa, xap);      _ntl_gcopy(xb, xbp);      _ntl_gcopy(d, dp);    }}long _ntl_ginv(_ntl_gbigint ain, _ntl_gbigint nin, _ntl_gbigint *invv){   static _ntl_gbigint u = 0;   static _ntl_gbigint d = 0;   static _ntl_gbigint a = 0;   static _ntl_gbigint n = 0;   long sz;    long sd;   mp_size_t su;   if (_ntl_gscompare(nin, 1) <= 0) {      ghalt("InvMod: second input <= 1");   }   if (_ntl_gsign(ain) < 0) {      ghalt("InvMod: first input negative");   }   if (_ntl_gcompare(ain, nin) >= 0) {      ghalt("InvMod: first input too big");   }   sz = SIZE(nin) + 2;   if (MustAlloc(a, sz))      _ntl_gsetlength(&a, sz);   if (MustAlloc(n, sz))       _ntl_gsetlength(&n, sz);   if (MustAlloc(d, sz))       _ntl_gsetlength(&d, sz);   if (MustAlloc(u, sz))       _ntl_gsetlength(&u, sz);   _ntl_gadd(ain, nin, &a);   _ntl_gcopy(nin, &n);   /* We apply mpn_gcdext to (a, n) = (ain+nin, nin), because that function    * only computes the co-factor of the larger input. This way, we avoid    * a multiplication and a division.    */   sd = mpn_gcdext(DATA(d), DATA(u), &su, DATA(a), SIZE(a), DATA(n), SIZE(n));   SIZE(d) = sd;   SIZE(u) = su;   if (ONEP(d)) {      if (_ntl_gsign(u) < 0) _ntl_gadd(u, nin, &u);      _ntl_gcopy(u, invv);      return 0;   }   else {      _ntl_gcopy(d, invv);      return 1;   }}void_ntl_ginvmod(	_ntl_gbigint a,	_ntl_gbigint n,	_ntl_gbigint *c	){	if (_ntl_ginv(a, n, c))		ghalt("undefined inverse in _ntl_ginvmod");}void_ntl_gaddmod(	_ntl_gbigint a,	_ntl_gbigint b,	_ntl_gbigint n,	_ntl_gbigint *c	){	if (*c != n) {		_ntl_gadd(a, b, c);		if (_ntl_gcompare(*c, n) >= 0)			_ntl_gsubpos(*c, n, c);	}	else {		static _ntl_gbigint mem = 0;		_ntl_gadd(a, b, &mem);		if (_ntl_gcompare(mem, n) >= 0)			_ntl_gsubpos(mem, n, c);		_ntl_gcopy(mem, c);	}}void_ntl_gsubmod(	_ntl_gbigint a,	_ntl_gbigint b,	_ntl_gbigint n,	_ntl_gbigint *c	){	static _ntl_gbigint mem = 0;	long cmp;	if ((cmp=_ntl_gcompare(a, b)) < 0) {		_ntl_gadd(n, a, &mem);		_ntl_gsubpos(mem, b, c);	} else if (!cmp) 		_ntl_gzero(c);	else 		_ntl_gsubpos(a, b, c);}void_ntl_gsmulmod(	_ntl_gbigint a,	long d,	_ntl_gbigint n,	_ntl_gbigint *c	){	static _ntl_gbigint mem = 0;	_ntl_gsmul(a, d, &mem);	_ntl_gmod(mem, n, c);}void_ntl_gmulmod(	_ntl_gbigint a,	_ntl_gbigint b,	_ntl_gbigint n,	_ntl_gbigint *c	){	static _ntl_gbigint mem = 0;	_ntl_gmul(a, b, &mem);	_ntl_gmod(mem, n, c);}void_ntl_gsqmod(	_ntl_gbigint a,	_ntl_gbigint n,	_ntl_gbigint *c	){	_ntl_gmulmod(a, a, n, c);}double _ntl_gdoub_aux(_ntl_gbigint n){   double res;   mp_limb_t *ndata;   long i, sn, nneg;   if (!n)      return ((double) 0);   GET_SIZE_NEG(sn, nneg, n);   ndata = DATA(n);   res = 0;   for (i = sn-1; i >= 0; i--)      res = res * NTL_ZZ_FRADIX + ((double) ndata[i]);   if (nneg) res = -res;   return res;}long _ntl_ground_correction(_ntl_gbigint a, long k, long residual){   long direction;   long p;   long sgn;   long bl;   mp_limb_t wh;   long i;   mp_limb_t *adata;   if (SIZE(a) > 0)      sgn = 1;   else      sgn = -1;   adata = DATA(a);   p = k - 1;   bl = (p/NTL_ZZ_NBITS);   wh = ((mp_limb_t) 1) << (p - NTL_ZZ_NBITS*bl);   if (adata[bl] & wh) {      /* bit is 1...we have to see if lower bits are all 0         in order to implement "round to even" */      if (adata[bl] & (wh - ((mp_limb_t) 1)))          direction = 1;      else {         i = bl - 1;         while (i >= 0 && adata[i] == 0) i--;         if (i >= 0)            direction = 1;         else            direction = 0;      }      /* use residual to break ties */      if (direction == 0 && residual != 0) {         if (residual == sgn)            direction = 1;         else             direction = -1;      }      if (direction == 0) {         /* round to even */         wh = wh << 1;         if (wh == 0) {            wh = 1;            bl++;         }         if (adata[bl] & wh)            direction = 1;         else            direction = -1;      }   }   else      direction = -1;   if (direction == 1)      return sgn;   return 0;}double _ntl_gdoub(_ntl_gbigint n){   static _ntl_gbigint tmp = 0;   long s;   long shamt;   long correction;   double x;   s = _ntl_g2log(n);   shamt = s - NTL_DOUBLE_PRECISION;   if (shamt <= 0)      return _ntl_gdoub_aux(n);   _ntl_grshift(n, shamt, &tmp);   correction = _ntl_ground_correction(n, shamt, 0);   if (correction) _ntl_gsadd(tmp, correction, &tmp);   x = _ntl_gdoub_aux(tmp);   /* We could just write x = ldexp(x, shamt); however, if long's    * are bigger than int's, there is the possibility that shamt would be    * truncated.  We could check for this and raise an error, but    * it is preferable to do it this way to get +/- infinity, if    * possible. */   while (shamt > 1024) {      x = ldexp(x, 1024);      shamt -= 1024;   }   x = ldexp(x, shamt);   return x;}double _ntl_glog(_ntl_gbigint n){   static _ntl_gbigint tmp = 0;   static double log_2;   static long init = 0;   long s;   long shamt;   long correction;   double x;   if (!init) {      log_2 = log(2.0);      init = 1;   }   if (_ntl_gsign(n) <= 0)      ghalt("log argument <= 0");   s = _ntl_g2log(n);   shamt = s - NTL_DOUBLE_PRECISION;   if (shamt <= 0)      return log(_ntl_gdoub_aux(n));   _ntl_grshift(n, shamt, &tmp);   correction = _ntl_ground_correction(n, shamt, 0);   if (correction) _ntl_gsadd(tmp, correction, &tmp);   x = _ntl_gdoub_aux(tmp);   return log(x) + shamt*log_2;}/* To implement _ntl_gdoubtoz, I've implemented essentially the * same algorithm as in LIP, processing in blocks of * NTL_SP_NBITS bits, rather than NTL_ZZ_NBITS. * This is conversion is rather delicate, and I don't want to * make any new assumptions about the underlying arithmetic. * This implementation should be quite portable. */void _ntl_gdoubtoz(double a, _ntl_gbigint *xx){   static _ntl_gbigint x = 0;   long neg, i, t, sz;   a = floor(a);   if (!_ntl_IsFinite(&a))      ghalt("_ntl_gdoubtoz: attempt to convert non-finite value");   if (a < 0) {      a = -a;      neg = 1;   }   else      neg = 0;   if (a == 0) {      _ntl_gzero(xx);      return;   }   sz = 0;   while (a >= 1) {      a = a*(1.0/NTL_SP_FBOUND);      sz++;   }   i = 0;   _ntl_gzero(&x);   while (a != 0) {      i++;      a = a*NTL_SP_FBOUND;      t = (long) a;      a = a - t;      if (i == 1) {         _ntl_gintoz(t, &x);      }      else {         _ntl_glshift(x, NTL_SP_NBITS, &x);         _ntl_gsadd(x, t, &x);      }   }   if (i > sz) ghalt("bug in _ntl_gdoubtoz");   _ntl_glshift(x, (sz-i)*NTL_SP_NBITS, xx);   if (neg) _ntl_gnegate(xx);}/* I've adapted LIP's extended euclidean algorithm to * do rational reconstruction.  -- VJS. */long _ntl_gxxratrecon(   _ntl_gbigint ain,   _ntl_gbigint nin,   _ntl_gbigint num_bound,   _ntl_gbigint den_bound,   _ntl_gbigint *num_out,   _ntl_gbigint *den_out   ){   static _ntl_gbigint a = 0;   static _ntl_gbigint n = 0;   static _ntl_gbigint q = 0;   static _ntl_gbigint w = 0;   static _ntl_gbigint x = 0;   static _ntl_gbigint y = 0;   static _ntl_gbigint z = 0;   static _ntl_gbigint inv = 0;   static _ntl_gbigint u = 0;   static _ntl_gbigint a_bak = 0;   static _ntl_gbigint n_bak = 0;   static _ntl_gbigint inv_bak = 0;   static _ntl_gbigint w_bak = 0;   mp_limb_t *p;   long diff;   long ilo;   long sa;   long sn;   long snum;   long sden;   long e;   long fast;   long temp;   long parity;   long gotthem;   long try11;   long try12;   long try21;   long try22;   long got11;   long got12;   long got21;   long got22;   double hi;   double lo;   double dt;   double fhi, fhi1;   double flo, flo1;   double num;   double den;   double dirt;   if (_ntl_gsign(num_bound) < 0)      ghalt("rational reconstruction: bad numerator bound");   if (!num_bound)      snum = 0;   else      snum = SIZE(num_bound);   if (_ntl_gsign(den_bound) <= 0)      ghalt("rational reconstruction: bad denominator bound");   sden = SIZE(den_bound);   if (_ntl_gsign(nin) <= 0)      ghalt("rational reconstruction: bad modulus");   if (_ntl_gsign(ain) < 0 || _ntl_gcompare(ain, nin) >= 0)      ghalt("rational reconstruction: bad residue");         e = SIZE(nin);   _ntl_gsetlength(&a, e);   _ntl_gsetlength(&n, e);   _ntl_gsetlength(&q, e);   _ntl_gsetlength(&w, e);   _ntl_gsetlength(&x, e);   _ntl_gsetlength(&y, e);   _ntl_gsetlength(&z, e);   _ntl_gsetlength(&inv, e);   _ntl_gsetlength(&u, e);   _ntl_gsetlength(&a_bak, e);   _ntl_gsetlength(&n_bak, e);   _ntl_gsetlength(&inv_bak, e);   _ntl_gsetlength(&w_bak, e);   fhi1 = 1.0 + ((double) 32.0)/NTL_FDOUBLE_PRECISION;   flo1 = 1.0 - ((double) 32.0)/NTL_FDOUBLE_PRECISION;   fhi = 1.0 + ((double) 8.0)/NTL_FDOUBLE_PRECISION;   flo = 1.0 - ((double) 8.0)/NTL_FDOUBLE_PRECISION;   _ntl_gcopy(ain, &a);   _ntl_gcopy(nin, &n);

⌨️ 快捷键说明

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