static int rsa_private_calculate(mpz_t in, mpz_t p, mpz_t q, mpz_t dmp1, mpz_t dmq1, mpz_t iqmp, mpz_t out) { mpz_t vp, vq, u; mpz_init(vp); mpz_init(vq); mpz_init(u); /* vq = c ^ (d mod (q - 1)) mod q */ /* vp = c ^ (d mod (p - 1)) mod p */ mpz_fdiv_r(vp, in, p); mpz_powm(vp, vp, dmp1, p); mpz_fdiv_r(vq, in, q); mpz_powm(vq, vq, dmq1, q); /* C2 = 1/q mod p (iqmp) */ /* u = (vp - vq)C2 mod p. */ mpz_sub(u, vp, vq); #if 0 if (mp_int_compare_zero(&u) < 0) mp_int_add(&u, p, &u); #endif mpz_mul(u, iqmp, u); mpz_fdiv_r(u, u, p); /* c ^ d mod n = vq + u q */ mpz_mul(u, q, u); mpz_add(out, u, vq); mpz_clear(vp); mpz_clear(vq); mpz_clear(u); return 0; }
void exp_modulo(mpz_t rop, const mpz_t base, const mpz_t exponent, const mpz_t modulus) { /* fast exp-modulo */ mpz_t c; mpz_init_set_ui(c, 1); mpz_t ex; mpz_init_set(ex, exponent); mpz_t b; mpz_init_set(b, base); mpz_t temp; mpz_init(temp); while (mpz_cmp_ui(ex, 0) > 0) { /* ex mod 2 == 1 */ mpz_fdiv_r_ui(temp, ex, 2); if (mpz_cmp_ui(temp, 1) == 0) { mpz_mul(temp, c, b); mpz_fdiv_r(c, temp, modulus); } /* right shift by 1 */ mpz_fdiv_q_2exp(ex, ex, 1); /* b^2 mod modulus */ mpz_mul(b, b, b); mpz_fdiv_r(b, b, modulus); } mpz_set(rop, c); mpz_clear(c); mpz_clear(ex); mpz_clear(temp); mpz_clear(b); }
// Algorithm 19.2 [PDF page 24](http://cr.yp.to/lineartime/dcba-20040404.pdf) // // See [reduce test](test-reduce.html) for basic usage. void reduce(mpz_t i, mpz_t pai, const mpz_t p, const mpz_t a) { mpz_t r, j, b, p2, a2; // **Sep 1** // // If p does not divide a: Print (0,a) and stop. mpz_init(r); mpz_fdiv_r(r, a, p); if (mpz_cmp_ui(r, 0) != 0) { mpz_clear(r); mpz_set_ui(i, 0); mpz_set(pai, a); return; } // **Sep 2** // // Compute (j,b) ← reduce(p^2 ,a/p) mpz_init(j); mpz_init(b); mpz_init(p2); mpz_init(a2); mpz_mul(p2, p, p); mpz_fdiv_q(a2, a, p); reduce(j, b, p2, a2); mpz_clear(p2); mpz_clear(a2); // **Sep 3** // // If p divides b: Print (2 j +2,b/p) and stop. mpz_fdiv_r(r, b, p); if (mpz_cmp_ui(r, 0) == 0) { mpz_mul_ui(j, j, 2); mpz_add_ui(j, j, 2); mpz_set(i, j); mpz_fdiv_q(b, b, p); mpz_set(pai, b); mpz_clear(r); mpz_clear(b); mpz_clear(j); return; } mpz_clear(r); // **Sep 4** // // Print (2 j +1,b). mpz_mul_ui(j, j, 2); mpz_add_ui(j, j, 1); mpz_set(i, j); mpz_set(pai, b); // Free the memory. mpz_clear(b); mpz_clear(j); }
/* Computing an rsa root. */ void rsa_compute_root(const struct rsa_private_key *key, mpz_t x, const mpz_t m) { mpz_t xp; /* modulo p */ mpz_t xq; /* modulo q */ mpz_init(xp); mpz_init(xq); /* Compute xq = m^d % q = (m%q)^b % q */ mpz_fdiv_r(xq, m, key->q); mpz_powm(xq, xq, key->b, key->q); /* Compute xp = m^d % p = (m%p)^a % p */ mpz_fdiv_r(xp, m, key->p); mpz_powm(xp, xp, key->a, key->p); /* Set xp' = (xp - xq) c % p. */ mpz_sub(xp, xp, xq); mpz_mul(xp, xp, key->c); mpz_fdiv_r(xp, xp, key->p); /* Finally, compute x = xq + q xp' * * To prove that this works, note that * * xp = x + i p, * xq = x + j q, * c q = 1 + k p * * for some integers i, j and k. Now, for some integer l, * * xp' = (xp - xq) c + l p * = (x + i p - (x + j q)) c + l p * = (i p - j q) c + l p * = (i c + l) p - j (c q) * = (i c + l) p - j (1 + kp) * = (i c + l - j k) p - j * * which shows that xp' = -j (mod p). We get * * xq + q xp' = x + j q + (i c + l - j k) p q - j q * = x + (i c + l - j k) p q * * so that * * xq + q xp' = x (mod pq) * * We also get 0 <= xq + q xp' < p q, because * * 0 <= xq < q and 0 <= xp' < p. */ mpz_mul(x, key->q, xp); mpz_add(x, x, xq); mpz_clear(xp); mpz_clear(xq); }
void check_random (int argc, char *argv[]) { gmp_randstate_ptr rands = RANDS; mpz_t a, c, d, ra, rc; int i; int want; int reps = 50000; if (argc >= 2) reps = atoi (argv[1]); mpz_init (a); mpz_init (c); mpz_init (d); mpz_init (ra); mpz_init (rc); for (i = 0; i < reps; i++) { mpz_errandomb (a, rands, 8*BITS_PER_MP_LIMB); MPZ_CHECK_FORMAT (a); mpz_errandomb (c, rands, 8*BITS_PER_MP_LIMB); MPZ_CHECK_FORMAT (c); mpz_errandomb_nonzero (d, rands, 8*BITS_PER_MP_LIMB); mpz_negrandom (a, rands); MPZ_CHECK_FORMAT (a); mpz_negrandom (c, rands); MPZ_CHECK_FORMAT (c); mpz_negrandom (d, rands); mpz_fdiv_r (ra, a, d); mpz_fdiv_r (rc, c, d); want = (mpz_cmp (ra, rc) == 0); check_one (a, c, d, want); mpz_sub (ra, ra, rc); mpz_sub (a, a, ra); MPZ_CHECK_FORMAT (a); check_one (a, c, d, 1); if (! mpz_pow2abs_p (d)) { refmpz_combit (a, urandom() % (8*BITS_PER_MP_LIMB)); check_one (a, c, d, 0); } } mpz_clear (a); mpz_clear (c); mpz_clear (d); mpz_clear (ra); mpz_clear (rc); }
int _dsa_sign(const struct dsa_public_key *pub, const struct dsa_private_key *key, void *random_ctx, nettle_random_func *random, unsigned digest_size, const uint8_t *digest, struct dsa_signature *signature) { mpz_t k; mpz_t h; mpz_t tmp; /* Require precise match of bitsize of q and hash size. The general description of DSA in FIPS186-3 allows both larger and smaller q; in the the latter case, the hash must be truncated to the right number of bits. */ if (mpz_sizeinbase(pub->q, 2) != 8 * digest_size) return 0; /* Select k, 0<k<q, randomly */ mpz_init_set(tmp, pub->q); mpz_sub_ui(tmp, tmp, 1); mpz_init(k); nettle_mpz_random(k, random_ctx, random, tmp); mpz_add_ui(k, k, 1); /* Compute r = (g^k (mod p)) (mod q) */ mpz_powm(tmp, pub->g, k, pub->p); mpz_fdiv_r(signature->r, tmp, pub->q); /* Compute hash */ mpz_init(h); nettle_mpz_set_str_256_u(h, digest_size, digest); /* Compute k^-1 (mod q) */ if (!mpz_invert(k, k, pub->q)) /* What do we do now? The key is invalid. */ return 0; /* Compute signature s = k^-1 (h + xr) (mod q) */ mpz_mul(tmp, signature->r, key->x); mpz_fdiv_r(tmp, tmp, pub->q); mpz_add(tmp, tmp, h); mpz_mul(tmp, tmp, k); mpz_fdiv_r(signature->s, tmp, pub->q); mpz_clear(k); mpz_clear(h); mpz_clear(tmp); return 1; }
/*-------------------------------------------------------------------*/ static void gmp_poly_mod_q(gmp_poly_t *p, mpz_t q, gmp_poly_t *res) { uint32 i; uint32 pbits, resbits; /* also trim aggressively the memory use of the computed remainders; the algebraic square root has comparatively few arithmetic operations but the memory use for large problems is a concern */ for (i = 0; i <= p->degree; i++) { pbits = mpz_sizeinbase(p->coeff[i], 2); mpz_fdiv_r(res->coeff[i], p->coeff[i], q); resbits = mpz_sizeinbase(res->coeff[i], 2); if (pbits > resbits + 1000) mpz_realloc2(res->coeff[i], resbits + 500); } /* recalculate the degree */ for (i = p->degree; i; i--) { if (mpz_sgn(res->coeff[i]) != 0) break; } res->degree = i; }
void test_dsa_key(struct dsa_public_key *pub, struct dsa_private_key *key, unsigned q_size) { mpz_t t; mpz_init(t); ASSERT(mpz_sizeinbase(pub->q, 2) == q_size); ASSERT(mpz_sizeinbase(pub->p, 2) >= DSA_SHA1_MIN_P_BITS); ASSERT(mpz_probab_prime_p(pub->p, 10)); ASSERT(mpz_probab_prime_p(pub->q, 10)); mpz_fdiv_r(t, pub->p, pub->q); ASSERT(0 == mpz_cmp_ui(t, 1)); ASSERT(mpz_cmp_ui(pub->g, 1) > 0); mpz_powm(t, pub->g, pub->q, pub->p); ASSERT(0 == mpz_cmp_ui(t, 1)); mpz_powm(t, pub->g, key->x, pub->p); ASSERT(0 == mpz_cmp(t, pub->y)); mpz_clear(t); }
/* Blinds the c, by computing c *= r^e (mod n), for a random r. Also returns the inverse (ri), for use by rsa_unblind. */ void _rsa_blind (const struct rsa_public_key *pub, void *random_ctx, nettle_random_func *random, mpz_t c, mpz_t ri) { mpz_t r; mpz_init(r); /* c = c*(r^e) * ri = r^(-1) */ do { nettle_mpz_random(r, random_ctx, random, pub->n); /* invert r */ } while (!mpz_invert (ri, r, pub->n)); /* c = c*(r^e) mod n */ mpz_powm_sec(r, r, pub->e, pub->n); mpz_mul(c, c, r); mpz_fdiv_r(c, c, pub->n); mpz_clear(r); }
static PyObject * Pygmpy_f_mod(PyObject *self, PyObject *args) { PyObject *x, *y; PympzObject *r, *tempx, *tempy; if(PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("f_mod() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); if (!(r = Pympz_new())) return NULL; if(CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("f_mod() division by 0"); Py_DECREF((PyObject*)r); return NULL; } mpz_fdiv_r(r->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("f_mod() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)r); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("f_mod() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)r); return NULL; } mpz_fdiv_r(r->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } return (PyObject*)r; }
static Variant HHVM_FUNCTION(gmp_div_r, const Variant& dataA, const Variant& dataB, int64_t round = GMP_ROUND_ZERO) { mpz_t gmpDataA, gmpDataB, gmpReturn; if (!variantToGMPData(cs_GMP_FUNC_NAME_GMP_DIV_R, gmpDataA, dataA)) { return false; } if (!variantToGMPData(cs_GMP_FUNC_NAME_GMP_DIV_R, gmpDataB, dataB)) { mpz_clear(gmpDataA); return false; } if (mpz_sgn(gmpDataB) == 0) { mpz_clear(gmpDataA); mpz_clear(gmpDataB); raise_warning(cs_GMP_INVALID_VALUE_MUST_NOT_BE_ZERO, cs_GMP_FUNC_NAME_GMP_DIV_R); return false; } mpz_init(gmpReturn); switch (round) { case GMP_ROUND_ZERO: mpz_tdiv_r(gmpReturn, gmpDataA, gmpDataB); break; case GMP_ROUND_PLUSINF: mpz_cdiv_r(gmpReturn, gmpDataA, gmpDataB); break; case GMP_ROUND_MINUSINF: mpz_fdiv_r(gmpReturn, gmpDataA, gmpDataB); break; default: mpz_clear(gmpDataA); mpz_clear(gmpDataB); mpz_clear(gmpReturn); return null_variant; } mpz_clear(gmpDataA); mpz_clear(gmpDataB); Variant ret; if (dataB.isInteger() && dataB.getInt64() >= 0) { ret = (int64_t)mpz_get_ui(gmpReturn); } else { ret = NEWOBJ(GMPResource)(gmpReturn); } mpz_clear(gmpReturn); return ret; }
static PyObject * GMPy_MPZ_IRem_Slot(PyObject *self, PyObject *other) { MPZ_Object *rz; if (!(rz = GMPy_MPZ_New(NULL))) return NULL; if (CHECK_MPZANY(other)) { if (mpz_sgn(MPZ(other)) == 0) { ZERO_ERROR("mpz modulo by zero"); return NULL; } mpz_fdiv_r(rz->z, MPZ(self), MPZ(other)); return (PyObject*)rz; } if (PyIntOrLong_Check(other)) { int error; long temp = GMPy_Integer_AsLongAndError(other, &error); if (!error) { if (temp > 0) { mpz_fdiv_r_ui(rz->z, MPZ(self), temp); } else if (temp == 0) { ZERO_ERROR("mpz modulo by zero"); return NULL; } else { mpz_cdiv_r_ui(rz->z, MPZ(self), -temp); } } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_fdiv_r(rz->z, MPZ(self), tempz); mpz_cloc(tempz); } return (PyObject*)rz; } Py_RETURN_NOTIMPLEMENTED; }
static int wrap_nettle_mpi_mulm(bigint_t w, const bigint_t a, const bigint_t b, const bigint_t m) { mpz_mul(TOMPZ(w), TOMPZ(a), TOMPZ(b)); mpz_fdiv_r(TOMPZ(w), TOMPZ(w), TOMPZ(m)); return 0; }
int mpz_divisible_p (mpz_t N, mpz_t D) { int d; mpz_t r; mpz_init(r); mpz_fdiv_r(r, N, D); d = mpz_sgn(r) == 0; mpz_clear(r); return d; }
static PyObject * Pyxmpz_inplace_rem(PyObject *a, PyObject *b) { mpz_t tempz; mpir_si temp_si; int overflow; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_fdiv_r(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if(temp_si > 0) { mpz_fdiv_r_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); } else if(temp_si == 0) { ZERO_ERROR("xmpz modulo by zero"); return NULL; } else { mpz_cdiv_r_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), -temp_si); } Py_INCREF(a); return a; } if (CHECK_MPZANY(b)) { if(mpz_sgn(Pyxmpz_AS_MPZ(b)) == 0) { ZERO_ERROR("xmpz modulo by zero"); return NULL; } mpz_fdiv_r(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(b)); Py_INCREF(a); return a; } Py_RETURN_NOTIMPLEMENTED; }
void init_montgomery_R2(mpz_t n) { size_t i; mpz_set_ui(montgomery_gmp_help,1); mpz_mul_2exp(montgomery_gmp_help,montgomery_gmp_help,2*mp_bits_per_limb*montgomery_ulongs); mpz_fdiv_r(montgomery_gmp_help,montgomery_gmp_help,n); montgomery_modulo_R2[0]=mpz_get_ui(montgomery_gmp_help); for (i=1; i<montgomery_ulongs; i++) { mpz_fdiv_q_2exp(montgomery_gmp_help,montgomery_gmp_help,mp_bits_per_limb); montgomery_modulo_R2[i]=mpz_get_ui(montgomery_gmp_help); } }
static PyObject * GMPy_XMPZ_IRem_Slot(PyObject *self, PyObject *other) { if (PyIntOrLong_Check(other)) { int error; native_si temp = GMPy_Integer_AsNative_siAndError(other, &error); if (!error) { if (temp > 0) { mpz_fdiv_r_ui(MPZ(self), MPZ(self), temp); } else if (temp == 0) { ZERO_ERROR("xmpz modulo by zero"); return NULL; } else { mpz_cdiv_r_ui(MPZ(self), MPZ(self), -temp); } } else { mpz_set_PyIntOrLong(global.tempz, other); mpz_fdiv_r(MPZ(self), MPZ(self), global.tempz); } Py_INCREF(self); return self; } if (CHECK_MPZANY(other)) { if(mpz_sgn(MPZ(other)) == 0) { ZERO_ERROR("xmpz modulo by zero"); return NULL; } mpz_fdiv_r(MPZ(self), MPZ(self), MPZ(other)); Py_INCREF(self); return self; } Py_RETURN_NOTIMPLEMENTED; }
void gcd( mpz_t g, mpz_t a, mpz_t b ) { mpz_t temp; mpz_init (temp); while ( mpz_cmp_ui (b, 0) > 0 ) { mpz_set (temp, b); mpz_fdiv_r (b, a, b); mpz_set (a, temp); } mpz_mul_ui (a, a, mpz_sgn (a)); mpz_set (g, a); mpz_clear (temp); return; }
bool Rational::isInteger(const Rational& tolerance) const { // if denominator is 1, then it is an integer for sure if (mpz_cmp_ui(mpq_denref(number), 1) == 0) return true; // otherwise, we must check w.r.t. the given tolerance // first calculate the fractional part Rational viol(*this); viol.abs(); mpz_t r; mpz_init(r); mpz_fdiv_r(r, mpq_numref(viol.number), mpq_denref(viol.number)); mpq_set_num(viol.number, r); mpz_clear(r); // then integrality violation if( viol > Rational(1, 2) ) sub(viol, Rational(1,1), viol); return !(viol > tolerance); }
void Rational::integralityViolation(Rational& violation) const { // if denominator is 1, then there is no integrality violation for sure if( mpz_cmp_ui(mpq_denref(number), 1) == 0 ) { violation.toZero(); return; } // otherwise, we must check w.r.t. the given tolerance // first calculate the fractional part violation = (*this); violation.abs(); mpz_t r; mpz_init(r); mpz_fdiv_r(r, mpq_numref(violation.number), mpq_denref(violation.number)); mpq_set_num(violation.number, r); mpz_clear(r); // then integrality violation if( violation > Rational(1, 2) ) sub(violation, Rational(1,1), violation); }
int compute(mw_work_t *work, mw_result_t **res) { // printf("lower_bound: %s, upper_bound: %s\n", // work->lower_bound, work->upper_bound); mpz_t start, end, object; mpz_init_set_str(start, work->lower_bound, 10); mpz_init_set_str(end, work->upper_bound, 10); mpz_init_set_str(object, work->object, 10); mpz_add_ui(end, end, 1); node *head = NULL; node *prev = NULL; int size = 0; mpz_t remain; mpz_init(remain); while(mpz_cmp(start,end)){ mpz_fdiv_r(remain, object, start); if(!mpz_cmp_ui(remain,0)){ node *curr = init_node(start); if(head==NULL){ head = curr; prev = curr; } else { prev->next = curr; prev = prev->next; } size++; } mpz_add_ui(start, start, 1); } *res = (mw_result_t *) malloc((size+1) * sizeof(mw_result_t)); int i = 0; for(i = 0;i < size; ++i) { mpz_get_str ((*res)[i].factor, 10, head->val); head = head->next; } return size; }
void check_random (int reps) { gmp_randstate_t rands; mpz_t a, d, r; int i; int want; gmp_randinit_default(rands); mpz_init (a); mpz_init (d); mpz_init (r); for (i = 0; i < reps; i++) { mpz_erandomb (a, rands, 512); mpz_erandomb_nonzero (d, rands, 512); mpz_fdiv_r (r, a, d); want = (mpz_sgn (r) == 0); check_one (a, d, want); mpz_sub (a, a, r); check_one (a, d, 1); if (mpz_cmpabs_ui (d, 1L) == 0) continue; mpz_add_ui (a, a, 1L); check_one (a, d, 0); } mpz_clear (a); mpz_clear (d); mpz_clear (r); gmp_randclear(rands); }
void check_random (int reps) { gmp_randstate_ptr rands = RANDS; mpz_t a, d, r; int i; int want; mpz_init (a); mpz_init (d); mpz_init (r); for (i = 0; i < reps; i++) { mpz_erandomb (a, rands, 1 << 19); mpz_erandomb_nonzero (d, rands, 1 << 18); mpz_fdiv_r (r, a, d); want = (mpz_sgn (r) == 0); check_one (a, d, want); mpz_sub (a, a, r); check_one (a, d, 1); if (mpz_cmpabs_ui (d, 1L) == 0) continue; mpz_add_ui (a, a, 1L); check_one (a, d, 0); } mpz_clear (a); mpz_clear (d); mpz_clear (r); }
extern void _jl_mpz_rem(mpz_t* rop, mpz_t* op1, mpz_t* op2) { mpz_fdiv_r(*rop, *op1, *op2); }
static gfc_dependency gfc_check_section_vs_section (gfc_ref *lref, gfc_ref *rref, int n) { gfc_array_ref l_ar; gfc_expr *l_start; gfc_expr *l_end; gfc_expr *l_stride; gfc_expr *l_lower; gfc_expr *l_upper; int l_dir; gfc_array_ref r_ar; gfc_expr *r_start; gfc_expr *r_end; gfc_expr *r_stride; gfc_expr *r_lower; gfc_expr *r_upper; int r_dir; l_ar = lref->u.ar; r_ar = rref->u.ar; /* If they are the same range, return without more ado. */ if (gfc_is_same_range (&l_ar, &r_ar, n, 0)) return GFC_DEP_EQUAL; l_start = l_ar.start[n]; l_end = l_ar.end[n]; l_stride = l_ar.stride[n]; r_start = r_ar.start[n]; r_end = r_ar.end[n]; r_stride = r_ar.stride[n]; /* If l_start is NULL take it from array specifier. */ if (NULL == l_start && IS_ARRAY_EXPLICIT (l_ar.as)) l_start = l_ar.as->lower[n]; /* If l_end is NULL take it from array specifier. */ if (NULL == l_end && IS_ARRAY_EXPLICIT (l_ar.as)) l_end = l_ar.as->upper[n]; /* If r_start is NULL take it from array specifier. */ if (NULL == r_start && IS_ARRAY_EXPLICIT (r_ar.as)) r_start = r_ar.as->lower[n]; /* If r_end is NULL take it from array specifier. */ if (NULL == r_end && IS_ARRAY_EXPLICIT (r_ar.as)) r_end = r_ar.as->upper[n]; /* Determine whether the l_stride is positive or negative. */ if (!l_stride) l_dir = 1; else if (l_stride->expr_type == EXPR_CONSTANT && l_stride->ts.type == BT_INTEGER) l_dir = mpz_sgn (l_stride->value.integer); else if (l_start && l_end) l_dir = gfc_dep_compare_expr (l_end, l_start); else l_dir = -2; /* Determine whether the r_stride is positive or negative. */ if (!r_stride) r_dir = 1; else if (r_stride->expr_type == EXPR_CONSTANT && r_stride->ts.type == BT_INTEGER) r_dir = mpz_sgn (r_stride->value.integer); else if (r_start && r_end) r_dir = gfc_dep_compare_expr (r_end, r_start); else r_dir = -2; /* The strides should never be zero. */ if (l_dir == 0 || r_dir == 0) return GFC_DEP_OVERLAP; /* Determine LHS upper and lower bounds. */ if (l_dir == 1) { l_lower = l_start; l_upper = l_end; } else if (l_dir == -1) { l_lower = l_end; l_upper = l_start; } else { l_lower = NULL; l_upper = NULL; } /* Determine RHS upper and lower bounds. */ if (r_dir == 1) { r_lower = r_start; r_upper = r_end; } else if (r_dir == -1) { r_lower = r_end; r_upper = r_start; } else { r_lower = NULL; r_upper = NULL; } /* Check whether the ranges are disjoint. */ if (l_upper && r_lower && gfc_dep_compare_expr (l_upper, r_lower) == -1) return GFC_DEP_NODEP; if (r_upper && l_lower && gfc_dep_compare_expr (r_upper, l_lower) == -1) return GFC_DEP_NODEP; /* Handle cases like x:y:1 vs. x:z:-1 as GFC_DEP_EQUAL. */ if (l_start && r_start && gfc_dep_compare_expr (l_start, r_start) == 0) { if (l_dir == 1 && r_dir == -1) return GFC_DEP_EQUAL; if (l_dir == -1 && r_dir == 1) return GFC_DEP_EQUAL; } /* Handle cases like x:y:1 vs. z:y:-1 as GFC_DEP_EQUAL. */ if (l_end && r_end && gfc_dep_compare_expr (l_end, r_end) == 0) { if (l_dir == 1 && r_dir == -1) return GFC_DEP_EQUAL; if (l_dir == -1 && r_dir == 1) return GFC_DEP_EQUAL; } /* Handle cases like x:y:2 vs. x+1:z:4 as GFC_DEP_NODEP. There is no dependency if the remainder of (l_start - r_start) / gcd(l_stride, r_stride) is nonzero. TODO: - Handle cases where x is an expression. - Cases like a(1:4:2) = a(2:3) are still not handled. */ #define IS_CONSTANT_INTEGER(a) ((a) && ((a)->expr_type == EXPR_CONSTANT) \ && (a)->ts.type == BT_INTEGER) if (IS_CONSTANT_INTEGER(l_start) && IS_CONSTANT_INTEGER(r_start) && IS_CONSTANT_INTEGER(l_stride) && IS_CONSTANT_INTEGER(r_stride)) { mpz_t gcd, tmp; int result; mpz_init (gcd); mpz_init (tmp); mpz_gcd (gcd, l_stride->value.integer, r_stride->value.integer); mpz_sub (tmp, l_start->value.integer, r_start->value.integer); mpz_fdiv_r (tmp, tmp, gcd); result = mpz_cmp_si (tmp, 0L); mpz_clear (gcd); mpz_clear (tmp); if (result != 0) return GFC_DEP_NODEP; } #undef IS_CONSTANT_INTEGER /* Check for forward dependencies x:y vs. x+1:z. */ if (l_dir == 1 && r_dir == 1 && l_start && r_start && gfc_dep_compare_expr (l_start, r_start) == -1 && l_end && r_end && gfc_dep_compare_expr (l_end, r_end) == -1) { /* Check that the strides are the same. */ if (!l_stride && !r_stride) return GFC_DEP_FORWARD; if (l_stride && r_stride && gfc_dep_compare_expr (l_stride, r_stride) == 0) return GFC_DEP_FORWARD; } /* Check for forward dependencies x:y:-1 vs. x-1:z:-1. */ if (l_dir == -1 && r_dir == -1 && l_start && r_start && gfc_dep_compare_expr (l_start, r_start) == 1 && l_end && r_end && gfc_dep_compare_expr (l_end, r_end) == 1) { /* Check that the strides are the same. */ if (!l_stride && !r_stride) return GFC_DEP_FORWARD; if (l_stride && r_stride && gfc_dep_compare_expr (l_stride, r_stride) == 0) return GFC_DEP_FORWARD; } /* Check for backward dependencies: Are the strides the same?. */ if ((!l_stride && !r_stride) || (l_stride && r_stride && gfc_dep_compare_expr (l_stride, r_stride) == 0)) { /* x:y vs. x+1:z. */ if (l_dir == 1 && r_dir == 1 && l_start && r_start && gfc_dep_compare_expr (l_start, r_start) == 1 && l_end && r_end && gfc_dep_compare_expr (l_end, r_end) == 1) return GFC_DEP_BACKWARD; /* x:y:-1 vs. x-1:z:-1. */ if (l_dir == -1 && r_dir == -1 && l_start && r_start && gfc_dep_compare_expr (l_start, r_start) == -1 && l_end && r_end && gfc_dep_compare_expr (l_end, r_end) == -1) return GFC_DEP_BACKWARD; } return GFC_DEP_OVERLAP; }
/* 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(); }
static PyObject * GMPy_Integer_Mod(PyObject *x, PyObject *y, CTXT_Object *context) { MPZ_Object *result; CHECK_CONTEXT(context); if (!(result = GMPy_MPZ_New(context))) return NULL; if (CHECK_MPZANY(x)) { if (PyIntOrLong_Check(y)) { int error; long temp = GMPy_Integer_AsLongAndError(y, &error); if (!error) { if (temp > 0) { mpz_fdiv_r_ui(result->z, MPZ(x), temp); } else if (temp == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } else { mpz_cdiv_r_ui(result->z, MPZ(x), -temp); } } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, y); mpz_fdiv_r(result->z, MPZ(x), tempz); mpz_cloc(tempz); } return (PyObject*)result; } if (CHECK_MPZANY(y)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } mpz_fdiv_r(result->z, MPZ(x), MPZ(y)); return (PyObject*)result; } } if (CHECK_MPZANY(y)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } if (PyIntOrLong_Check(x)) { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, x); mpz_fdiv_r(result->z, tempz, MPZ(y)); mpz_cloc(tempz); return (PyObject*)result; } } if (IS_INTEGER(x) && IS_INTEGER(y)) { MPZ_Object *tempx, *tempy; tempx = GMPy_MPZ_From_Integer(x, context); tempy = GMPy_MPZ_From_Integer(y, context); if (!tempx || !tempy) { SYSTEM_ERROR("could not convert Integer to mpz"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } if (mpz_sgn(tempy->z) == 0) { ZERO_ERROR("division or modulo by zero"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } mpz_fdiv_r(result->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return (PyObject*)result; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; }
/* Evaluate the expression E and put the result in R. */ void mpz_eval_expr (mpz_ptr r, expr_t e) { mpz_t lhs, rhs; switch (e->op) { case LIT: mpz_set (r, e->operands.val); return; case PLUS: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_add (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MINUS: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_sub (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MULT: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_mul (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case DIV: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_fdiv_q (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MOD: mpz_init (rhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_abs (rhs, rhs); mpz_eval_mod_expr (r, e->operands.ops.lhs, rhs); mpz_clear (rhs); return; case REM: /* Check if lhs operand is POW expression and optimize for that case. */ if (e->operands.ops.lhs->op == POW) { mpz_t powlhs, powrhs; mpz_init (powlhs); mpz_init (powrhs); mpz_init (rhs); mpz_eval_expr (powlhs, e->operands.ops.lhs->operands.ops.lhs); mpz_eval_expr (powrhs, e->operands.ops.lhs->operands.ops.rhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_powm (r, powlhs, powrhs, rhs); if (mpz_cmp_si (rhs, 0L) < 0) mpz_neg (r, r); mpz_clear (powlhs); mpz_clear (powrhs); mpz_clear (rhs); return; } mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_fdiv_r (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION >= 2 case INVMOD: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_invert (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case POW: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_cmpabs_ui (lhs, 1) <= 0) { /* For 0^rhs and 1^rhs, we just need to verify that rhs is well-defined. For (-1)^rhs we need to determine (rhs mod 2). For simplicity, compute (rhs mod 2) for all three cases. */ expr_t two, et; two = malloc (sizeof (struct expr)); two -> op = LIT; mpz_init_set_ui (two->operands.val, 2L); makeexp (&et, MOD, e->operands.ops.rhs, two); e->operands.ops.rhs = et; } mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_cmp_si (rhs, 0L) == 0) /* x^0 is 1 */ mpz_set_ui (r, 1L); else if (mpz_cmp_si (lhs, 0L) == 0) /* 0^y (where y != 0) is 0 */ mpz_set_ui (r, 0L); else if (mpz_cmp_ui (lhs, 1L) == 0) /* 1^y is 1 */ mpz_set_ui (r, 1L); else if (mpz_cmp_si (lhs, -1L) == 0) /* (-1)^y just depends on whether y is even or odd */ mpz_set_si (r, (mpz_get_ui (rhs) & 1) ? -1L : 1L); else if (mpz_cmp_si (rhs, 0L) < 0) /* x^(-n) is 0 */ mpz_set_ui (r, 0L); else { unsigned long int cnt; unsigned long int y; /* error if exponent does not fit into an unsigned long int. */ if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) goto pow_err; y = mpz_get_ui (rhs); /* x^y == (x/(2^c))^y * 2^(c*y) */ #if __GNU_MP_VERSION >= 2 cnt = mpz_scan1 (lhs, 0); #else cnt = 0; #endif if (cnt != 0) { if (y * cnt / cnt != y) goto pow_err; mpz_tdiv_q_2exp (lhs, lhs, cnt); mpz_pow_ui (r, lhs, y); mpz_mul_2exp (r, r, y * cnt); } else mpz_pow_ui (r, lhs, y); } mpz_clear (lhs); mpz_clear (rhs); return; pow_err: error = "result of `pow' operator too large"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); case GCD: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_gcd (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case LCM: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_lcm (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case AND: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_and (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case IOR: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_ior (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case XOR: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_xor (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case NEG: mpz_eval_expr (r, e->operands.ops.lhs); mpz_neg (r, r); return; case NOT: mpz_eval_expr (r, e->operands.ops.lhs); mpz_com (r, r); return; case SQRT: mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) < 0) { error = "cannot take square root of negative numbers"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_sqrt (r, lhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case ROOT: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_sgn (rhs) <= 0) { error = "cannot take non-positive root orders"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } if (mpz_sgn (lhs) < 0 && (mpz_get_ui (rhs) & 1) == 0) { error = "cannot take even root orders of negative numbers"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } { unsigned long int nth = mpz_get_ui (rhs); if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) { /* If we are asked to take an awfully large root order, cheat and ask for the largest order we can pass to mpz_root. This saves some error prone special cases. */ nth = ~(unsigned long int) 0; } mpz_root (r, lhs, nth); } mpz_clear (lhs); mpz_clear (rhs); return; #endif case FAC: mpz_eval_expr (r, e->operands.ops.lhs); if (mpz_size (r) > 1) { error = "result of `!' operator too large"; longjmp (errjmpbuf, 1); } mpz_fac_ui (r, mpz_get_ui (r)); return; #if __GNU_MP_VERSION >= 2 case POPCNT: mpz_eval_expr (r, e->operands.ops.lhs); { long int cnt; cnt = mpz_popcount (r); mpz_set_si (r, cnt); } return; case HAMDIST: { long int cnt; mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); cnt = mpz_hamdist (lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); mpz_set_si (r, cnt); } return; #endif case LOG2: mpz_eval_expr (r, e->operands.ops.lhs); { unsigned long int cnt; if (mpz_sgn (r) <= 0) { error = "logarithm of non-positive number"; longjmp (errjmpbuf, 1); } cnt = mpz_sizeinbase (r, 2); mpz_set_ui (r, cnt - 1); } return; case LOG: { unsigned long int cnt; mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_sgn (lhs) <= 0) { error = "logarithm of non-positive number"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } if (mpz_cmp_ui (rhs, 256) >= 0) { error = "logarithm base too large"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } cnt = mpz_sizeinbase (lhs, mpz_get_ui (rhs)); mpz_set_ui (r, cnt - 1); mpz_clear (lhs); mpz_clear (rhs); } return; case FERMAT: { unsigned long int t; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); t = (unsigned long int) 1 << mpz_get_ui (lhs); if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0 || t == 0) { error = "too large Mersenne number index"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_set_ui (r, 1); mpz_mul_2exp (r, r, t); mpz_add_ui (r, r, 1); mpz_clear (lhs); } return; case MERSENNE: mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0) { error = "too large Mersenne number index"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_set_ui (r, 1); mpz_mul_2exp (r, r, mpz_get_ui (lhs)); mpz_sub_ui (r, r, 1); mpz_clear (lhs); return; case FIBONACCI: { mpz_t t; unsigned long int n, i; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0) { error = "Fibonacci index out of range"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } n = mpz_get_ui (lhs); mpz_clear (lhs); #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 mpz_fib_ui (r, n); #else mpz_init_set_ui (t, 1); mpz_set_ui (r, 1); if (n <= 2) mpz_set_ui (r, 1); else { for (i = 3; i <= n; i++) { mpz_add (t, t, r); mpz_swap (t, r); } } mpz_clear (t); #endif } return; case RANDOM: { unsigned long int n; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0) { error = "random number size out of range"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } n = mpz_get_ui (lhs); mpz_clear (lhs); mpz_urandomb (r, rstate, n); } return; case NEXTPRIME: { mpz_eval_expr (r, e->operands.ops.lhs); mpz_nextprime (r, r); } return; case BINOM: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); { unsigned long int k; if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) { error = "k too large in (n over k) expression"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } k = mpz_get_ui (rhs); mpz_bin_ui (r, lhs, k); } mpz_clear (lhs); mpz_clear (rhs); return; case TIMING: { int t0; t0 = cputime (); mpz_eval_expr (r, e->operands.ops.lhs); printf ("time: %d\n", cputime () - t0); } return; default: abort (); } }
/* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4. * * The hash function used is SHA384. * The exponent e used is the value in pub->e. */ int _rsa_generate_fips186_4_keypair(struct rsa_public_key *pub, struct rsa_private_key *key, unsigned seed_length, uint8_t * seed, void *progress_ctx, nettle_progress_func * progress, /* Desired size of modulo, in bits */ unsigned n_size) { mpz_t t, r, p1, q1, lcm; int ret; struct dss_params_validation_seeds cert; unsigned l = n_size / 2; if (_gnutls_fips_mode_enabled() != 0) { if (n_size == 2048) { if (seed_length != 14 * 2) { _gnutls_debug_log("Seed length must be 28 bytes (it is %d)\n", seed_length); return 0; } } else if (n_size == 3072) { if (seed_length != 16 * 2) { _gnutls_debug_log("Seed length must be 32 bytes (it is %d)\n", seed_length); return 0; } } else { _gnutls_debug_log("Unsupported size for modulus\n"); return 0; } } if (!mpz_tstbit(pub->e, 0)) { _gnutls_debug_log("Unacceptable e (it is even)\n"); return 0; } if (mpz_cmp_ui(pub->e, 65536) <= 0) { _gnutls_debug_log("Unacceptable e\n"); return 0; } mpz_init(p1); mpz_init(q1); mpz_init(lcm); mpz_init(t); mpz_init(r); mpz_set_ui(t, 1); mpz_mul_2exp(t, t, 256); if (mpz_cmp(pub->e, t) >= 0) { ret = 0; goto cleanup; } cert.pseed_length = sizeof(cert.pseed); ret = rsa_provable_prime(key->p, &cert.pseed_length, cert.pseed, l, seed_length, seed, pub->e, progress_ctx, progress); if (ret == 0) { goto cleanup; } mpz_set_ui(r, 1); mpz_mul_2exp(r, r, (l) - 100); do { cert.qseed_length = sizeof(cert.qseed); ret = rsa_provable_prime(key->q, &cert.qseed_length, cert.qseed, l, cert.pseed_length, cert.pseed, pub->e, progress_ctx, progress); if (ret == 0) { goto cleanup; } cert.pseed_length = cert.qseed_length; memcpy(cert.pseed, cert.qseed, cert.qseed_length); if (mpz_cmp(key->p, key->q) > 0) mpz_sub(t, key->p, key->q); else mpz_sub(t, key->q, key->p); } while (mpz_cmp(t, r) <= 0); memset(&cert, 0, sizeof(cert)); mpz_mul(pub->n, key->p, key->q); assert(mpz_sizeinbase(pub->n, 2) == n_size); /* c = q^{-1} (mod p) */ assert(mpz_invert(key->c, key->q, key->p) != 0); mpz_sub_ui(p1, key->p, 1); mpz_sub_ui(q1, key->q, 1); mpz_lcm(lcm, p1, q1); if (mpz_invert(key->d, pub->e, lcm) == 0) { ret = 0; goto cleanup; } /* Done! Almost, we must compute the auxillary private values. */ /* a = d % (p-1) */ mpz_fdiv_r(key->a, key->d, p1); /* b = d % (q-1) */ mpz_fdiv_r(key->b, key->d, q1); /* c was computed earlier */ pub->size = key->size = (n_size + 7) / 8; assert(pub->size >= RSA_MINIMUM_N_OCTETS); ret = 1; cleanup: mpz_clear(p1); mpz_clear(q1); mpz_clear(lcm); mpz_clear(t); mpz_clear(r); return ret; }
void ConstFoldBinop(BinopKind kind, const mpz_t left_val, const mpz_t right_val, mpz_t res) { switch (kind) { case B_Plus: mpz_add(res, left_val, right_val); break; case B_Minus: case B_MinusPP: // TODO: include scaling here? mpz_sub(res, left_val, right_val); break; case B_Mult: mpz_mul(res, left_val, right_val); break; case B_Div: case B_DivExact: // treat like regular division during folding. // leave zero value for division by zero. if (mpz_cmp_si(right_val, 0) != 0) mpz_fdiv_q(res, left_val, right_val); break; case B_Mod: // ditto for modulus by zero or negative values. if (mpz_cmp_si(right_val, 0) > 0) mpz_fdiv_r(res, left_val, right_val); break; case B_ShiftLeft: // ditto for left shifts by negative or large values. if (mpz_cmp_si(right_val, 0) >= 0 && mpz_cmp_si(right_val, 64) <= 0) mpz_mul_2exp(res, left_val, mpz_get_ui(right_val)); break; case B_ShiftRight: // ditto for right shifts by negative values or large values. if (mpz_cmp_si(right_val, 0) >= 0 && mpz_cmp_si(right_val, 64) <= 0) mpz_tdiv_q_2exp(res, left_val, mpz_get_ui(right_val)); break; case B_BitwiseAnd: mpz_and(res, left_val, right_val); break; case B_BitwiseOr: mpz_ior(res, left_val, right_val); break; case B_BitwiseXOr: mpz_xor(res, left_val, right_val); break; case B_Min: if (mpz_cmp(left_val, right_val) < 0) mpz_set(res, left_val); else mpz_set(res, right_val); break; case B_Max: if (mpz_cmp(left_val, right_val) > 0) mpz_set(res, left_val); else mpz_set(res, right_val); break; case B_LessThan: case B_LessThanP: FoldBoolean(res, mpz_cmp(left_val, right_val) < 0); break; case B_GreaterThan: case B_GreaterThanP: FoldBoolean(res, mpz_cmp(left_val, right_val) > 0); break; case B_LessEqual: case B_LessEqualP: FoldBoolean(res, mpz_cmp(left_val, right_val) <= 0); break; case B_GreaterEqual: case B_GreaterEqualP: FoldBoolean(res, mpz_cmp(left_val, right_val) >= 0); break; case B_Equal: case B_EqualP: FoldBoolean(res, mpz_cmp(left_val, right_val) == 0); break; case B_NotEqual: case B_NotEqualP: FoldBoolean(res, mpz_cmp(left_val, right_val) != 0); break; case B_LogicalAnd: FoldBoolean(res, mpz_cmp_si(left_val, 0) != 0 && mpz_cmp_si(right_val, 0) != 0); break; case B_LogicalOr: FoldBoolean(res, mpz_cmp_si(left_val, 0) != 0 || mpz_cmp_si(right_val, 0) != 0); break; default: logout << "ERROR: ConstFoldBinop: Unexpected " << BinopString(kind) << " " << left_val << " " << right_val << endl; Assert(false); } }