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

📄 g_lip.c

📁 密码大家Shoup写的数论算法c语言实现
💻 C
📖 第 1 页 / 共 5 页
字号:
#include <NTL/lip.h>#include <NTL/IsFinite.h>#include <stdlib.h>#include <stdio.h>#include <math.h>#include <gmp.h>typedef mp_limb_t *_ntl_limb_t_ptr;int _ntl_gmp_hack = 0;#if (__GNU_MP_VERSION < 3)#error "You have to use GNP version >= 3.1"#endif#if ((__GNU_MP_VERSION == 3) && (__GNU_MP_VERSION_MINOR < 1))#error "You have to use GNP version >= 3.1"#endif/* v 3.1 is supposed  mpn_tdiv_qr defined, but it doesn't.   Here's a workaround */#if ((__GNU_MP_VERSION == 3) && (__GNU_MP_VERSION_MINOR == 1) && (__GNU_MP_VERSION_PATCHLEVEL == 0))#define mpn_tdiv_qr __MPN(tdiv_qr)#ifdef __cplusplusextern "C" #endifvoid mpn_tdiv_qr(mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t,                  mp_srcptr, mp_size_t);#endif#if (defined(NTL_CXX_ONLY) && !defined(__cplusplus))#error "CXX_ONLY flag set...must use C++ compiler"#endifunion gbigint_header {   long info[2];   mp_limb_t alignment;};/* A bigint is represented as two long's, ALLOC and SIZE, followed by a  * vector DATA of mp_limb_t's.   *  * ALLOC is of the form *    (alloc << 2) | continue_flag | frozen_flag * where  *    - alloc is the number of allocated mp_limb_t's, *    - continue flag is either 2 or 0, *    - frozen_flag is either 1 or 0. * If frozen_flag is set, then the space for this bigint is *not* * managed by the _ntl_gsetlength and _ntl_gfree routines, * but are instead managed by the vec_ZZ_p and ZZVec routines. * The continue_flag is only set when the frozen_flag is set. *  * SIZE is the number of mp_limb_t's actually * used by the bigint, with the sign of SIZE having * the sign of the bigint. * Note that the zero bigint is represented as SIZE=0. *  * Bigint's are accessed through a handle, which is pointer to void. * A null handle logically represents the bigint zero. * This is done so that the interface presented to higher level * routines is essentially the same as that of NTL's traditional * long integer package. *  * The components ALLOC, SIZE, and DATA are all accessed through * macros using pointer casts.  While all of may seem a bit dirty,  * it should be quite portable: objects are never referenced * through pointers of different types, and no alignmement * problems should arise. *  * Actually, mp_limb_t is usually the type unsigned long. * However, on some 64-bit platforms, the type long is only 32 bits, * and gmp makes mp_limb_t unsigned long long in this case. * This is fairly rare, as the industry standard for Unix is to * have 64-bit longs on 64-bit machines. */ #if 1#define ALLOC(p) (((long *) (p))[0])#define SIZE(p) (((long *) (p))[1])#define DATA(p) ((mp_limb_t *) (((long *) (p)) + 2))#define STORAGE(len) ((long)(2*sizeof(long) + (len)*sizeof(mp_limb_t)))/* STORAGE computes the number of bytes to allocate for a bigint * of maximal SIZE len.  This should be computed so that one * can store several such bigints in a contiguous array * of memory without breaking any alignment requirements. * Currently, it is assumed (and explicitly checked in the NTL installation * script) that sizeof(mp_limb_t) is either sizeof(long) or * 2*sizeof(long), and therfore, nothing special needs to * be done to enfoce alignment requirements.  If this assumption * should change, then the storage layout for bigints must be * re-designed.   However, this is very unlikely to ever happen. *  */#define MustAlloc(c, len)  (!(c) || (ALLOC(c) >> 2) < (len))#define GET_SIZE_NEG(sz, neg, p)  \do  \{   \   long _s;   \   _s = SIZE(p);   \   if (_s < 0) {  \      sz = -_s;  \      neg = 1;  \   }  \   else {  \      sz = _s;  \      neg = 0;  \   }  \}  \while (0)#define STRIP(sz, p)  \do  \{  \   long _i;  \   _i = sz - 1;  \   while (_i >= 0 && p[_i] == 0) _i--;  \   sz = _i + 1;  \}  \while (0) #define ZEROP(p) (!p || !SIZE(p))#define ONEP(p) (p && SIZE(p) == 1 && DATA(p)[0] == 1)#define SWAP_BIGINT(a, b)  \do  \{  \   _ntl_gbigint _t;  \   _t = a;  \   a = b;  \   b = _t;  \}  \while (0) #define SWAP_LONG(a, b)  \do  \{  \   long _t;  \   _t = a;  \   a = b;  \   b = _t;  \}  \while (0) #define SWAP_LIMB_PTR(a, b)  \do  \{  \   _ntl_limb_t_ptr _t;  \   _t = a;  \   a = b;  \   b = _t;  \}  \while (0) #define COUNT_BITS(cnt, a)  \do  \{  \   long _i = 0;  \   mp_limb_t _a = (a);  \  \   while (_a>=256)  \      _i += 8, _a >>= 8;  \   if (_a >=16)  \      _i += 4, _a >>= 4;  \   if (_a >= 4)  \      _i += 2, _a >>= 2;  \   if (_a >= 2)  \      _i += 2;  \   else if (_a >= 1)  \      _i++;  \  \   cnt = _i;  \}  \while (0) #else/* These are C++ inline functions that are equivalent to the above * macros.  They are mainly intended as a debugging aid. */inline long& ALLOC(_ntl_gbigint p)    { return (((long *) p)[0]); }inline long& SIZE(_ntl_gbigint p)    { return (((long *) p)[1]); }inline mp_limb_t * DATA(_ntl_gbigint p)    { return ((mp_limb_t *) (((long *) (p)) + 2)); }inline long STORAGE(long len)   { return ((long)(2*sizeof(long) + (len)*sizeof(mp_limb_t))); }inline long MustAlloc(_ntl_gbigint c, long len)     { return (!(c) || (ALLOC(c) >> 2) < (len)); }inline void GET_SIZE_NEG(long& sz, long& neg, _ntl_gbigint p){    long s;    s = SIZE(p);    if (s < 0) {      sz = -s;      neg = 1;   }   else {      sz = s;      neg = 0;   }}inline void STRIP(long& sz, mp_limb_t *p){   long i;   i = sz - 1;   while (i >= 0 && p[i] == 0) i--;   sz = i + 1;}inline long ZEROP(_ntl_gbigint p){   return !p || !SIZE(p);}inline long ONEP(_ntl_gbigint p){   return p && SIZE(p) == 1 && DATA(p)[0] == 1;}inline void SWAP_BIGINT(_ntl_gbigint& a, _ntl_gbigint& b){   _ntl_gbigint t;   t = a;   a = b;   b = t;}inline void SWAP_LONG(long& a, long& b){   long t;   t = a;   a = b;   b = t;}inline void SWAP_LIMB_PTR(_ntl_limb_t_ptr& a, _ntl_limb_t_ptr& b){   _ntl_limb_t_ptr t;   t = a;   a = b;   b = t;}inline void COUNT_BITS(long& cnt, mp_limb_t a){   long i = 0;   while (a>=256)      i += 8, a >>= 8;   if (a >=16)      i += 4, a >>= 4;   if (a >= 4)      i += 2, a >>= 2;   if (a >= 2)      i += 2;   else if (a >= 1)      i++;   cnt = i;}#endifstatic void ghalt(char *c){   fprintf(stderr,"fatal error:\n   %s\nexit...\n",c);   fflush(stderr);   abort();}#define MIN_SETL	(4)   /* _ntl_gsetlength allocates a multiple of MIN_SETL digits */void _ntl_gsetlength(_ntl_gbigint *v, long len){   _ntl_gbigint x = *v;   if (len < 0)      ghalt("negative size allocation in _ntl_zgetlength");   if (len >= (1L << (NTL_BITS_PER_LONG-4))/NTL_ZZ_NBITS)      ghalt("size too big in _ntl_gsetlength");#ifdef NTL_SMALL_MP_SIZE_T   /* this makes sure that numbers don't get too big for GMP */   if (len >= (1L << (NTL_BITS_PER_INT-4)))      ghalt("size too big for GMP");#endif   if (x) {      long oldlen = ALLOC(x);      long fixed = oldlen & 1;      oldlen = oldlen >> 2;      if (fixed) {         if (len > oldlen)             ghalt("internal error: can't grow this _ntl_gbigint");         else            return;      }      if (len <= oldlen) return;      len++;  /* always allocate at least one more than requested */      oldlen = (long) (oldlen * 1.2); /* always increase by at least 20% */      if (len < oldlen)         len = oldlen;      /* round up to multiple of MIN_SETL */      len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL;       /* test len again */      if (len >= (1L << (NTL_BITS_PER_LONG-4))/NTL_ZZ_NBITS)         ghalt("size too big in _ntl_gsetlength");      ALLOC(x) = len << 2;      if (!(x = (_ntl_gbigint)realloc((void*) x, STORAGE(len)))) {         ghalt("reallocation failed in _ntl_gsetlength");      }   }   else {      len++;      len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL;      /* test len again */      if (len >= (1L << (NTL_BITS_PER_LONG-4))/NTL_ZZ_NBITS)         ghalt("size too big in _ntl_gsetlength");      if (!(x = (_ntl_gbigint)malloc(STORAGE(len)))) {         ghalt("allocation failed in _ntl_gsetlength");      }      ALLOC(x) = len << 2;      SIZE(x) = 0;   }   *v = x;}void _ntl_gfree(_ntl_gbigint *xx){   _ntl_gbigint x = *xx;   if (!x)      return;   if (ALLOC(x) & 1)      ghalt("Internal error: can't free this _ntl_gbigint");   free((void*) x);   *xx = 0;   return;}void_ntl_gswap(_ntl_gbigint *a, _ntl_gbigint *b){   _ntl_gbigint c;   if ((*a && (ALLOC(*a) & 1)) || (*b && (ALLOC(*b) & 1))) {      static _ntl_gbigint t = 0;       _ntl_gcopy(*a, &t);      _ntl_gcopy(*b, a);      _ntl_gcopy(t, b);      return;   }   c = *a;   *a = *b;   *b = c;}void _ntl_gcopy(_ntl_gbigint a, _ntl_gbigint *bb){   _ntl_gbigint b;   long sa, abs_sa, i;   mp_limb_t *adata, *bdata;   b = *bb;   if (!a || (sa = SIZE(a)) == 0) {      if (b) SIZE(b) = 0;   }   else {      if (a != b) {         if (sa >= 0)            abs_sa = sa;         else            abs_sa = -sa;         if (MustAlloc(b, abs_sa)) {            _ntl_gsetlength(&b, abs_sa);            *bb = b;         }         adata = DATA(a);         bdata = DATA(b);         for (i = 0; i < abs_sa; i++)            bdata[i] = adata[i];         SIZE(b) = sa;      }   }}void _ntl_gzero(_ntl_gbigint *aa) {   _ntl_gbigint a = *aa;   if (a) SIZE(a) = 0;}void _ntl_gone(_ntl_gbigint *aa){   _ntl_gbigint a = *aa;   if (!a) {      _ntl_gsetlength(&a, 1);      *aa = a;   }   SIZE(a) = 1;   DATA(a)[0] = 1;}long _ntl_giszero(_ntl_gbigint a){   return ZEROP(a);}long _ntl_godd(_ntl_gbigint a){   if (ZEROP(a))       return 0;   else      return DATA(a)[0]&1;}long _ntl_gbit(_ntl_gbigint a, long p){   long bl;   long sa;   mp_limb_t wh;   if (p < 0 || !a) return 0;   bl = p/NTL_ZZ_NBITS;   wh = ((mp_limb_t) 1) << (p - NTL_ZZ_NBITS*bl);   sa = SIZE(a);   if (sa < 0) sa = -sa;   if (sa <= bl) return 0;   if (DATA(a)[bl] & wh) return 1;   return 0;}void _ntl_glowbits(_ntl_gbigint a, long b, _ntl_gbigint *cc){   _ntl_gbigint c = *cc;   long bl;   long wh;   long sa;   long i;   mp_limb_t *adata, *cdata;   if (ZEROP(a) || (b<=0)) {      _ntl_gzero(cc);      return;   }   bl = b/NTL_ZZ_NBITS;   wh = b - NTL_ZZ_NBITS*bl;   if (wh != 0)       bl++;   else      wh = NTL_ZZ_NBITS;   sa = SIZE(a);   if (sa < 0) sa = -sa;   if (sa < bl) {      _ntl_gcopy(a,cc);      _ntl_gabs(cc);      return;   }   _ntl_gsetlength(&c, bl);   if (a == *cc) a = c;   *cc = c;   adata = DATA(a);   cdata = DATA(c);   for (i = 0; i < bl-1; i++)      cdata[i] = adata[i];   if (wh == NTL_ZZ_NBITS)      cdata[bl-1] = adata[bl-1];   else      cdata[bl-1] = adata[bl-1] & ((((mp_limb_t) 1) << wh) - ((mp_limb_t) 1));   STRIP(bl, cdata);   SIZE(c) = bl; }long _ntl_gslowbits(_ntl_gbigint a, long p){   static _ntl_gbigint x = 0;   _ntl_glowbits(a, p, &x);   return _ntl_gtoint(x);}long _ntl_gsetbit(_ntl_gbigint *a, long b){   long bl;   long sa, aneg;   long i;   mp_limb_t wh, *adata, tmp;   if (b<0) ghalt("_ntl_gsetbit: negative index");   if (ZEROP(*a)) {      _ntl_gintoz(1, a);      _ntl_glshift(*a, b, a);      return 0;   }   bl = (b/NTL_ZZ_NBITS);   wh = ((mp_limb_t) 1) << (b - NTL_ZZ_NBITS*bl);   GET_SIZE_NEG(sa, aneg, *a);   if (sa > bl) {      adata = DATA(*a);      tmp = adata[bl] & wh;      adata[bl] |= wh;      if (tmp) return 1;      return 0;   }    else {      _ntl_gsetlength(a, bl+1);      adata = DATA(*a);      for (i = sa; i < bl; i++)         adata[i] = 0;      adata[bl] = wh;      sa = bl+1;      if (aneg) sa = -sa;      SIZE(*a) = sa;      return 0;   }}long _ntl_gswitchbit(_ntl_gbigint *a, long b){   long bl;   long sa, aneg;   long i;   mp_limb_t wh, *adata, tmp;   if (b<0) ghalt("_ntl_gswitchbit: negative index");   if (ZEROP(*a)) {      _ntl_gintoz(1, a);      _ntl_glshift(*a, b, a);      return 0;   }   bl = (b/NTL_ZZ_NBITS);   wh = ((mp_limb_t) 1) << (b - NTL_ZZ_NBITS*bl);   GET_SIZE_NEG(sa, aneg, *a);   if (sa > bl) {      adata = DATA(*a);      tmp = adata[bl] & wh;      adata[bl] ^= wh;      if (bl == sa-1) {         STRIP(sa, adata);         if (aneg) sa = -sa;         SIZE(*a) = sa;      }      if (tmp) return 1;      return 0;   }    else {      _ntl_gsetlength(a, bl+1);      adata = DATA(*a);      for (i = sa; i < bl; i++)         adata[i] = 0;      adata[bl] = wh;      sa = bl+1;      if (aneg) sa = -sa;      SIZE(*a) = sa;      return 0;   }}long_ntl_gweights(	long aa	){	unsigned long a;	long res = 0;	if (aa < 0) 		a = -aa;	else		a = aa;   	while (a) {		if (a & 1) res ++;		a >>= 1;	}	return (res);}static longgweights_mp_limb(	mp_limb_t a	){	long res = 0;   	while (a) {		if (a & 1) res ++;		a >>= 1;	}	return (res);}long_ntl_gweight(        _ntl_gbigint a        ){	long i;	long sa;	mp_limb_t *adata;	long res;	if (!a) return (0);	sa = SIZE(a);	if (sa < 0) sa = -sa;	adata = DATA(a);

⌨️ 快捷键说明

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