static PyObject * GMPy_MPZ_Function_GCDext(PyObject *self, PyObject *args) { PyObject *arg0, *arg1, *result = NULL; MPZ_Object *g = NULL, *s = NULL, *t = NULL, *tempa = NULL, *tempb = NULL; if(PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("gcdext() requires 'mpz','mpz' arguments"); return NULL; } if (!(result = PyTuple_New(3)) || !(g = GMPy_MPZ_New(NULL)) || !(s = GMPy_MPZ_New(NULL)) || !(t = GMPy_MPZ_New(NULL))) { /* LCOV_EXCL_START */ Py_XDECREF((PyObject*)g); Py_XDECREF((PyObject*)s); Py_XDECREF((PyObject*)t); Py_XDECREF(result); return NULL; /* LCOV_EXCL_STOP */ } arg0 = PyTuple_GET_ITEM(args, 0); arg1 = PyTuple_GET_ITEM(args, 1); if (MPZ_Check(arg0) && MPZ_Check(arg1)) { mpz_gcdext(g->z, s->z, t->z, MPZ(arg0), MPZ(arg1)); } else { if(!(tempa = GMPy_MPZ_From_Integer(arg0, NULL)) || !(tempb = GMPy_MPZ_From_Integer(arg1, NULL))) { TYPE_ERROR("gcdext() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempa); Py_XDECREF((PyObject*)tempb); Py_DECREF((PyObject*)g); Py_DECREF((PyObject*)s); Py_DECREF((PyObject*)t); Py_DECREF(result); return NULL; } mpz_gcdext(g->z, s->z, t->z, tempa->z, tempb->z); Py_DECREF((PyObject*)tempa); Py_DECREF((PyObject*)tempb); } PyTuple_SET_ITEM(result, 0, (PyObject*)g); PyTuple_SET_ITEM(result, 1, (PyObject*)s); PyTuple_SET_ITEM(result, 2, (PyObject*)t); return result; }
/* wraps mpz_gcdext() * * Set g to the greatest common divisor of x and y, and in addition * set s and t to coefficients satisfying x*s + y*t = g. * * The {gp,gn} array is zero-padded (as otherwise 'gn' can't be * reconstructed). * * g must have space for exactly gn=min(xn,yn) limbs. * s must have space for at least xn limbs. * * return value: signed 'sn' of {sp,sn} */ mp_size_t integer_gmp_gcdext(mp_limb_t s0[], mp_limb_t g0[], const mp_limb_t x0[], const mp_size_t xn, const mp_limb_t y0[], const mp_size_t yn) { const mp_size_t gn0 = mp_size_minabs(xn, yn); const mpz_t x = CONST_MPZ_INIT(x0, mp_limb_zero_p(x0,xn) ? 0 : xn); const mpz_t y = CONST_MPZ_INIT(y0, mp_limb_zero_p(y0,yn) ? 0 : yn); mpz_t g, s; mpz_init (g); mpz_init (s); mpz_gcdext (g, s, NULL, x, y); const mp_size_t gn = g[0]._mp_size; assert(0 <= gn && gn <= gn0); memset(g0, 0, gn0*sizeof(mp_limb_t)); memcpy(g0, g[0]._mp_d, gn*sizeof(mp_limb_t)); mpz_clear (g); const mp_size_t ssn = s[0]._mp_size; const mp_size_t sn = mp_size_abs(ssn); assert(sn <= xn); memcpy(s0, s[0]._mp_d, sn*sizeof(mp_limb_t)); mpz_clear (s); if (!sn) { s0[0] = 0; return 1; } return ssn; }
static Variant HHVM_FUNCTION(gmp_gcdext, const Variant& dataA, const Variant& dataB) { mpz_t gmpDataA, gmpDataB, gmpReturnG, gmpReturnS, gmpReturnT; if (!variantToGMPData(cs_GMP_FUNC_NAME_GMP_GCDEXCT, gmpDataA, dataA)) { return false; } if (!variantToGMPData(cs_GMP_FUNC_NAME_GMP_GCDEXCT, gmpDataB, dataB)) { mpz_clear(gmpDataA); return false; } mpz_init(gmpReturnG); mpz_init(gmpReturnS); mpz_init(gmpReturnT); mpz_gcdext(gmpReturnG, gmpReturnS, gmpReturnT, gmpDataA, gmpDataB); ArrayInit returnArray(3, ArrayInit::Map{}); returnArray.set(s_gmp_g, NEWOBJ(GMPResource)(gmpReturnG)); returnArray.set(s_gmp_s, NEWOBJ(GMPResource)(gmpReturnS)); returnArray.set(s_gmp_t, NEWOBJ(GMPResource)(gmpReturnT)); mpz_clear(gmpDataA); mpz_clear(gmpDataB); mpz_clear(gmpReturnG); mpz_clear(gmpReturnS); mpz_clear(gmpReturnT); return returnArray.toVariant(); }
/* Puts in inv[0..l-1] the inverses of a[0..l-1] (mod n), using 3*(l-1) multiplies and one gcdext. Returns 1 if a factor was found (stored in t), 0 otherwise. */ int list_invert (listz_t inv, listz_t a, unsigned long l, mpz_t t, mpmod_t modulus) { unsigned long i; if (l == 0) return 0; mpz_set (inv[0], a[0]); for (i = 1; i < l; i++) { mpz_mul (t, inv[i-1], a[i]); mpz_mod (inv[i], t, modulus->orig_modulus); /* inv[i] = a[0]*...*a[i] */ } mpz_gcdext (t, inv[l-1], NULL, inv[l-1], modulus->orig_modulus); if (mpz_cmp_ui (t, 1) != 0) return 1; for (i = l-1; i > 0; i--) { mpz_mul (t, inv[i], inv[i-1]); /* t = (a[0]*...*a[i])^(-1) * (a[0]*...*a[i-1]) = a[i]^(-1) */ mpz_mul (inv[i-1], inv[i], a[i]); /* inv[i-1] = (a[0]*...*a[i])^(-1) * a[i] = (a[0]*...*a[i-1])^(-1) */ mpz_mod (inv[i-1], inv[i-1], modulus->orig_modulus); mpz_mod (inv[i], t, modulus->orig_modulus); } return 0; }
void xgcd_mpz_s128(s128_t* out_g, s128_t* out_s, s128_t* out_t, const s128_t* in_u, const s128_t* in_v) { if (s128_is_s64(in_u) && s128_is_s64(in_v)) { int64_t s; int64_t t; int64_t g = xgcd_mpz_s64(&s, &t, in_u->v0, in_v->v0); set_s128_s64(out_g, g); set_s128_s64(out_s, s); set_s128_s64(out_t, t); return; } // NOTE: We hack the structure of an mpz_t so that // it uses stack memory. We use 256-bits instead of 128-bits // since it seems that some intermediate numbers use more than // 128-bits. We hope that 256-bits is enough. mpz_t g; mpz_t s; mpz_t t; mpz_t u; mpz_t v; uint64_t g_[4]; uint64_t s_[4]; uint64_t t_[4]; uint64_t u_[4]; uint64_t v_[4]; g->_mp_alloc = 256 / GMP_LIMB_BITS; g->_mp_size = 0; g->_mp_d = (mp_limb_t*)g_; s->_mp_alloc = 256 / GMP_LIMB_BITS; s->_mp_size = 0; s->_mp_d = (mp_limb_t*)s_; t->_mp_alloc = 256 / GMP_LIMB_BITS; t->_mp_size = 0; t->_mp_d = (mp_limb_t*)t_; u->_mp_alloc = 256 / GMP_LIMB_BITS; u->_mp_size = 0; u->_mp_d = (mp_limb_t*)u_; v->_mp_alloc = 256 / GMP_LIMB_BITS; v->_mp_size = 0; v->_mp_d = (mp_limb_t*)v_; mpz_set_ui(g, 0); mpz_set_ui(s, 0); mpz_set_ui(t, 0); s128_to_mpz(in_u, u); s128_to_mpz(in_v, v); mpz_gcdext(g, s, t, u, v); s128_from_mpz(out_g, g); s128_from_mpz(out_s, s); s128_from_mpz(out_t, t); }
void Bezout<>(boost::multiprecision::mpz_int a, boost::multiprecision::mpz_int b, boost::multiprecision::mpz_int& x, boost::multiprecision::mpz_int& y) { boost::multiprecision::mpz_int g = 1; mpz_gcdext (g.backend().data(), x.backend().data(), y.backend().data(), a.backend().data(), b.backend().data()); }
ring_elem RingZZ::gcd_extended(const ring_elem f, const ring_elem g, ring_elem &u, ring_elem &v) const { mpz_ptr result = new_elem(); mpz_ptr u1 = new_elem(); mpz_ptr v1 = new_elem(); mpz_gcdext(result, u1, v1, f.get_mpz(), g.get_mpz()); u = ring_elem(u1); v = ring_elem(v1); return ring_elem(result); }
void mpz_sqrtmn (mpz_ptr root, mpz_srcptr a, mpz_srcptr p, mpz_srcptr q, mpz_srcptr n) { mpz_t g, u, v; mpz_init(g), mpz_init(u), mpz_init(v); mpz_gcdext(g, u, v, p, q); if (mpz_cmp_ui(g, 1L) == 0) { mpz_t root_p, root_q, root1, root2, root3, root4; /* single square roots */ mpz_init(root_p), mpz_init(root_q); mpz_sqrtmp(root_p, a, p); mpz_sqrtmp(root_q, a, q); /* construct common square root */ mpz_init_set(root1, root_q); mpz_init_set(root2, root_p); mpz_init_set(root3, root_q); mpz_init_set(root4, root_p); mpz_mul(root1, root1, u); mpz_mul(root1, root1, p); mpz_mul(root2, root2, v); mpz_mul(root2, root2, q); mpz_add(root1, root1, root2); mpz_mod(root1, root1, n); mpz_sqrtmn_2(root2, root1, n); mpz_neg(root3, root3); mpz_mul(root3, root3, u); mpz_mul(root3, root3, p); mpz_mul(root4, root4, v); mpz_mul(root4, root4, q); mpz_add(root3, root3, root4); mpz_mod(root3, root3, n); mpz_sqrtmn_2 (root4, root3, n); /* choose smallest root */ mpz_set(root, root1); if (mpz_cmpabs(root2, root) < 0) mpz_set(root, root2); if (mpz_cmpabs(root3, root) < 0) mpz_set(root, root3); if (mpz_cmpabs(root4, root) < 0) mpz_set(root, root4); mpz_clear(root_p), mpz_clear(root_q); mpz_clear(root1), mpz_clear(root2); mpz_clear(root3), mpz_clear(root4); mpz_clear(g), mpz_clear(u), mpz_clear(v); return; } mpz_clear(g), mpz_clear(u), mpz_clear(v); /* error, return zero root */ mpz_set_ui(root, 0L); }
mpz_class invertMultiplicative(const mpz_class& x, const mpz_class& p) { if (x == p - 1 || x == 1) return x; mpz_t gcd, s, t; mpz_init(gcd); mpz_init(s); mpz_init(t); mpz_gcdext(gcd, s, t, x.get_mpz_t(), p.get_mpz_t()); mpz_class inverse(s); if (inverse < 0) inverse += p; return inverse; }
int64_t xgcd_mpz_s64(int64_t* out_s, int64_t* out_t, const int64_t in_u, const int64_t in_v) { // NOTE: We hack the structure of an mpz_t so that // it uses stack memory. We use 128-bits instead of 64-bits // since it seems that some intermediate numbers use more than // 64-bits. We hope that 128-bits is enough. mpz_t g; mpz_t s; mpz_t t; mpz_t u; mpz_t v; uint64_t g_[2]; uint64_t s_[2]; uint64_t t_[2]; uint64_t u_[2]; uint64_t v_[2]; g->_mp_alloc = 128 / GMP_LIMB_BITS; g->_mp_size = 0; g->_mp_d = (mp_limb_t*)g_; s->_mp_alloc = 128 / GMP_LIMB_BITS; s->_mp_size = 0; s->_mp_d = (mp_limb_t*)s_; t->_mp_alloc = 128 / GMP_LIMB_BITS; t->_mp_size = 0; t->_mp_d = (mp_limb_t*)t_; u->_mp_alloc = 128 / GMP_LIMB_BITS; u->_mp_size = 0; u->_mp_d = (mp_limb_t*)u_; v->_mp_alloc = 128 / GMP_LIMB_BITS; v->_mp_size = 0; v->_mp_d = (mp_limb_t*)v_; mpz_set_ui(g, 0); mpz_set_ui(s, 0); mpz_set_ui(t, 0); mpz_set_si(u, in_u); mpz_set_si(v, in_v); mpz_gcdext(g, s, t, u, v); *out_s = mpz_get_si(s); *out_t = mpz_get_si(t); return mpz_get_si(g); }
void ecc_jcb_to_afn(ecc_afn_t *ROP, ecc_jcb_t *P, ecc_curve *curve) { mpz_t g, s, inv, tmp; mpz_inits(g, s, inv, tmp, NULL); mpz_gcdext(g, s, inv, curve->p, P->z); // inv = Z^1 fp_mul_mpz(tmp, inv, inv, curve->p); // (Z^1)^2 fp_mul_mpz(ROP->x, P->x, tmp, curve->p); // X*((Z^1)^2) fp_mul_mpz(tmp, tmp, inv, curve->p); // (Z^1)^3 fp_mul_mpz(ROP->y, P->y, tmp, curve->p); // Y*((Z^1)^3) mpz_clears(g, s, inv, tmp, NULL); }
int mpz_invert (mpz_ptr inverse, mpz_srcptr x, mpz_srcptr n) { mpz_t gcd, tmp; mp_size_t xsize, nsize, size; TMP_DECL (marker); xsize = SIZ (x); nsize = SIZ (n); xsize = ABS (xsize); nsize = ABS (nsize); size = MAX (xsize, nsize) + 1; /* No inverse exists if the leftside operand is 0. Likewise, no inverse exists if the mod operand is 1. */ if (xsize == 0 || (nsize == 1 && (PTR (n))[0] == 1)) return 0; TMP_MARK (marker); MPZ_TMP_INIT (gcd, size); MPZ_TMP_INIT (tmp, size); mpz_gcdext (gcd, tmp, (mpz_ptr) 0, x, n); /* If no inverse existed, return with an indication of that. */ if (SIZ (gcd) != 1 || PTR(gcd)[0] != 1) { TMP_FREE (marker); return 0; } /* Make sure we return a positive inverse. */ if (SIZ (tmp) < 0) { if (SIZ (n) < 0) mpz_sub (inverse, tmp, n); else mpz_add (inverse, tmp, n); } else mpz_set (inverse, tmp); TMP_FREE (marker); return 1; }
void gcd_ext(const Ptr<RCP<const Integer>> &g, const Ptr<RCP<const Integer>> &s, const Ptr<RCP<const Integer>> &t, const Integer &a, const Integer &b) { mpz_t g_t; mpz_t s_t; mpz_t t_t; mpz_init(g_t); mpz_init(s_t); mpz_init(t_t); mpz_gcdext(g_t, s_t, t_t, a.as_mpz().get_mpz_t(), b.as_mpz().get_mpz_t()); *g = integer(mpz_class(g_t)); *s = integer(mpz_class(s_t)); *t = integer(mpz_class(t_t)); mpz_clear(g_t); mpz_clear(s_t); mpz_clear(t_t); }
int qsieve_extgcd(mpz_t x, mpz_t y, mpz_t xd, mpz_t yd, mpz_t z) { mpz_gcdext(TD, TB, TC, x, y); while(qsieve_getsize(TB) < 0) { mpz_add(TB, TB, y); mpz_sub(TC, TC, x); } if(z != xd && z != yd) if(TD!=z) mpz_set(z, TD); if(xd != yd) { if(TB!=xd) mpz_set(xd, TB); if(TC!=yd) mpz_set(yd, TC); } else { if(TB!=xd) mpz_set(xd, TB); } return qsieve_getsize(TD); }
void inverse(mpz_t inv, mpz_t n, mpz_t mod) { mpz_t d, y; mpz_init(d); mpz_init(y); mpz_init(inv); mpz_gcdext(d, inv, y, n, mod); if(mpz_cmp_ui(d, 1) > 0) { /* inverse element doesn't exist */ mpz_set_ui(inv, 0); } /* keep inverse value positive */ mpz_mod(inv, inv, mod); mpz_clear(d); mpz_clear(y); return; }
/* * It is a function that generates the keys for RSA algorithm * input: mpz_t e, mpz_t, d, mpz_t n and int bitUsed; * output: mpz_t e, mpz_t d, mpz_t n */ void findRSAKeys(mpz_t e, mpz_t d, mpz_t n, int bitUsed){ mpz_t p; mpz_init(p); mpz_t q; mpz_init(q); //mpz_t n; //mpz_init(n); mpz_t p1; mpz_init(p1); mpz_t q1; mpz_init(q1); mpz_t eulerN; mpz_init(eulerN); //steps according to wikipedia //step 1 generatePrime(p, bitUsed); while(mpz_cmp_ui(q, 0) == 0 || mpz_cmp(p, q) == 0){ generatePrime(q, bitUsed); } //step 2 mpz_mul(n,p,q); //step 3 mpz_sub_ui(p1, p, 1); mpz_sub_ui(q1, q, 1); mpz_mul(eulerN, p1, q1); //step 4 //mpz_t e; //mpz_init(e); findESimple(e, eulerN); //gmp_printf("e is %Zd\n", e); //step 5 mpz_t g, s; mpz_init(g); mpz_init(s); mpz_gcdext(g, s, d, eulerN, e); }
extern void _jl_mpz_gcdext(mpz_t *g, mpz_t *s, mpz_t *t, mpz_t *a, mpz_t *b) { mpz_gcdext(*g, *s, *t, *a, *b); }
/* p-adic logarithm */ void padiclog(mpz_t ans, const mpz_t a, unsigned long p, unsigned long prec, const mpz_t modulo) { /* Compute the p-adic logarithm of a, which is supposed to be congruent to 1 mod p Algorithm: 1. we raise a at the power p^(v-1) (for a suitable v) in order to make it closer to 1 2. we write the new a as a product 1/a = (1 - a_0*p^v) (1 - a_1*p^(2*v) (1 - a_2*p^(4*v) ... with 0 <= a_i < p^(v*2^i). 3. we compute each log(1 - a_i*p^(v*2^i)) using Taylor expansion and a binary spliting strategy. */ unsigned long i, v, e, N, saveN, Np, tmp, trunc, step; double den = log(p); mpz_t f, arg, trunc_mod, h, hpow, mpz_tmp, mpz_tmp2, d, inv, mod2; mpz_t *num, *denom; mpz_init(mpz_tmp); mpz_init(mpz_tmp2); mpz_init(arg); mpz_set_ui(ans, 0); mpz_fdiv_r_ui(mpz_tmp, a, p); mpz_set(arg, a); /* First we make the argument closer to 1 by raising it to the p^(v-1) */ if (prec < p) { v = 0; e = 1; } else { v = (unsigned long)(log(prec)/den); // v here is v-1 e = pow(p,v); mpz_mul_ui(mpz_tmp, modulo, e); mpz_powm_ui(arg, arg, e, mpz_tmp); prec += v; } /* Where do we need to truncate the Taylor expansion */ N = prec+v; N /= ++v; // note the ++v Np = N; den *= v; while(1) { tmp = Np + (unsigned long)(log(N)/den); if (tmp == N) break; N = tmp; } /* We allocate memory and initialize variables */ mpz_init(f); mpz_init(mod2); mpz_init(h); mpz_init(hpow); mpz_init(d); mpz_init(inv); sig_block(); num = (mpz_t*)malloc(N*sizeof(mpz_t)); denom = (mpz_t*)malloc(N*sizeof(mpz_t)); sig_unblock(); for (i = 0; i < N; i++) { mpz_init(num[i]); mpz_init(denom[i]); } trunc = v << 1; mpz_init(trunc_mod); mpz_ui_pow_ui(trunc_mod, p, trunc); while(1) { /* We compute f = 1 - a_i*p^((v+1)*2^i) trunc_mod is p^((v+1)*2^(i+1)) */ mpz_fdiv_r(f, arg, trunc_mod); if (mpz_cmp_ui(f, 1) != 0) { mpz_ui_sub(f, 2, f); mpz_mul(arg, arg, f); /* We compute the Taylor expansion of log(f) For now, computations are carried out over the rationals */ for (i = 0; i < N; i++) { mpz_set_ui(num[i], 1); mpz_set_ui(denom[i], i+1); } step = 1; mpz_ui_sub(h, 1, f); // we write f = 1 - h, i.e. h = a_i*p^(2^i) mpz_set(hpow, h); while(step < N) { for (i = 0; i < N - step; i += step << 1) { mpz_mul(mpz_tmp2, hpow, num[i+step]); mpz_mul(mpz_tmp, mpz_tmp2, denom[i]); mpz_mul(num[i], num[i], denom[i+step]); mpz_add(num[i], num[i], mpz_tmp); mpz_mul(denom[i], denom[i], denom[i+step]); } step <<= 1; mpz_mul(hpow, hpow, hpow); } /* We simplify the fraction */ Np = N; tmp = 0; while(Np > 0) { Np /= p; tmp += Np; } mpz_ui_pow_ui(d, p, tmp); mpz_divexact(mpz_tmp, num[0], d); mpz_divexact(denom[0], denom[0], d); mpz_divexact_ui(h, h, e); mpz_mul(mpz_tmp, h, mpz_tmp); /* We coerce the result from Q to Zp */ mpz_gcdext(d, inv, NULL, denom[0], modulo); mpz_mul(mpz_tmp, mpz_tmp, inv); /* We add this contribution to log(f) */ mpz_add(ans, ans, mpz_tmp); } if (trunc > prec) break; /* We update the variables for the next step */ mpz_mul(trunc_mod, trunc_mod, trunc_mod); trunc <<= 1; for (i = N >> 1; i < N; i++) { mpz_clear(num[i]); mpz_clear(denom[i]); } N >>= 1; } mpz_fdiv_r(ans, ans, modulo); /* We clear memory */ mpz_clear(arg); mpz_clear(f); mpz_clear(trunc_mod); mpz_clear(h); mpz_clear(hpow); mpz_clear(mpz_tmp); mpz_clear(d); mpz_clear(inv); mpz_clear(mod2); for (i = 0; i < N; i++) { mpz_clear(num[i]); mpz_clear(denom[i]); } sig_block(); free(num); free(denom); sig_unblock(); }
/** \brief 整系数多项式最大公因子. \param f,g 整系数本原多项式,且\f$\deg f=n\ge\deg g\ge 1\f$. \param r 最大公因子. \note 小素数模方法. \todo 理论文档此处有误. */ void UniGcdZ_SmallPrime1(poly_z & r,const poly_z & f,const poly_z & g) { poly_z fp,gp,vp,v1; poly_z fstar,gstar; mpz_t c,s,t; mpz_init(c);mpz_init(s);mpz_init(t); mpz_t A,b,B,z_temp,k,p_bound,p,p_low_bound,p1,B2; mpf_t float_temp; mpz_init(A);mpz_init(b);mpz_init(B);mpz_init(z_temp);mpz_init(k);mpz_init(p_bound);mpz_init(p);mpz_init(p1);mpz_init(p_low_bound);mpf_init(float_temp);mpz_init(B2); UniMaxNormZ(A,f);UniMaxNormZ(b,g); int n=f.size()-1,m=g.size()-1; if(mpz_cmp(A,b)<0)mpz_set(A,b); mpz_gcd(b,f[n],g[m]); mpz_ui_pow_ui(B,2,n); mpz_mul(B,B,A); mpz_mul(B,B,b); mpf_sqrt_ui(float_temp,n+1); mpz_set_f(z_temp,float_temp); mpz_mul(B,B,z_temp); mpz_mul_ui(B2,B,2); mpz_set_si(z_temp,n); int tempint; tempint=2*n*mpz_sizeinbase(z_temp,2)+2*mpz_sizeinbase(b,2)+4*n*mpz_sizeinbase(A,2); //tempint=2*n*Modules::NumberTheory::IntegerLength(Z(n),2)+2*Modules::NumberTheory::IntegerLength(b,2)+4*n*Modules::NumberTheory::IntegerLength(A,2); mpz_set_si(k,tempint); mpz_mul_ui(p_bound,k,2); mpz_mul_ui(p_bound,p_bound,mpz_sizeinbase(k,2)); mpz_set_ui(p_low_bound,3); fstar.resize(n+1); for(size_t i=0;i<=n;i++) { mpz_mul(fstar[i],f[i],b); } gstar.resize(m+1); for(size_t i=0;i<=m;i++) { mpz_mul(gstar[i],g[i],b); } while(1) { while(1) { random::randominteger(p,p_low_bound,p_bound); if(mpz_probab_prime_p(p,10)>0&&mpz_divisible_p(b,p)==0)break; } UniPolynomialMod(fp,f,p); UniPolynomialMod(gp,g,p); UniGcdZp(vp,fp,gp,p); if(vp.size()==1) { r.resize(1); mpz_set_si(r[0],1); fp.resize(0);gp.resize(0);vp.resize(0);v1.resize(0); fstar.resize(0);gstar.resize(0); mpz_clear(c);mpz_clear(s);mpz_clear(t); mpz_clear(A);mpz_clear(b);mpz_clear(B);mpz_clear(z_temp);mpz_clear(k);mpz_clear(p_bound);mpz_clear(p);mpz_clear(p1);mpz_clear(p_low_bound);mpf_clear(float_temp); return ; } mpz_set(p1,p); copy_poly_z(v1,vp); while(mpz_cmp(p1,B2)<0) { while(1) { random::randominteger(p,p_low_bound,p_bound); if(mpz_probab_prime_p(p,10)>0&&mpz_divisible_p(b,p)==0)break; } UniPolynomialMod(fp,f,p); UniPolynomialMod(gp,g,p); UniGcdZp(vp,fp,gp,p); if(vp.size()==1) { r.resize(1); mpz_set_si(r[0],1); fp.resize(0);gp.resize(0);vp.resize(0);v1.resize(0); fstar.resize(0);gstar.resize(0); mpz_clear(c);mpz_clear(s);mpz_clear(t); mpz_clear(A);mpz_clear(b);mpz_clear(B);mpz_clear(z_temp);mpz_clear(k);mpz_clear(p_bound);mpz_clear(p);mpz_clear(p1);mpz_clear(p_low_bound);mpf_clear(float_temp); return ; } if(vp.size()<v1.size()) { mpz_set(p1,p); copy_poly_z(v1,vp); continue; } if(vp.size()==v1.size()) { mpz_gcdext(c,s,t,p1,p); mpz_mul(t,p,t); mpz_mul(s,p1,s); mpz_mul(p1,p1,p); for(size_t i=0;i<vp.size();i++) { mpz_mul(c,v1[i],t); mpz_addmul(c,vp[i],s); mpz_set(v1[i],c); } UniPolynomialMod(v1,v1,p1); } } for(size_t i=0;i<v1.size();i++)mpz_mul(v1[i],v1[i],b); UniPolynomialMod(v1,v1,p1); if(poly_z_divisible(fstar,v1)&&poly_z_divisible(gstar,v1)) { UniPPZ(r,v1);break; } } fp.resize(0);gp.resize(0);vp.resize(0);v1.resize(0); fstar.resize(0);gstar.resize(0); mpz_clear(c);mpz_clear(s);mpz_clear(t); mpz_clear(A);mpz_clear(b);mpz_clear(B);mpz_clear(z_temp);mpz_clear(k);mpz_clear(p_bound);mpz_clear(p);mpz_clear(p1);mpz_clear(p_low_bound);mpf_clear(float_temp); return ; }
int chinese(mpz_t ret, mpz_t lcm, mpz_t *a, mpz_t *m, int items) { mpz_t sum, gcd, u, v, s, t, temp1, temp2; int i, rval = 1; #if 0 if (items >= 128) { int first = items/2; mpz_t ca[2], cm[2]; for (i = 0; i < 2; i++) { mpz_init(ca[i]); mpz_init(cm[i]); } rval = chinese(ca[0], cm[0], a, m, first); if (rval == 1) rval = chinese(ca[1], cm[1], a+first, m+first, items-first); if (rval == 1) rval = chinese(ret, lcm, ca, cm, 2); for (i = 0; i < 2; i++) { mpz_clear(ca[i]); mpz_clear(cm[i]); } return rval; } #else #define CRTN 8 if (items >= 64) { int start = 0, step = items/CRTN; mpz_t ca[CRTN], cm[CRTN]; for (i = 0; i < CRTN; i++) { mpz_init(ca[i]); mpz_init(cm[i]); } for (i = 0; rval && i < CRTN; i++) { int citems = (i==CRTN-1) ? items-(CRTN-1)*step : step; rval = chinese(ca[i], cm[i], a+i*step, m+i*step, citems); } if (rval) rval = chinese(ret, lcm, ca, cm, CRTN); for (i = 0; i < CRTN; i++) { mpz_clear(ca[i]); mpz_clear(cm[i]); } return rval; } #endif mpz_init(temp1); mpz_init(temp2); mpz_init(sum); mpz_init(gcd); mpz_init(s); mpz_init(t); mpz_init(u); mpz_init(v); mpz_set(lcm, m[0]); mpz_mod(sum, a[0], m[0]); for (i = 1; i < items; i++) { mpz_gcdext(gcd, u, v, lcm, m[i]); mpz_divexact(s, m[i], gcd); mpz_divexact(t, lcm, gcd); if (mpz_cmp_ui(gcd,1) != 0) { mpz_mod(temp1, sum, gcd); mpz_mod(temp2, a[i], gcd); if (mpz_cmp(temp1, temp2) != 0) { rval = 0; break; } } if (mpz_sgn(s) < 0) mpz_neg(s,s); if (mpz_sgn(t) < 0) mpz_neg(t,t); mpz_mul(lcm, lcm, s); if (mpz_sgn(u) < 0) mpz_add(u, u, lcm); if (mpz_sgn(v) < 0) mpz_add(v, v, lcm); mpz_mul(temp1, v, s); mpz_mul(v, temp1, sum); mpz_mul(temp1, u, t); mpz_mul(u, temp1, a[i]); mpz_add(temp1, v, u); mpz_mod(sum, temp1, lcm); } mpz_set(ret, sum); mpz_clear(sum); mpz_clear(gcd); mpz_clear(s); mpz_clear(t); mpz_clear(u); mpz_clear(v); mpz_clear(temp1); mpz_clear(temp2); return rval; }
static int ec_add(mpz_t xr, mpz_t yr, mpz_t x1, mpz_t y1, int z1, mpz_t x2, mpz_t y2, int z2, unsigned long n, mpz_t a) { /* add two points of an elliptic curve by matching an addition rule, * in non-trivial cases producing a secant connecting the points (or a * tangent in case of overlapping points), finding the third intersection * point and mirroring it to the x axis */ if (0 == z1 && 0 == z2) /* 0 + 0 = 0 */ { mpz_set_ui(xr, 0); mpz_set_ui(yr, 1); return 0; } else if (0 == z2) /* P + 0 = P */ { mpz_set(xr, x1); mpz_set(yr, y1); return 1; } else if (0 == z1) /* 0 + Q = Q */ { mpz_set(xr, x2); mpz_set(yr, y2); return 1; } else if (0 != mpz_cmp(x1, x2)) /* P + Q, P != Q */ { /* m = (y2 - y1) / (x2 - x1) * xr = m^2 - x1 - x2 * yr = m * (x1 - x3) - y1 */ mpz_t xt, yt, tmp; mpz_init(xt); mpz_init(yt); mpz_init_set_ui(tmp, n); mpz_sub(yt, y2, y1); mpz_sub(xt, x2, x1); { /* multiplicative inverse over GF(n) using the Extended Euclidean * Algorithm * 1 = g = s * (x2 - x1) + t * n = s * (x2 - x1) */ mpz_t s, t, g; mpz_init(s); mpz_init(t); mpz_init(g); mpz_gcdext(g, s, t, xt, tmp); mpz_mul(xt, s, yt); mpz_mod_ui(xt, xt, n); mpz_set(yt, xt); mpz_clear(s); mpz_clear(t); mpz_clear(g); } mpz_mul(xt, xt, xt); mpz_sub(xt, xt, x1); mpz_sub(xt, xt, x2); mpz_mod_ui(xt, xt, n); mpz_sub(tmp, x1, xt); mpz_mul(yt, yt, tmp); mpz_sub(yt, yt, y1); mpz_mod_ui(yt, yt, n); mpz_set(xr, xt); mpz_set(yr, yt); mpz_clear(xt); mpz_clear(yt); mpz_clear(tmp); return 1; } else if (0 != mpz_cmp(y1, y2)) /* P + (-P) = 0 */ { mpz_set_ui(xr, 0); mpz_set_ui(yr, 1); return 0; } else /* P + P */ { /* m = (3 * x1^2 + a) / (2 * y1) * xr = m^2 - 2 * x1 * yr = m * (x1 - x3) - y1 */ mpz_t xt, yt, tmp; mpz_init(xt); mpz_init(yt); mpz_init_set_ui(tmp, n); mpz_mul(xt, x1, x1); mpz_mul_ui(xt, xt, 3); mpz_add(xt, xt, a); mpz_add(yt, y1, y1); { /* multiplicative inverse over GF(n) using the Extended Euclidean * Algorithm * 1 = g = s * (2 * y1) + t * n = s * (2 * y1) */ mpz_t s, t, g; mpz_init(s); mpz_init(t); mpz_init(g); mpz_gcdext(g, s, t, yt, tmp); mpz_mul(xt, s, xt); mpz_mod_ui(xt, xt, n); mpz_set(yt, xt); mpz_clear(s); mpz_clear(t); mpz_clear(g); } mpz_mul(xt, xt, xt); mpz_sub(xt, xt, x1); mpz_sub(xt, xt, x1); mpz_mod_ui(xt, xt, n); mpz_sub(tmp, x1, xt); mpz_mul(yt, yt, tmp); mpz_sub(yt, yt, y1); mpz_mod_ui(yt, yt, n); mpz_set(xr, xt); mpz_set(yr, yt); mpz_clear(xt); mpz_clear(yt); mpz_clear(tmp); return 1; } }
int main (int argc, char **argv) { int i; int pass, reps = 400; mpz_t in1, in2, in3; unsigned long int in2i; mp_size_t size; mpz_t res1, res2, res3; mpz_t ref1, ref2, ref3; mpz_t t; unsigned long int r1, r2; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); TESTS_REPS (reps, argv, argc); rands = RANDS; mpz_init (bs); mpz_init (in1); mpz_init (in2); mpz_init (in3); mpz_init (ref1); mpz_init (ref2); mpz_init (ref3); mpz_init (res1); mpz_init (res2); mpz_init (res3); mpz_init (t); for (pass = 1; pass <= reps; pass++) { if (isatty (fileno (stdout))) { printf ("\r%d/%d passes", pass, reps); fflush (stdout); } mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 21 + 2; if ((pass & 1) == 0) { /* Make all input operands have quite different sizes */ mpz_urandomb (bs, rands, 32); size = mpz_get_ui (bs) % size_range; mpz_rrandomb (in1, rands, size); mpz_urandomb (bs, rands, 32); size = mpz_get_ui (bs) % size_range; mpz_rrandomb (in2, rands, size); mpz_urandomb (bs, rands, 32); size = mpz_get_ui (bs) % size_range; mpz_rrandomb (in3, rands, size); } else { /* Make all input operands have about the same size */ mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (in1, rands, size); mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (in2, rands, size); mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (in3, rands, size); } mpz_urandomb (bs, rands, 3); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (in1, in1); if ((bsi & 2) != 0) mpz_neg (in2, in2); if ((bsi & 4) != 0) mpz_neg (in3, in3); for (i = 0; i < numberof (dss); i++) { if (dss[i].isdivision && mpz_sgn (in2) == 0) continue; if (dss[i].isslow && size_range > 19) continue; (dss[i].fptr) (ref1, in1, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); INVOKE_RSS (dss[i], res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (dss, i, in1, in2, NULL); mpz_set (res1, in2); INVOKE_RSS (dss[i], res1, in1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (dss, i, in1, in2, NULL); } for (i = 0; i < numberof (ddss_div); i++) { if (mpz_sgn (in2) == 0) continue; (ddss_div[i].fptr) (ref1, ref2, in1, in2); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); mpz_set (res1, in1); INVOKE_RRSS (ddss_div[i], res1, res2, res1, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); mpz_set (res2, in1); INVOKE_RRSS (ddss_div[i], res1, res2, res2, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); mpz_set (res1, in2); INVOKE_RRSS (ddss_div[i], res1, res2, in1, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); mpz_set (res2, in2); INVOKE_RRSS (ddss_div[i], res1, res2, in1, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); } for (i = 0; i < numberof (ds); i++) { if (ds[i].nonneg && mpz_sgn (in1) < 0) continue; (ds[i].fptr) (ref1, in1); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); INVOKE_RS (ds[i], res1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (ds, i, in1, in2, NULL); } in2i = mpz_get_ui (in2); for (i = 0; i < numberof (dsi); i++) { if (dsi[i].mod != 0) in2i = mpz_get_ui (in2) % dsi[i].mod; (dsi[i].fptr) (ref1, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); INVOKE_RRS (dsi[i], res1, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (dsi, i, in1, in2, NULL); } if (in2i != 0) /* Don't divide by 0. */ { for (i = 0; i < numberof (dsi_div); i++) { r1 = (dsi_div[i].fptr) (ref1, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); r2 = (dsi_div[i].fptr) (res1, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || r1 != r2) FAIL (dsi_div, i, in1, in2, NULL); } for (i = 0; i < numberof (ddsi_div); i++) { r1 = (ddsi_div[i].fptr) (ref1, ref2, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); r2 = (ddsi_div[i].fptr) (res1, res2, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2) FAIL (ddsi_div, i, in1, in2, NULL); mpz_set (res2, in1); (ddsi_div[i].fptr) (res1, res2, res2, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2) FAIL (ddsi_div, i, in1, in2, NULL); } } if (mpz_sgn (in1) >= 0) { mpz_sqrtrem (ref1, ref2, in1); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); mpz_set (res1, in1); mpz_sqrtrem (res1, res2, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_sqrtrem, in1, NULL, NULL); mpz_set (res2, in1); mpz_sqrtrem (res1, res2, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_sqrtrem, in1, NULL, NULL); mpz_set (res1, in1); mpz_sqrtrem (res1, res1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref2, res1) != 0) FAIL2 (mpz_sqrtrem, in1, NULL, NULL); } if (mpz_sgn (in1) >= 0) { mpz_root (ref1, in1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); mpz_root (res1, res1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_root, in1, in2, NULL); } if (mpz_sgn (in1) >= 0) { mpz_rootrem (ref1, ref2, in1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); mpz_set (res1, in1); mpz_rootrem (res1, res2, res1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_rootrem, in1, in2, NULL); mpz_set (res2, in1); mpz_rootrem (res1, res2, res2, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_rootrem, in1, in2, NULL); } if (size_range < 18) /* run fewer tests since gcdext lots of time */ { mpz_gcdext (ref1, ref2, ref3, in1, in2); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); MPZ_CHECK_FORMAT (ref3); mpz_set (res1, in1); mpz_gcdext (res1, res2, res3, res1, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in1); mpz_gcdext (res1, res2, res3, res2, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res3, in1); mpz_gcdext (res1, res2, res3, res3, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res1, in2); mpz_gcdext (res1, res2, res3, in1, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in2); mpz_gcdext (res1, res2, res3, in1, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res3, in2); mpz_gcdext (res1, res2, res3, in1, res3); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res1, in1); mpz_gcdext (res1, res2, NULL, res1, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in1); mpz_gcdext (res1, res2, NULL, res2, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res1, in2); mpz_gcdext (res1, res2, NULL, in1, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in2); mpz_gcdext (res1, res2, NULL, in1, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); } /* Don't run mpz_powm for huge exponents or when undefined. */ if (size_range < 17 && mpz_sizeinbase (in2, 2) < 250 && mpz_sgn (in3) != 0 && (mpz_sgn (in2) >= 0 || mpz_invert (t, in1, in3))) { mpz_powm (ref1, in1, in2, in3); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); mpz_powm (res1, res1, in2, in3); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm, in1, in2, in3); mpz_set (res1, in2); mpz_powm (res1, in1, res1, in3); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm, in1, in2, in3); mpz_set (res1, in3); mpz_powm (res1, in1, in2, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm, in1, in2, in3); } /* Don't run mpz_powm_ui when undefined. */ if (size_range < 17 && mpz_sgn (in3) != 0) { mpz_powm_ui (ref1, in1, in2i, in3); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); mpz_powm_ui (res1, res1, in2i, in3); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm_ui, in1, in2, in3); mpz_set (res1, in3); mpz_powm_ui (res1, in1, in2i, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm_ui, in1, in2, in3); } { r1 = mpz_gcd_ui (ref1, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); r2 = mpz_gcd_ui (res1, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_gcd_ui, in1, in2, NULL); } if (mpz_sgn (in2) != 0) { /* Test mpz_remove */ mp_bitcnt_t refretval, retval; refretval = mpz_remove (ref1, in1, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); retval = mpz_remove (res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || refretval != retval) FAIL2 (mpz_remove, in1, in2, NULL); mpz_set (res1, in2); retval = mpz_remove (res1, in1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || refretval != retval) FAIL2 (mpz_remove, in1, in2, NULL); } if (mpz_sgn (in2) != 0) { /* Test mpz_divexact */ mpz_mul (t, in1, in2); mpz_divexact (ref1, t, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, t); mpz_divexact (res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact, t, in2, NULL); mpz_set (res1, in2); mpz_divexact (res1, t, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact, t, in2, NULL); } if (mpz_sgn (in2) > 0) { /* Test mpz_divexact_gcd, same as mpz_divexact */ mpz_mul (t, in1, in2); mpz_divexact_gcd (ref1, t, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, t); mpz_divexact_gcd (res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact_gcd, t, in2, NULL); mpz_set (res1, in2); mpz_divexact_gcd (res1, t, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact_gcd, t, in2, NULL); } } if (isatty (fileno (stdout))) printf ("\r%20s", ""); mpz_clear (bs); mpz_clear (in1); mpz_clear (in2); mpz_clear (in3); mpz_clear (ref1); mpz_clear (ref2); mpz_clear (ref3); mpz_clear (res1); mpz_clear (res2); mpz_clear (res3); mpz_clear (t); if (isatty (fileno (stdout))) printf ("\r"); tests_end (); exit (0); }
/* void key_generation(int, RSA_PRIVATE, RSA_PUBLIC) * generate keys for encrypting and decrypting messages * see more at http://tools.ietf.org/html/rfc2313 */ void key_generation(int length, RSA_PRIVATE &priv, RSA_PUBLIC &pub) { mpz_t p, q, p1, q1; mpz_init2(p, length/2); mpz_init2(q, length/2); mpz_init2(p1, length/2); mpz_init2(q1, length/2); // generate a random number of bit, set two highest bits and one lowest string p_tab(length/2, '1'); string q_tab(length/2, '1'); // generating random bits int r; for (int i=2; i<(length/2 -1); i++) { r = random(2); if (r==0) p_tab[i]='0'; else p_tab[i]='1'; r = random(2); if (r==0) q_tab[i]='0'; else q_tab[i]='1'; } mpz_set_str(p, p_tab.c_str(), 2); mpz_set_str(q, q_tab.c_str(), 2); // if p not prime, then +=2 and try again while ( mpz_probab_prime_p(p, 100)==0 ) { mpz_add_ui(p, p, 2L); } // if q not prime, then +=2 and try again while ( mpz_probab_prime_p(q, 100)==0 ) { mpz_add_ui(q, q, 2L); } // swap values if and only if p < q // will be used later (see CRT - Chinese Remainder Theorem) if (mpz_cmp(p, q) < 0) { mpz_swap(p, q); } mpz_t n, phi; mpz_init2(n, length); mpz_init2(phi, length); //n: mpz_mul(n, p, q); // p1 = p-1 // q1 = q-1 // will be useful later mpz_sub_ui(p1, p, 1); mpz_sub_ui(q1, q, 1); mpz_mul(phi, p1, q1); // e: // 1 < e < phi, gcd(e, phi) == 1 mpz_t e, gcd; mpz_inits(e, gcd, NULL); unsigned int gcd_tab[] = {3, 17, 65537}; for (int i=0; i<3; i++) { mpz_gcd_ui(gcd, phi, gcd_tab[i]); if (mpz_cmp_ui(gcd, 1) == 0) { mpz_set_ui(e, gcd_tab[i]); break; } } // d: // probably redundant mpz_t d; mpz_init(d); mpz_gcdext(gcd, d, NULL, e, phi); if (mpz_cmp_ui(d,0) < 0) mpz_mod(d, d, phi); mpz_t dP, dQ, qInv; mpz_inits(dP, dQ, qInv, NULL); // dP: mpz_gcdext(gcd, dP, NULL, e, p1); if (mpz_cmp_ui(dP, 0) < 0) mpz_mod(dP, dP, p1); // dQ: mpz_gcdext(gcd, dQ, NULL, e, q1); if (mpz_cmp_ui(dQ, 0) < 0) mpz_mod(dQ, dQ, q1); // qInv: mpz_gcdext(gcd, qInv, NULL, q, p); if (mpz_cmp_ui(qInv, 0) < 0) mpz_mod(qInv, qInv, p); // public key: // (n, e) mpz_set(pub.n, n); mpz_set(pub.e, e); // private key: // (n, d) OR (p, q, dP, dQ, qInv) mpz_set(priv.p, p); mpz_set(priv.q, q); mpz_set(priv.dP, dP); mpz_set(priv.dQ, dQ); mpz_set(priv.qInv, qInv); pub.length = priv.length = length; mpz_clears(p, q, p1, q1, n, phi, e, gcd, d, dP, dQ, qInv, NULL); }
/* * Compute the Rabin signature and the useful value of f. */ int rs_sign_rabin(mpz_t res, /* mpz to store signature */ int* f, /* f value chosen */ const mpz_t hash, /* MD5 hash of app */ int rootnum, /* root number (0, 1, 2, 3) */ RSKey* key) /* key structure */ { mpz_t mm; int mLp, mLq; int pm8, qm8; if (!mpz_sgn(key->n)) { rs_error(key, NULL, "unable to sign: public key missing"); return RS_ERR_MISSING_PUBLIC_KEY; } if (!mpz_sgn(key->p) || !mpz_sgn(key->q)) { rs_error(key, NULL, "unable to sign: private key missing"); return RS_ERR_MISSING_PRIVATE_KEY; } mpz_init(mm); /* Calculate q^-1 if necessary */ if (!mpz_sgn(key->qinv)) { #ifndef USE_MPZ_GCDEXT mpz_sub_ui(mm, key->p, 2); mpz_powm(key->qinv, key->q, mm, key->p); #else mpz_gcdext(mm, key->qinv, NULL, key->q, key->p); if (mpz_cmp_ui(mm, 1)) { mpz_clear(mm); rs_error(key, NULL, "unable to sign: unsuitable key"); return RS_ERR_UNSUITABLE_RABIN_KEY; } #endif } applyf(mm, hash, key->n, 2); mLp = mpz_legendre(mm, key->p); mLq = mpz_legendre(mm, key->q); pm8 = mpz_get_ui(key->p) % 8; qm8 = mpz_get_ui(key->q) % 8; if (pm8 == 1 || qm8 == 1 || (pm8 % 2) == 0 || (qm8 % 2) == 0) { mpz_clear(mm); rs_error(key, NULL, "unable to sign: unsuitable key"); return RS_ERR_UNSUITABLE_RABIN_KEY; } *f = ftab[(mLp == 1 ? 0 : 1) + (mLq == 1 ? 0 : 2) + (((qm8 - 3) / 2) * 4) + (((pm8 - 3) / 2) * 12)]; if (*f == 99) { mpz_clear(mm); rs_error(key, NULL, "unable to sign: unsuitable key"); return RS_ERR_UNSUITABLE_RABIN_KEY; } rabsigf(res, hash, key->n, key->p, key->q, key->qinv, *f, rootnum); mpz_clear(mm); return RS_SUCCESS; }
void one_test (mpz_t op1, mpz_t op2, mpz_t ref, int i) { /* printf ("%ld %ld %ld\n", SIZ (op1), SIZ (op2), SIZ (ref)); fflush (stdout); */ /* fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); */ mpz_gcdext (gcd1, s, NULL, op1, op2); if (ref && mpz_cmp (ref, gcd1) != 0) { fprintf (stderr, "ERROR in test %d\n", i); fprintf (stderr, "mpz_gcdext returned incorrect result\n"); fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); fprintf (stderr, "expected result:\n"); debug_mp (ref, -16); fprintf (stderr, "mpz_gcdext returns:\n");debug_mp (gcd1, -16); abort (); } if (!gcdext_valid_p(op1, op2, gcd1, s)) { fprintf (stderr, "ERROR in test %d\n", i); fprintf (stderr, "mpz_gcdext returned invalid result\n"); fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); fprintf (stderr, "mpz_gcdext returns:\n");debug_mp (gcd1, -16); abort (); } mpz_gcd (gcd2, op1, op2); if (mpz_cmp (gcd2, gcd1) != 0) { fprintf (stderr, "ERROR in test %d\n", i); fprintf (stderr, "mpz_gcd returned incorrect result\n"); fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); fprintf (stderr, "expected result:\n"); debug_mp (gcd1, -16); fprintf (stderr, "mpz_gcd returns:\n"); debug_mp (gcd2, -16); abort (); } /* This should probably move to t-gcd_ui.c */ if (mpz_fits_ulong_p (op1) || mpz_fits_ulong_p (op2)) { if (mpz_fits_ulong_p (op1)) mpz_gcd_ui (gcd2, op2, mpz_get_ui (op1)); else mpz_gcd_ui (gcd2, op1, mpz_get_ui (op2)); if (mpz_cmp (gcd2, gcd1)) { fprintf (stderr, "ERROR in test %d\n", i); fprintf (stderr, "mpz_gcd_ui returned incorrect result\n"); fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); fprintf (stderr, "expected result:\n"); debug_mp (gcd1, -16); fprintf (stderr, "mpz_gcd_ui returns:\n"); debug_mp (gcd2, -16); abort (); } } mpz_gcdext (gcd2, temp1, temp2, op1, op2); mpz_mul (temp1, temp1, op1); mpz_mul (temp2, temp2, op2); mpz_add (temp1, temp1, temp2); if (mpz_cmp (gcd1, gcd2) != 0 || mpz_cmp (gcd2, temp1) != 0) { fprintf (stderr, "ERROR in test %d\n", i); fprintf (stderr, "mpz_gcdext returned incorrect result\n"); fprintf (stderr, "op1="); debug_mp (op1, -16); fprintf (stderr, "op2="); debug_mp (op2, -16); fprintf (stderr, "expected result:\n"); debug_mp (gcd1, -16); fprintf (stderr, "mpz_gcdext returns:\n");debug_mp (gcd2, -16); abort (); } }
int main (int argc, char **argv) { mpz_t op1, op2, x; mpz_t gcd, gcd2, s, t; mpz_t temp1, temp2; mp_size_t op1_size, op2_size, x_size; int i; int reps = 2000; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); rands = RANDS; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (op1); mpz_init (op2); mpz_init (x); mpz_init (gcd); mpz_init (gcd2); mpz_init (temp1); mpz_init (temp2); mpz_init (s); mpz_init (t); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 12 + 2; /* 0..8191 bit operands */ mpz_urandomb (bs, rands, size_range); op1_size = mpz_get_ui (bs); mpz_rrandomb (op1, rands, op1_size); mpz_urandomb (bs, rands, size_range); op2_size = mpz_get_ui (bs); mpz_rrandomb (op2, rands, op2_size); mpz_urandomb (bs, rands, size_range); x_size = mpz_get_ui (bs); mpz_rrandomb (x, rands, x_size); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (op1, op1); if ((bsi & 2) != 0) mpz_neg (op2, op2); /* printf ("%ld %ld\n", SIZ (op1), SIZ (op2)); */ mpz_mul (op1, op1, x); mpz_mul (op2, op2, x); mpz_gcd (gcd, op1, op2); /* We know GCD will be at least X, since we multiplied both operands with it. */ if (mpz_cmp (gcd, x) < 0 && mpz_sgn (op1) != 0 && mpz_sgn (op2) != 0) dump_abort (i, op1, op2); if (mpz_fits_ulong_p (op2)) { mpz_gcd_ui (gcd2, op1, mpz_get_ui (op2)); if (mpz_cmp (gcd, gcd2)) dump_abort (i, op1, op2); } mpz_gcdext (gcd2, s, t, op1, op2); if (mpz_cmp (gcd, gcd2)) dump_abort (i, op1, op2); mpz_gcdext (gcd2, s, NULL, op1, op2); if (mpz_cmp (gcd, gcd2)) dump_abort (i, op1, op2); mpz_mul (temp1, s, op1); mpz_mul (temp2, t, op2); mpz_add (gcd2, temp1, temp2); if (mpz_cmp (gcd, gcd2)) dump_abort (i, op1, op2); } mpz_clear (bs); mpz_clear (op1); mpz_clear (op2); mpz_clear (x); mpz_clear (gcd); mpz_clear (gcd2); mpz_clear (temp1); mpz_clear (temp2); mpz_clear (s); mpz_clear (t); tests_end (); exit (0); }