int main() { mpz_t a,b,r; mpz_init(a); mpz_init(b); mpz_init(r); printf("Enter a:"); gmp_scanf("%Zd",a); printf("Enter b:"); gmp_scanf("%Zd",b); mpz_abs(a,a); mpz_abs(b,b); gcd(r,a,b); gmp_printf("GCD : %Zd \n",r); mpz_clear(a); mpz_clear(b); mpz_clear(r); }
static PyObject * GMPy_Rational_Abs(PyObject *x, CTXT_Object *context) { MPQ_Object *result = NULL; if (MPQ_Check(x)) { if (mpz_sgn(mpq_numref(MPQ(x))) >= 0) { Py_INCREF(x); return x; } else { if ((result = GMPy_MPQ_New(context))) { mpq_set(result->q, MPQ(x)); mpz_abs(mpq_numref(result->q), mpq_numref(result->q)); } return (PyObject*)result; } } /* This is safe because result is not an incremented reference to an * existing value. MPQ is already handled so GMPy_MPQ_From_Rational() * can't return an incremented reference to an existing value (which it * would do if passed an MPQ). */ if ((result = GMPy_MPQ_From_Rational(x, context))) { mpz_abs(mpq_numref(result->q), mpq_numref(result->q)); } return (PyObject*)result; }
static PyObject * GMPy_Integer_Abs(PyObject *x, CTXT_Object *context) { MPZ_Object *result = NULL; if (MPZ_Check(x)) { if (mpz_sgn(MPZ(x)) >= 0) { Py_INCREF(x); return x; } else { if ((result = GMPy_MPZ_New(context))) mpz_abs(result->z, MPZ(x)); return (PyObject*)result; } } /* This is safe because result is not an incremented reference to an * existing value. Why? * 1) No values are interned like Python's integers. * 2) MPZ is already handled so GMPy_MPZ_From_Integer() can't return * an incremented reference to an existing value (which it would do * if passed an MPZ). */ if ((result = GMPy_MPZ_From_Integer(x, context))) { mpz_abs(result->z, result->z); } return (PyObject*)result; }
/** * Stein's binary greatest common divisor algorithm */ void cpt_bin_gcd(mpz_t res, mpz_srcptr a, mpz_srcptr b) { mpz_t x,y,p,r; mpz_init(x); mpz_init(y); mpz_init(r); mpz_abs(x,a); mpz_abs(y,b); if(mpz_cmp_si(x,0) == 0) { mpz_set(res,y); mpz_clear(x); mpz_clear(y); mpz_clear(r); return; } if(mpz_cmp_si(y,0) == 0) { mpz_set(res,x); mpz_clear(x); mpz_clear(y); mpz_clear(r); return; } mpz_init_set_si(p,1); while(mpz_even_p(x) && mpz_even_p(y)) { mpz_divexact_ui(x,x,2); mpz_divexact_ui(y,y,2); mpz_mul_ui(p,p,2); } while(mpz_even_p(x)) mpz_divexact_ui(x,x,2); while(mpz_even_p(y)) mpz_divexact_ui(y,y,2); if(mpz_cmp(x,y) > 0) mpz_swap(x,y); while(mpz_cmp_si(x,0) > 0) { mpz_sub(r,y,x); while(mpz_cmp_si(r,0) && mpz_even_p(r)) mpz_divexact_ui(r,r,2); if(mpz_cmp(r,x) >= 0) mpz_set(y,r); else { mpz_set(y,x); mpz_set(x,r); } } mpz_mul(res,p,y); mpz_clear(x); mpz_clear(y); mpz_clear(p); mpz_clear(r); }
char * mpc_get_str (mpc_t op) { char *return_value; mpz_t temp_op; mpz_t temp1; mpz_t temp2; if (op.precision == 0) return_value = mpz_get_str (NULL, 10, op.object); else { mpz_init (temp_op); mpz_abs (temp_op, op.object); mpz_init_set (temp1, temp_op); mpz_init_set_ui (temp2, 1); power_of_ten (temp2, op.precision); mpz_tdiv_q (temp1, temp1, temp2); return_value = concatinate_free (mpz_get_str (NULL, 10, temp1), ".", true, false); mpz_mul (temp1, temp1, temp2); mpz_sub (temp1, temp_op, temp1); mpz_abs (temp1, temp1); mpz_tdiv_q_ui (temp2, temp2, 10); while (mpz_cmp (temp2, temp1) > 0) { return_value = concatinate_free (return_value, "0", true, false); mpz_tdiv_q_ui (temp2, temp2, 10); } return_value = concatinate_free (return_value, mpz_get_str (NULL, 10, temp1), true, true); if (mpz_sgn (op.object) < 0) return_value = concatinate_free ("-", return_value, false, true); mpz_clear (temp1); mpz_clear (temp2); mpz_clear (temp_op); } return return_value; }
void LLLoperations::REDI(int k, int ell, MutableMatrix *A, MutableMatrix *Achange, // can be NULL MutableMatrix *lambda) { // set q = ... // negate q. ring_elem Dl, mkl, q; if (!lambda->get_entry(ell,k,mkl)) return; lambda->get_entry(ell,ell,Dl); mpz_ptr a = mkl.get_mpz(); mpz_ptr b = Dl.get_mpz(); // b = D#ell mpz_t c, d; mpz_init(c); mpz_init(d); mpz_mul_2exp(c,a,1); // c = 2*lambda#(k,ell) mpz_abs(d,c); // d = abs(2*lambda#(k,ell) mpz_add(c,c,b); // c = 2*lambda#(k,ell) + D#ell mpz_mul_2exp(d,b,1); // d = 2*D#ell mpz_fdiv_q(c,c,d); // c = (almost) final q mpz_neg(c,c); q = c; //A->addColumnMultiple(ell,q,k); //lambda->addColumnMultiple(ell,q,k); A->column_op(k,q,ell); if (Achange) Achange->column_op(k,q,ell); lambda->column_op(k,q,ell); mpz_clear(c); mpz_clear(d); }
ring_elem RingZZ::remainderAndQuotient(const ring_elem f, const ring_elem g, ring_elem ") const { mpz_ptr q = new_elem(); mpz_ptr r = new_elem(); int gsign = mpz_sgn(g.get_mpz()); mpz_t gg, ghalf; mpz_init(gg); mpz_init(ghalf); mpz_abs(gg,g.get_mpz()); mpz_fdiv_qr(q, r, f.get_mpz(), gg); mpz_tdiv_q_2exp(ghalf, gg, 1); if (mpz_cmp(r,ghalf) > 0) // r > ghalf { mpz_sub(r,r,gg); mpz_add_ui(q,q,1); } if (gsign < 0) mpz_neg(q,q); mpz_clear(gg); mpz_clear(ghalf); quot = ring_elem(q); return ring_elem(r); }
void pollard(mpz_t x_1, mpz_t x_2, mpz_t d, mpz_t n, int init, int c, int counter) { if(mpz_divisible_ui_p(n, 2)) { mpz_set_ui(d, 2); return; } mpz_set_ui(x_1, init); NEXT_VALUE(x_1, x_1, n, c); NEXT_VALUE(x_2, x_1, n, c); mpz_set_ui(d, 1); while (mpz_cmp_ui(d, 1) == 0) { NEXT_VALUE(x_1, x_1, n, c); NEXT_VALUE(x_2, x_2, n, c); NEXT_VALUE(x_2, x_2, n, c); mpz_sub(d, x_2, x_1); mpz_abs(d, d); mpz_gcd(d, d, n); if (counter < 0) { mpz_set_ui(d, 0); return; } else { --counter; } } if(mpz_cmp(d, n) == 0) { return pollard(x_1, x_2, d, n, primes[RAND], primes[RAND], counter); } }
/* See Cohen 1.5.3 */ int modified_cornacchia(mpz_t x, mpz_t y, mpz_t D, mpz_t p) { int result = 0; mpz_t a, b, c, d; if (mpz_cmp_ui(p, 2) == 0) { mpz_add_ui(x, D, 8); if (mpz_perfect_square_p(x)) { mpz_sqrt(x, x); mpz_set_ui(y, 1); result = 1; } return result; } if (mpz_jacobi(D, p) == -1) /* No solution */ return 0; mpz_init(a); mpz_init(b); mpz_init(c); mpz_init(d); sqrtmod(x, D, p, a, b, c, d); if ( (mpz_even_p(D) && mpz_odd_p(x)) || (mpz_odd_p(D) && mpz_even_p(x)) ) mpz_sub(x, p, x); mpz_mul_ui(a, p, 2); mpz_set(b, x); mpz_sqrt(c, p); mpz_mul_ui(c, c, 2); /* Euclidean algorithm */ while (mpz_cmp(b, c) > 0) { mpz_set(d, a); mpz_set(a, b); mpz_mod(b, d, b); } mpz_mul_ui(c, p, 4); mpz_mul(a, b, b); mpz_sub(a, c, a); /* a = 4p - b^2 */ mpz_abs(d, D); /* d = |D| */ if (mpz_divisible_p(a, d)) { mpz_divexact(c, a, d); if (mpz_perfect_square_p(c)) { mpz_set(x, b); mpz_sqrt(y, c); result = 1; } } mpz_clear(a); mpz_clear(b); mpz_clear(c); mpz_clear(d); return result; }
int main (int argc, char **argv) { mpz_t x2; mpz_t root1; mp_size_t x2_size; int i; int reps = 5000; unsigned long nth; 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 (x2); mpz_init (root1); /* This triggers a gcc 4.3.2 bug */ mpz_set_str (x2, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000002", 16); mpz_root (root1, x2, 2); check_one (root1, x2, 2, -1); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 12 + 2; mpz_urandomb (bs, rands, size_range); x2_size = mpz_get_ui (bs) + 10; mpz_rrandomb (x2, rands, x2_size); mpz_urandomb (bs, rands, 15); nth = mpz_getlimbn (bs, 0) % mpz_sizeinbase (x2, 2) + 2; mpz_root (root1, x2, nth); mpz_urandomb (bs, rands, 4); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) { /* With 50% probability, set x2 near a perfect power. */ mpz_pow_ui (x2, root1, nth); if ((bsi & 2) != 0) { mpz_sub_ui (x2, x2, bsi >> 2); mpz_abs (x2, x2); } else
int main (int argc, char **argv) { mpz_t x2; mpz_t x; mpz_t temp, temp2; mp_size_t x2_size; int i; int reps = 1000; unsigned long nth; 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 (x2); mpz_init (x); mpz_init (temp); mpz_init (temp2); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 12 + 2; mpz_urandomb (bs, rands, size_range); x2_size = mpz_get_ui (bs) + 10; mpz_rrandomb (x2, rands, x2_size); mpz_urandomb (bs, rands, 15); nth = mpz_getlimbn (bs, 0) % mpz_sizeinbase (x2, 2) + 2; mpz_root (x, x2, nth); mpz_urandomb (bs, rands, 4); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) { /* With 50% probability, set x2 near a perfect power. */ mpz_pow_ui (x2, x, nth); if ((bsi & 2) != 0) { mpz_sub_ui (x2, x2, bsi >> 2); mpz_abs (x2, x2); } else
/** \brief 整系数多项式1-范数. \param f 整系数多项式. \return 系数向量的1-范数. */ void UniOneNormZ(mpz_ptr r,const poly_z & f) { mpz_set_ui(r,0); static mpz_t temp; mpz_init(temp); for(int i=0;i<f.size();i++) { mpz_abs(temp,f[i]); mpz_add(r,r,temp); } mpz_clear(temp); }
static PyObject * Pympq_abs(PympqObject *self) { PympqObject *result; if ((result = (PympqObject*)Pympq_new())) { mpq_set(result->q, self->q); mpz_abs(mpq_numref(result->q), mpq_numref(result->q)); } return (PyObject*)result; }
RCP<const Integer> iabs(const Integer &n) { mpz_class m; mpz_t m_t; mpz_init(m_t); mpz_abs(m_t, n.as_mpz().get_mpz_t()); m = mpz_class(m_t); mpz_clear(m_t); return integer(mpz_class(m)); }
/** \brief 整系数多项式无穷范数. \param f 整系数多项式. \param r 系数向量的无穷范数. */ void UniMaxNormZ(mpz_ptr r,const poly_z & f) { mpz_set_ui(r,0); mpz_t tempz; mpz_init(tempz); for(int i=0;i<f.size();i++) { mpz_abs(tempz,f[i]); if(mpz_cmp(r,tempz)<0)mpz_set(r,tempz); } mpz_clear(tempz); return ; }
/* This routine will scan over the sieve for values that look promising, and then attempt to factor * them over the factor base. If it finds one that factors (or is a partial), it will add it to the * list that we're accumulating for this poly_group. */ void extract_relations (block_data_t *data, poly_group_t *pg, poly_t *p, nsieve_t *ns, int block_start){ /* The sieve now contains estimates of the size (in bits) of the unfactored portion of the * polynomial values. We scan the sieve for values less than this cutoff, and trial divide * the ones that pass the test. */ mpz_t temp; mpz_init (temp); poly(temp, p, block_start + BLOCKSIZE/2); mpz_abs(temp, temp); uint8_t logQ = (uint8_t) mpz_sizeinbase (temp, 2); int cutoff = (int) (fast_log(ns->lp_bound) * ns->T); /* To accelerate the sieve scanning for promising values, instead of comparing each 8-bit entry * one at a time, we instead look at 64 bits at a time. We are looking for sieve values such that * sieve[x] > logQ - cutoff. We can use as a first approximation to this the test that * sieve[x] > S, where S is the smallest power of 2 larger than (logQ - cutoff). Create an 8-bit * mask - say S is 32 - the mask is 11100000. Then if you AND the mask with any sieve value, and * the result is nonzero, it cannot possibly be below the cutoff. Make 8 copies of the mask, put * it in a 64-bit int, cast the pointer to the sieve block, and do this AND on 64-bit chunks (8 * sieve locations at a time). Since it will be relatively rare for a value to pass the cutoff, * most of the time this test will immediately reject all 8 values. If it doesn't, test each one * against the cutoff individually. */ uint64_t *chunk = (uint64_t *) data->sieve; uint32_t nchunks = BLOCKSIZE/8; uint8_t maskchar = 1; // this is the 8-bit version of the mask while (maskchar < logQ - cutoff){ maskchar *= 2; } maskchar /= 2; maskchar = ~ (maskchar - 1); uint64_t mask = maskchar; for (int i=0; i<8; i++){ // make 8 copies of it mask = (mask << 8) | maskchar; } // now loop over the sieve, a chunk at a time for (int i=0; i < nchunks; i++){ if (mask & chunk[i]){ // then some value *might* have passed the test for (int j=0; j<8; j++){ if (logQ - data->sieve[i*8+j] < cutoff){ // check them all poly (temp, p, block_start + i*8 + j); construct_relation (temp, block_start + i*8 + j, p, ns); } } } } mpz_clear (temp); }
static void rho(mpz_t R, mpz_t N) { mpz_t divisor; mpz_t c; mpz_t x; mpz_t xx; mpz_t abs; mpz_init(divisor); mpz_init(c); mpz_init(x); mpz_init(xx); mpz_init(abs); mpz_urandomm(c, randstate, N); mpz_urandomm(x, randstate, N); mpz_set(xx, x); /* check divisibility by 2 */ if (mpz_divisible_p(N, two)) { mpz_set(R, two); return; } do { /* Do this with x */ mpz_mul(x, x, x); mpz_mod(x, x, N); mpz_add(x, x, c); mpz_mod(x, x, N); /* First time with xx */ mpz_mul(xx, xx, xx); mpz_mod(xx, xx, N); mpz_add(xx, xx, c); mpz_mod(xx, xx, N); /* Second time with xx */ mpz_mul(xx, xx, xx); mpz_mod(xx, xx, N); mpz_add(xx, xx, c); mpz_mod(xx, xx, N); mpz_sub(abs, x, xx); mpz_abs(abs, abs); mpz_gcd(divisor, abs, N); } while (mpz_cmp(divisor, one) == 0); mpz_set(R, divisor); }
/** * Euclid's greatest common divisor algorithm */ void cpt_gcd(mpz_t res, mpz_srcptr a, mpz_srcptr b) { mpz_t aa, ab; /*************Initialization********/ mpz_init(aa); /*aa = |a|*/ mpz_init(ab); /*ab = |b|*/ mpz_abs(aa,a); mpz_abs(ab,b); /*If a > b, exchange them*/ if(mpz_cmp(aa,ab) > 0) mpz_swap(aa,ab); while(mpz_cmp_si(aa,0) > 0) { mpz_mod(ab,ab,aa); mpz_swap(aa,ab); } mpz_set(res,ab); /***************Clear**************/ mpz_clear(aa); mpz_clear(ab); }
void pollard_brent(mpz_t x_1, mpz_t x_2, mpz_t d, mpz_t n, int init, int c, int counter) { int i; for(i = 0; i < 10000; ++i) { if(mpz_divisible_ui_p(n, primes[i])) { mpz_set_ui(d, primes[i]); return; } } unsigned long power = 1; unsigned long lam = 1; mpz_set_ui(x_1, init); mpz_set_ui(d, 1); while(mpz_cmp_ui(d, 1) == 0) { if (power == lam) { mpz_set(x_2, x_1); power *= 2; lam = 0; } mpz_mul(x_1, x_1, x_1); mpz_add_ui(x_1, x_1, c); mpz_mod(x_1, x_1, n); mpz_sub(d, x_2, x_1); mpz_abs(d, d); mpz_gcd(d, d, n); lam++; if (counter < 0) { mpz_set_ui(d, 0); return; } else { --counter; } } if(mpz_cmp(d, n) == 0) { return pollard_brent(x_1, x_2, d, n, rand(), rand(), counter); } }
static Variant HHVM_FUNCTION(gmp_abs, const Variant& data) { mpz_t gmpReturn, gmpData; if (!variantToGMPData(cs_GMP_FUNC_NAME_GMP_ABS, gmpData, data)) { return false; } mpz_init(gmpReturn); mpz_abs(gmpReturn, gmpData); Variant ret = NEWOBJ(GMPResource)(gmpReturn); mpz_clear(gmpReturn); mpz_clear(gmpData); return ret; }
/* See Cohen 1.5.2 */ int cornacchia(mpz_t x, mpz_t y, mpz_t D, mpz_t p) { int result = 0; mpz_t a, b, c, d; if (mpz_jacobi(D, p) < 0) /* No solution */ return 0; mpz_init(a); mpz_init(b); mpz_init(c); mpz_init(d); sqrtmod(x, D, p, a, b, c, d); mpz_set(a, p); mpz_set(b, x); mpz_sqrt(c, p); while (mpz_cmp(b,c) > 0) { mpz_set(d, a); mpz_set(a, b); mpz_mod(b, d, b); } mpz_mul(a, b, b); mpz_sub(a, p, a); /* a = p - b^2 */ mpz_abs(d, D); /* d = |D| */ if (mpz_divisible_p(a, d)) { mpz_divexact(c, a, d); if (mpz_perfect_square_p(c)) { mpz_set(x, b); mpz_sqrt(y, c); result = 1; } } mpz_clear(a); mpz_clear(b); mpz_clear(c); mpz_clear(d); return result; }
void DMPZinteger_content(mpz_t content, DMPZ f) { DMPZ iter, min_ptr; size_t min; if (f == NULL) { mpz_set_ui(content, 0); return; } /* silly case, f==0 */ /* Start content with value of the "smallest" coefficient. */ min_ptr = f; min = mpz_sizeinbase(f->coeff, 2); for (iter=f; iter; iter = iter->next) if (mpz_sizeinbase(iter->coeff, 2) < min) { min = mpz_sizeinbase(iter->coeff, 2); min_ptr = iter; } mpz_abs(content, min_ptr->coeff); /* Now gcd content with all the other coefficients. */ for (iter=f; (mpz_cmp_ui(content, 1) != 0) && iter; iter = iter->next) if (iter != min_ptr) mpz_gcd(content, content, iter->coeff); }
void llln_redi (int k, int l, int C, int F) { int i; mpz_t q; mpz_t auxi1; mpz_init (q); mpz_init (auxi1); mpz_mul_ui (auxi1, llln_lambda[k][l], 2); mpz_abs (auxi1, auxi1); if (mpz_cmp (auxi1, llln_d[l]) > 0) { mpz_mul_ui (auxi1, llln_lambda[k][l], 2); mpz_add (auxi1, auxi1, llln_d[l]); mpz_mul_ui (q, llln_d[l], 2); mpz_fdiv_q (q, auxi1, q); for (i=1; i<F+1; i++) { mpz_mul (auxi1, q, llln_H[l][i]); mpz_sub (llln_H[k][i], llln_H[k][i], auxi1); } for (i=1; i<C+1; i++) { mpz_mul (auxi1, q, llln_b[l][i]); mpz_sub (llln_b[k][i], llln_b[k][i], auxi1); } mpz_mul (auxi1, q, llln_d[l]); mpz_sub (llln_lambda[k][l], llln_lambda[k][l], auxi1); for (i=1; i<=l-1; i++){ mpz_mul (auxi1, q, llln_lambda[l][i]); mpz_sub (llln_lambda[k][i], llln_lambda[k][i], auxi1); } } mpz_clear (q); mpz_clear (auxi1); }
std::vector<mpz_class> Sieve::Factor() { unsigned long int first = 0; int iter = 0; #ifdef PRINT std::cout << "beginning to factor"<< std::endl; std::cout << "num smooth required: " << numsmoothrequired << std::endl; std::cout << "MAXSWEEPS: " << MAXSWEEPS << std::endl; #endif while (numsmooth < numsmoothrequired && iter++ < MAXSWEEPS) { Sweep(first); updateThreshhold(); first += SIEVESIZE; } #ifdef PRINT std::cout << iter << " sweeps done"<< std::endl; #endif std::vector<mpz_class> factors; std::vector<int> nullvec; #ifdef PRINT std::cout << "num smooth found: " << numsmooth << std::endl; std::cout << "num tried: " << numtried << std::endl; #endif if (numsmooth == numsmoothrequired) { mpz_class a, b, ab, factor1; matrixptr->gauss(); for (int i = 0; i < 20 && matrixptr->hasMoreSolutions(); ++i) { nullvec = matrixptr->getNextSolution(); a = 1; b = 1; for (int j = 0; j < nullvec.size(); j++) { if (nullvec[j] == 1) { a = (a * smooth_x[j]); b = (b * smooth_y[j]); } } mpz_root(b.get_mpz_t(), b.get_mpz_t(), 2); ab = a - b; mpz_abs(ab.get_mpz_t(), ab.get_mpz_t()); mpz_gcd(factor1.get_mpz_t(), ab.get_mpz_t(), N.get_mpz_t()); if (factor1 != 1 && factor1 != N) { bool exists = false; for (std::vector<mpz_class>::iterator it = factors.begin(); it != factors.end(); ++it) { if ((*it) == factor1) { exists = true; break; } } if (!exists) { factors.push_back(factor1); i = 0; } } } } return factors; }
/* P1 <- V_e(P0), using P, Q as auxiliary variables, where V_{2k}(P0) = V_k(P0)^2 - 2 V_{2k-1}(P0) = V_k(P0)*V_{k-1}(P0) - P0. (More generally V_{m+n} = V_m * V_n - V_{m-n}.) Warning: P1 and P0 may be equal. */ static void pp1_mul (mpres_t P1, mpres_t P0, mpz_t e, mpmod_t n, mpres_t P, mpres_t Q) { mp_size_t size_e; unsigned long i; int sign; sign = mpz_sgn (e); mpz_abs (e, e); if (sign == 0) { mpres_set_ui (P1, 2, n); goto unnegate; } if (mpz_cmp_ui (e, 1) == 0) { mpres_set (P1, P0, n); goto unnegate; } /* now e >= 2 */ mpz_sub_ui (e, e, 1); mpres_sqr (P, P0, n); mpres_sub_ui (P, P, 2, n); /* P = V_2(P0) = P0^2-2 */ mpres_set (Q, P0, n); /* Q = V_1(P0) = P0 */ /* invariant: (P, Q) = (V_{k+1}(P0), V_k(P0)), start with k=1 */ size_e = mpz_sizeinbase (e, 2); for (i = size_e - 1; i > 0;) { if (mpz_tstbit (e, --i)) /* k -> 2k+1 */ { if (i) /* Q is not needed for last iteration */ { mpres_mul (Q, P, Q, n); mpres_sub (Q, Q, P0, n); } mpres_sqr (P, P, n); mpres_sub_ui (P, P, 2, n); } else /* k -> 2k */ { mpres_mul (P, P, Q, n); mpres_sub (P, P, P0, n); if (i) /* Q is not needed for last iteration */ { mpres_sqr (Q, Q, n); mpres_sub_ui (Q, Q, 2, n); } } } mpres_set (P1, P, n); mpz_add_ui (e, e, 1); /* recover original value of e */ unnegate: if (sign == -1) mpz_neg (e, e); return; }
/* return NULL if an error occurred */ pp1_roots_state_t * pp1_rootsG_init (mpres_t *x, root_params_t *root_params, mpmod_t modulus) { mpres_t P; pp1_roots_state_t *state; progression_params_t *params; /* for less typing */ unsigned long i; ASSERT (gcd (root_params->d1, root_params->d2) == 1); state = (pp1_roots_state_t *) malloc (sizeof (pp1_roots_state_t)); if (state == NULL) return NULL; params = &(state->params); /* we don't need the sign anymore after pp1_rootsG_init */ params->S = ABS(root_params->S); if (params->S == 1) { mpz_t t; mpz_init (t); mpres_init (P, modulus); for (i = 0; i < 4; i++) mpres_init (state->tmp[i], modulus); params->dsieve = root_params->d2; /* needed in pp1_rootsG */ /* We want to skip values where gcd((i0 + i) * d1, d2) != 1. We can test for gcd(i0 + i, d2) instead and let pp1_rootsG() advance params->rsieve in steps of 1 */ /* params->rsieve = i0 % d2 */ params->rsieve = mpz_fdiv_ui (root_params->i0, root_params->d2); outputf (OUTPUT_DEVVERBOSE, "pp1_rootsG_init: i0 = %Zd, state: " "dsieve = %d, rsieve = %d, S = %d\n", root_params->i0, params->dsieve, params->rsieve, params->S); mpz_set_ui (t, root_params->d1); pp1_mul (state->tmp[1], *x, t, modulus, state->tmp[3], P); pp1_mul (state->tmp[0], state->tmp[1], root_params->i0, modulus, state->tmp[3], P); mpz_sub_ui (t, root_params->i0, 1); mpz_abs (t, t); pp1_mul (state->tmp[2], state->tmp[1], t, modulus, state->tmp[3], P); /* for P+1, tmp[0] = V_s(P), tmp[1] = V_d1(P), tmp[2] = V_{|s-d1|}(P) */ mpres_clear (P, modulus); mpz_clear (t); } else { listz_t coeffs; params->dickson_a = (root_params->S < 0) ? -1 : 0; params->nr = (root_params->d2 > 1) ? root_params->d2 - 1 : 1; params->size_fd = params->nr * (params->S + 1); params->next = 0; params->dsieve = 1; params->rsieve = 1; state->fd = (point *) malloc (params->size_fd * sizeof (point)); if (state->fd == NULL) { free (state); return NULL; } coeffs = init_progression_coeffs (root_params->i0, root_params->d2, root_params->d1, 1, 1, params->S, params->dickson_a); if (coeffs == NULL) { free (state->fd); free (state); return NULL; } for (i = 0; i < params->size_fd; i++) { mpres_init (state->fd[i].x, modulus); mpres_init (state->fd[i].y, modulus); /* The S-th coeff of all progressions is identical */ if (i > params->S && i % (params->S + 1) == params->S) { /* Simply copy from the first progression */ mpres_set (state->fd[i].x, state->fd[params->S].x, modulus); mpres_set (state->fd[i].y, state->fd[params->S].y, modulus); } else pp1_mul2 (state->fd[i].x, state->fd[i].y, x[0], coeffs[i], modulus); } clear_list (coeffs, params->size_fd); } return state; }
static void pp1_mul2 (mpres_t a, mpres_t b, mpres_t P, mpz_t e, mpmod_t n) { unsigned long l; mpres_t t; mpz_t abs_e; const int positive_e = (mpz_sgn (e) > 0); if (mpz_cmp_ui (e, 0UL) == 0) /* x^0 = 1 */ { mpres_set_ui (a, 0, n); mpres_set_ui (b, 1, n); return; } mpres_init (t, n); mpz_init (abs_e); mpz_abs (abs_e, e); if (positive_e) { mpres_set_ui (a, 1, n); mpres_set_ui (b, 0, n); } else { /* Set to -x+P */ mpres_set_ui (a, 1, n); mpres_neg (a, a, n); mpres_set (b, P, n); } l = mpz_sizeinbase (abs_e, 2) - 1; /* number of bits of e (minus 1) */ while (l--) { /* square: (ax+b)^2 = (a^2P+2ab) x + (b^2-a^2) */ mpres_sqr (t, a, n); /* a^2 */ mpres_mul (a, a, b, n); mpres_add (a, a, a, n); /* 2ab */ mpres_sqr (b, b, n); /* b^2 */ mpres_sub (b, b, t, n); /* b^2-a^2 */ mpres_mul (t, t, P, n); /* a^2P */ mpres_add (a, t, a, n); /* a^2P+2ab */ if (mpz_tstbit (abs_e, l)) { if (positive_e) { /* multiply: (ax+b)*x = (aP+b) x - a */ mpres_mul (t, a, P, n); mpres_add (t, t, b, n); mpres_neg (b, a, n); mpres_set (a, t, n); } else { /* multiply: (ax+b)*(-x+P) = -ax^2+(aP-b)x+b*P == -bx + (bP + a) (mod x^2-P*x+1) */ mpres_mul (t, b, P, n); mpres_add (t, t, a, n); mpres_neg (a, b, n); mpres_set (b, t, n); } } } mpz_clear (abs_e); mpres_clear (t, n); }
int main (int argc, char **argv) { mpz_t dividend, divisor; mpz_t quotient, remainder; mpz_t quotient2, remainder2; mpz_t temp; mp_size_t dividend_size, divisor_size; int i; int reps = 1000; 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 (dividend); mpz_init (divisor); mpz_init (quotient); mpz_init (remainder); mpz_init (quotient2); mpz_init (remainder2); mpz_init (temp); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 18 + 2; /* 0..524288 bit operands */ do { mpz_urandomb (bs, rands, size_range); divisor_size = mpz_get_ui (bs); mpz_rrandomb (divisor, rands, divisor_size); } while (mpz_sgn (divisor) == 0); mpz_urandomb (bs, rands, size_range); dividend_size = mpz_get_ui (bs) + divisor_size; mpz_rrandomb (dividend, rands, dividend_size); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (dividend, dividend); if ((bsi & 2) != 0) mpz_neg (divisor, divisor); /* printf ("%ld %ld\n", SIZ (dividend), SIZ (divisor)); */ mpz_tdiv_qr (quotient, remainder, dividend, divisor); mpz_tdiv_q (quotient2, dividend, divisor); mpz_tdiv_r (remainder2, dividend, divisor); /* First determine that the quotients and remainders computed with different functions are equal. */ if (mpz_cmp (quotient, quotient2) != 0) dump_abort (dividend, divisor); if (mpz_cmp (remainder, remainder2) != 0) dump_abort (dividend, divisor); /* Check if the sign of the quotient is correct. */ if (mpz_cmp_ui (quotient, 0) != 0) if ((mpz_cmp_ui (quotient, 0) < 0) != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0)) dump_abort (dividend, divisor); /* Check if the remainder has the same sign as the dividend (quotient rounded towards 0). */ if (mpz_cmp_ui (remainder, 0) != 0) if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0)) dump_abort (dividend, divisor); mpz_mul (temp, quotient, divisor); mpz_add (temp, temp, remainder); if (mpz_cmp (temp, dividend) != 0) dump_abort (dividend, divisor); mpz_abs (temp, divisor); mpz_abs (remainder, remainder); if (mpz_cmp (remainder, temp) >= 0) dump_abort (dividend, divisor); } mpz_clear (bs); mpz_clear (dividend); mpz_clear (divisor); mpz_clear (quotient); mpz_clear (remainder); mpz_clear (quotient2); mpz_clear (remainder2); mpz_clear (temp); tests_end (); exit (0); }
void spectral_test (mpf_t rop[], unsigned int T, mpz_t a, mpz_t m) { /* Knuth "Seminumerical Algorithms, Third Edition", section 3.3.4 (pp. 101-103). */ /* v[t] = min { sqrt (x[1]^2 + ... + x[t]^2) | x[1] + a*x[2] + ... + pow (a, t-1) * x[t] is congruent to 0 (mod m) } */ /* Variables. */ unsigned int ui_t; unsigned int ui_i, ui_j, ui_k, ui_l; mpf_t f_tmp1, f_tmp2; mpz_t tmp1, tmp2, tmp3; mpz_t U[GMP_SPECT_MAXT][GMP_SPECT_MAXT], V[GMP_SPECT_MAXT][GMP_SPECT_MAXT], X[GMP_SPECT_MAXT], Y[GMP_SPECT_MAXT], Z[GMP_SPECT_MAXT]; mpz_t h, hp, r, s, p, pp, q, u, v; /* GMP inits. */ mpf_init (f_tmp1); mpf_init (f_tmp2); for (ui_i = 0; ui_i < GMP_SPECT_MAXT; ui_i++) { for (ui_j = 0; ui_j < GMP_SPECT_MAXT; ui_j++) { mpz_init_set_ui (U[ui_i][ui_j], 0); mpz_init_set_ui (V[ui_i][ui_j], 0); } mpz_init_set_ui (X[ui_i], 0); mpz_init_set_ui (Y[ui_i], 0); mpz_init (Z[ui_i]); } mpz_init (tmp1); mpz_init (tmp2); mpz_init (tmp3); mpz_init (h); mpz_init (hp); mpz_init (r); mpz_init (s); mpz_init (p); mpz_init (pp); mpz_init (q); mpz_init (u); mpz_init (v); /* Implementation inits. */ if (T > GMP_SPECT_MAXT) T = GMP_SPECT_MAXT; /* FIXME: Lazy. */ /* S1 [Initialize.] */ ui_t = 2 - 1; /* NOTE: `t' in description == ui_t + 1 for easy indexing */ mpz_set (h, a); mpz_set (hp, m); mpz_set_ui (p, 1); mpz_set_ui (pp, 0); mpz_set (r, a); mpz_pow_ui (s, a, 2); mpz_add_ui (s, s, 1); /* s = 1 + a^2 */ /* S2 [Euclidean step.] */ while (1) { if (g_debug > DEBUG_1) { mpz_mul (tmp1, h, pp); mpz_mul (tmp2, hp, p); mpz_sub (tmp1, tmp1, tmp2); if (mpz_cmpabs (m, tmp1)) { printf ("***BUG***: h*pp - hp*p = "); mpz_out_str (stdout, 10, tmp1); printf ("\n"); } } if (g_debug > DEBUG_2) { printf ("hp = "); mpz_out_str (stdout, 10, hp); printf ("\nh = "); mpz_out_str (stdout, 10, h); printf ("\n"); fflush (stdout); } if (mpz_sgn (h)) mpz_tdiv_q (q, hp, h); /* q = floor(hp/h) */ else mpz_set_ui (q, 1); if (g_debug > DEBUG_2) { printf ("q = "); mpz_out_str (stdout, 10, q); printf ("\n"); fflush (stdout); } mpz_mul (tmp1, q, h); mpz_sub (u, hp, tmp1); /* u = hp - q*h */ mpz_mul (tmp1, q, p); mpz_sub (v, pp, tmp1); /* v = pp - q*p */ mpz_pow_ui (tmp1, u, 2); mpz_pow_ui (tmp2, v, 2); mpz_add (tmp1, tmp1, tmp2); if (mpz_cmp (tmp1, s) < 0) { mpz_set (s, tmp1); /* s = u^2 + v^2 */ mpz_set (hp, h); /* hp = h */ mpz_set (h, u); /* h = u */ mpz_set (pp, p); /* pp = p */ mpz_set (p, v); /* p = v */ } else break; } /* S3 [Compute v2.] */ mpz_sub (u, u, h); mpz_sub (v, v, p); mpz_pow_ui (tmp1, u, 2); mpz_pow_ui (tmp2, v, 2); mpz_add (tmp1, tmp1, tmp2); if (mpz_cmp (tmp1, s) < 0) { mpz_set (s, tmp1); /* s = u^2 + v^2 */ mpz_set (hp, u); mpz_set (pp, v); } mpf_set_z (f_tmp1, s); mpf_sqrt (rop[ui_t - 1], f_tmp1); /* S4 [Advance t.] */ mpz_neg (U[0][0], h); mpz_set (U[0][1], p); mpz_neg (U[1][0], hp); mpz_set (U[1][1], pp); mpz_set (V[0][0], pp); mpz_set (V[0][1], hp); mpz_neg (V[1][0], p); mpz_neg (V[1][1], h); if (mpz_cmp_ui (pp, 0) > 0) { mpz_neg (V[0][0], V[0][0]); mpz_neg (V[0][1], V[0][1]); mpz_neg (V[1][0], V[1][0]); mpz_neg (V[1][1], V[1][1]); } while (ui_t + 1 != T) /* S4 loop */ { ui_t++; mpz_mul (r, a, r); mpz_mod (r, r, m); /* Add new row and column to U and V. They are initialized with all elements set to zero, so clearing is not necessary. */ mpz_neg (U[ui_t][0], r); /* U: First col in new row. */ mpz_set_ui (U[ui_t][ui_t], 1); /* U: Last col in new row. */ mpz_set (V[ui_t][ui_t], m); /* V: Last col in new row. */ /* "Finally, for 1 <= i < t, set q = round (vi1 * r / m), vit = vi1*r - q*m, and Ut=Ut+q*Ui */ for (ui_i = 0; ui_i < ui_t; ui_i++) { mpz_mul (tmp1, V[ui_i][0], r); /* tmp1=vi1*r */ zdiv_round (q, tmp1, m); /* q=round(vi1*r/m) */ mpz_mul (tmp2, q, m); /* tmp2=q*m */ mpz_sub (V[ui_i][ui_t], tmp1, tmp2); for (ui_j = 0; ui_j <= ui_t; ui_j++) /* U[t] = U[t] + q*U[i] */ { mpz_mul (tmp1, q, U[ui_i][ui_j]); /* tmp=q*uij */ mpz_add (U[ui_t][ui_j], U[ui_t][ui_j], tmp1); /* utj = utj + q*uij */ } } /* s = min (s, zdot (U[t], U[t]) */ vz_dot (tmp1, U[ui_t], U[ui_t], ui_t + 1); if (mpz_cmp (tmp1, s) < 0) mpz_set (s, tmp1); ui_k = ui_t; ui_j = 0; /* WARNING: ui_j no longer a temp. */ /* S5 [Transform.] */ if (g_debug > DEBUG_2) printf ("(t, k, j, q1, q2, ...)\n"); do { if (g_debug > DEBUG_2) printf ("(%u, %u, %u", ui_t + 1, ui_k + 1, ui_j + 1); for (ui_i = 0; ui_i <= ui_t; ui_i++) { if (ui_i != ui_j) { vz_dot (tmp1, V[ui_i], V[ui_j], ui_t + 1); /* tmp1=dot(Vi,Vj). */ mpz_abs (tmp2, tmp1); mpz_mul_ui (tmp2, tmp2, 2); /* tmp2 = 2*abs(dot(Vi,Vj) */ vz_dot (tmp3, V[ui_j], V[ui_j], ui_t + 1); /* tmp3=dot(Vj,Vj). */ if (mpz_cmp (tmp2, tmp3) > 0) { zdiv_round (q, tmp1, tmp3); /* q=round(Vi.Vj/Vj.Vj) */ if (g_debug > DEBUG_2) { printf (", "); mpz_out_str (stdout, 10, q); } for (ui_l = 0; ui_l <= ui_t; ui_l++) { mpz_mul (tmp1, q, V[ui_j][ui_l]); mpz_sub (V[ui_i][ui_l], V[ui_i][ui_l], tmp1); /* Vi=Vi-q*Vj */ mpz_mul (tmp1, q, U[ui_i][ui_l]); mpz_add (U[ui_j][ui_l], U[ui_j][ui_l], tmp1); /* Uj=Uj+q*Ui */ } vz_dot (tmp1, U[ui_j], U[ui_j], ui_t + 1); /* tmp1=dot(Uj,Uj) */ if (mpz_cmp (tmp1, s) < 0) /* s = min(s,dot(Uj,Uj)) */ mpz_set (s, tmp1); ui_k = ui_j; } else if (g_debug > DEBUG_2) printf (", #"); /* 2|Vi.Vj| <= Vj.Vj */ } else if (g_debug > DEBUG_2) printf (", *"); /* i == j */ } if (g_debug > DEBUG_2) printf (")\n"); /* S6 [Advance j.] */ if (ui_j == ui_t) ui_j = 0; else ui_j++; } while (ui_j != ui_k); /* S5 */ /* From Knuth p. 104: "The exhaustive search in steps S8-S10 reduces the value of s only rarely." */ #ifdef DO_SEARCH /* S7 [Prepare for search.] */ /* Find minimum in (x[1], ..., x[t]) satisfying condition x[k]^2 <= f(y[1], ...,y[t]) * dot(V[k],V[k]) */ ui_k = ui_t; if (g_debug > DEBUG_2) { printf ("searching..."); /*for (f = 0; f < ui_t*/ fflush (stdout); } /* Z[i] = floor (sqrt (floor (dot(V[i],V[i]) * s / m^2))); */ mpz_pow_ui (tmp1, m, 2); mpf_set_z (f_tmp1, tmp1); mpf_set_z (f_tmp2, s); mpf_div (f_tmp1, f_tmp2, f_tmp1); /* f_tmp1 = s/m^2 */ for (ui_i = 0; ui_i <= ui_t; ui_i++) { vz_dot (tmp1, V[ui_i], V[ui_i], ui_t + 1); mpf_set_z (f_tmp2, tmp1); mpf_mul (f_tmp2, f_tmp2, f_tmp1); f_floor (f_tmp2, f_tmp2); mpf_sqrt (f_tmp2, f_tmp2); mpz_set_f (Z[ui_i], f_tmp2); } /* S8 [Advance X[k].] */ do { if (g_debug > DEBUG_2) { printf ("X[%u] = ", ui_k); mpz_out_str (stdout, 10, X[ui_k]); printf ("\tZ[%u] = ", ui_k); mpz_out_str (stdout, 10, Z[ui_k]); printf ("\n"); fflush (stdout); } if (mpz_cmp (X[ui_k], Z[ui_k])) { mpz_add_ui (X[ui_k], X[ui_k], 1); for (ui_i = 0; ui_i <= ui_t; ui_i++) mpz_add (Y[ui_i], Y[ui_i], U[ui_k][ui_i]); /* S9 [Advance k.] */ while (++ui_k <= ui_t) { mpz_neg (X[ui_k], Z[ui_k]); mpz_mul_ui (tmp1, Z[ui_k], 2); for (ui_i = 0; ui_i <= ui_t; ui_i++) { mpz_mul (tmp2, tmp1, U[ui_k][ui_i]); mpz_sub (Y[ui_i], Y[ui_i], tmp2); } } vz_dot (tmp1, Y, Y, ui_t + 1); if (mpz_cmp (tmp1, s) < 0) mpz_set (s, tmp1); } } while (--ui_k); #endif /* DO_SEARCH */ mpf_set_z (f_tmp1, s); mpf_sqrt (rop[ui_t - 1], f_tmp1); #ifdef DO_SEARCH if (g_debug > DEBUG_2) printf ("done.\n"); #endif /* DO_SEARCH */ } /* S4 loop */ /* Clear GMP variables. */ mpf_clear (f_tmp1); mpf_clear (f_tmp2); for (ui_i = 0; ui_i < GMP_SPECT_MAXT; ui_i++) { for (ui_j = 0; ui_j < GMP_SPECT_MAXT; ui_j++) { mpz_clear (U[ui_i][ui_j]); mpz_clear (V[ui_i][ui_j]); } mpz_clear (X[ui_i]); mpz_clear (Y[ui_i]); mpz_clear (Z[ui_i]); } mpz_clear (tmp1); mpz_clear (tmp2); mpz_clear (tmp3); mpz_clear (h); mpz_clear (hp); mpz_clear (r); mpz_clear (s); mpz_clear (p); mpz_clear (pp); mpz_clear (q); mpz_clear (u); mpz_clear (v); return; }
extern void _jl_mpz_abs(mpz_t* rop, mpz_t* op1) { mpz_abs(*rop, *op1); }