Exemple #1
0
/*------------------------------------------------------------------------*/
static uint32 
lift_roots(sieve_fb_t *s, curr_poly_t *c, 
		uint64 p, uint32 num_roots)
{
	uint32 i;
	uint32 degree = s->degree;

	uint64_2gmp(p, s->p);
	mpz_mul(s->p2, s->p, s->p);
	mpz_tdiv_r(s->nmodp2, c->trans_N, s->p2);
	mpz_sub(s->tmp1, c->trans_m0, c->mp_sieve_size);
	mpz_tdiv_r(s->m0, s->tmp1, s->p2);

	for (i = 0; i < num_roots; i++) {

		mpz_powm_ui(s->tmp1, s->roots[i], (mp_limb_t)degree, s->p2);
		mpz_sub(s->tmp1, s->nmodp2, s->tmp1);
		if (mpz_cmp_ui(s->tmp1, (mp_limb_t)0) < 0)
			mpz_add(s->tmp1, s->tmp1, s->p2);
		mpz_tdiv_q(s->tmp1, s->tmp1, s->p);

		mpz_powm_ui(s->tmp2, s->roots[i], (mp_limb_t)(degree-1), s->p);
		mpz_mul_ui(s->tmp2, s->tmp2, (mp_limb_t)degree);
		mpz_invert(s->tmp2, s->tmp2, s->p);

		mpz_mul(s->tmp1, s->tmp1, s->tmp2);
		mpz_tdiv_r(s->tmp1, s->tmp1, s->p);
		mpz_addmul(s->roots[i], s->tmp1, s->p);
		mpz_sub(s->roots[i], s->roots[i], s->m0);
		if (mpz_cmp_ui(s->roots[i], (mp_limb_t)0) < 0)
			mpz_add(s->roots[i], s->roots[i], s->p2);
	}

	return num_roots;
}
Exemple #2
0
int is_residue_test(){
	printf("\n\nTesting the is_residue function\n");
	if(debug)printf("testing is residue for a residue\n");
	unsigned int test_prime = 7;
	unsigned int test_rand = 2384832;
	mpz_t p;
	mpz_init_set_ui(p,test_prime);
	if(debug){
		printf("\ninitial p:");
		mpz_out_str(stdout,10,p);
		printf("\n");
	}
	

	mpz_t p2;
	mpz_init_set_ui(p2,test_rand);
	mpz_mul(p2,p2,p2);
	if(debug){
		printf("\ninitial p2:");
		mpz_out_str(stdout,10,p2);
		printf("\n");
	}
	
	mpz_tdiv_r(p2,p2,p);
	if(debug){
		printf("initial p2^2 (mod p):");
		mpz_out_str(stdout,10,p2);
		printf("\n");
	}
	int result1 = is_residue_modp(p2,p);
	if(debug)printf("is_residue returns %d for the residue\n", result1);

	unsigned int test_prime2 = 19;
	unsigned int test_rand2 = 348909;
	mpz_t q;
	mpz_init_set_ui(q,test_prime2);
	mpz_t q2; 
	mpz_init_set_ui(q2,test_rand2);
	mpz_mul(q2, q2, p);
	mpz_tdiv_r(q2,q2,q);
	int result2 = is_residue_modp(q2,q);
	if(debug)printf("is_residue returns %d for the nonresidue\n", result2);

	int res = !result1||result2;
	if(!res) printf("is_residue PASSED!\n");
	else printf("is_residue FAILED!\n");

	return res; //if 1 is false or 2 is true then we fail
}
Exemple #3
0
void
ovm_q_rem(oregister_t *l, oregister_t *r)
{
    switch (r->t) {
	case t_void:
	     ovm_raise(except_floating_point_error);
	case t_word:
	    if (r->v.w == 0)
		ovm_raise(except_floating_point_error);
	    if (r->v.w > 0)
		mpz_mul_ui(ozr(r), ozs(l), r->v.w);
	    else {
		mpz_set_si(ozr(r), r->v.w);
		mpz_mul(ozr(r), ozs(l), ozr(r));
	    }
	    mpz_tdiv_r(ozr(l), ozr(l), ozr(r));
	    mpq_canonicalize(oqr(l));
	    check_mpq(l);
	    break;
	case t_float:
	    l->t = t_float;
	    l->v.d = fmod(mpq_get_d(oqr(l)), r->v.d);
	    break;
	case t_mpz:
	    mpz_mul(ozr(r), ozs(l), ozr(r));
	    mpz_tdiv_r(ozr(l), ozr(l), ozr(r));
	    check_mpq(l);
	    break;
	case t_rat:
	    mpq_set_si(oqr(r), rat_num(r->v.r), rat_den(r->v.r));
	case t_mpq:
	    mpq_div(oqr(l), oqr(l), oqr(r));
	    mpz_tdiv_r(ozr(l), ozr(l), ozs(l));
	    mpz_mul(ozs(l), ozs(l), ozs(r));
	    mpq_canonicalize(oqr(l));
	    if (mpq_sgn(oqr(r)) < 0)
		mpq_neg(oqr(l), oqr(l));
	    check_mpq(l);
	    break;
	case t_mpr:
	    l->t = t_mpr;
	    mpfr_set_q(orr(l), oqr(l), thr_rnd);
	    mpfr_fmod(orr(l), orr(l), orr(r), thr_rnd);
	    break;
	 default:
	     ovm_raise(except_not_a_real_number);
    }
}
double PrimeTester::EulerLagrangeLifchitzTest(const Bn& primePrev, bool bSophieGermain) {
	((m_tmpNext = primePrev) <<= 1) += bSophieGermain ? 1 : -1;
	unsigned mod = m_tmpNext.get_ui() % 8;
	if (bSophieGermain) {
		mpz_powm(m_tmp_R.get_mpz_t(), BN_2.get_mpz_t(), primePrev.get_mpz_t(), m_tmpNext.get_mpz_t());
	} else {
		mpz_sub_ui(m_tmp_N_Minus1.get_mpz_t(), primePrev.get_mpz_t(), 1);
		mpz_powm(m_tmp_R.get_mpz_t(), BN_2.get_mpz_t(), m_tmp_N_Minus1.get_mpz_t(), m_tmpNext.get_mpz_t());
	}
	if (mod == (bSophieGermain ? 7 : 1)) {
		if (m_tmp_R==1)
			return 1;
	} else if (mod == (bSophieGermain ? 3 : 5)) {
		mpz_add_ui(m_tmp_T.get_mpz_t(), m_tmp_R.get_mpz_t(), 1);
		if (m_tmp_T == m_tmpNext)
			return 1;
	}

	mpz_mul(m_tmp_T.get_mpz_t(), m_tmp_R.get_mpz_t(), m_tmp_R.get_mpz_t());
	mpz_tdiv_r(m_tmp_R.get_mpz_t(), m_tmp_T.get_mpz_t(), m_tmpNext.get_mpz_t()); // derive Fermat test remainder

	m_tmp_T = (m_tmpNext - m_tmp_R) << 24;	
	mpz_tdiv_q(m_tmp_T.get_mpz_t(), m_tmp_T.get_mpz_t(), m_tmpNext.get_mpz_t());
	int64_t len = m_tmp_T.get_ui();
//	if (!(((n - r) << FRACTIONAL_BITS) / n).AsInt64(len) || len >= (1<<FRACTIONAL_BITS))
//		Throw(E_FAIL);
	return double(len) / (1 << FRACTIONAL_BITS);
}
Exemple #5
0
void
mpz_fdiv_r (mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor)
{
  mp_size_t divisor_size = SIZ (divisor);
  mpz_t temp_divisor;		/* N.B.: lives until function returns! */
  TMP_DECL;

  TMP_MARK;

  /* We need the original value of the divisor after the remainder has been
     preliminary calculated.  We have to copy it to temporary space if it's
     the same variable as REM.  */
  if (rem == divisor)
    {
      MPZ_TMP_INIT (temp_divisor, ABS (divisor_size));
      mpz_set (temp_divisor, divisor);
      divisor = temp_divisor;
    }

  mpz_tdiv_r (rem, dividend, divisor);

  if ((divisor_size ^ SIZ (dividend)) < 0 && SIZ (rem) != 0)
    mpz_add (rem, rem, divisor);

  TMP_FREE;
}
Exemple #6
0
/* functions
*/
  u3_noun
  u3qa_mod(u3_atom a,
           u3_atom b)
  {
#if 0
    if ( b == 3 && a == 2684227708 ) {
      printf("dword at 0x27ff84ff8 is %" PRIu64 "\r\n", *(c3_d *)0x27ff84ff8);
      *(c3_d *)0x27ff84ff8 = 25;
      printf("see, we modified it\r\n");
    }
#endif
    if ( 0 == b ) {
      return u3m_bail(c3__exit);
    } else {
      mpz_t a_mp, b_mp;

      u3r_mp(a_mp, a);
      u3r_mp(b_mp, b);

      mpz_tdiv_r(a_mp, a_mp, b_mp);
      mpz_clear(b_mp);

      return u3i_mp(a_mp);
    }
  }
Exemple #7
0
void
mpz_mod (mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor)
{
  mp_size_t divisor_size = divisor->_mp_size;
  mpz_t temp_divisor;		/* N.B.: lives until function returns! */
  TMP_DECL (marker);

  TMP_MARK (marker);

  /* We need the original value of the divisor after the remainder has been
     preliminary calculated.  We have to copy it to temporary space if it's
     the same variable as REM.  */
  if (rem == divisor)
    {
      MPZ_TMP_INIT (temp_divisor, ABS (divisor_size));
      mpz_set (temp_divisor, divisor);
      divisor = temp_divisor;
    }

  mpz_tdiv_r (rem, dividend, divisor);

  if (rem->_mp_size != 0)
    {
      if (dividend->_mp_size < 0)
	{
	  if (divisor->_mp_size < 0)
	    mpz_sub (rem, rem, divisor);
	  else
	    mpz_add (rem, rem, divisor);
	}
    }

  TMP_FREE (marker);
}
void qsieve_muladddiv(mpz_t x, mpz_t y, mpz_t z, mpz_t w, mpz_t q, mpz_t r)
{
    mpz_mul(TB, x, y);
    if(x != z && y != z) mpz_add(TB, TB, z);
    if(q != r) mpz_tdiv_r(r, TB, w);
    if(w != q) qsieve_divide(TB, w, q);
}
void qsieve_divide(mpz_t x, mpz_t y, mpz_t z)
{
    if(x != z) mpz_tdiv_r(TD, x, y);
    if(y != z) mpz_tdiv_q(TC, x, y);
    if(x != z) if(TD!=x) mpz_set(x, TD);
    if(y != z) if(TC!=z) mpz_set(z, TC);
}
static PyObject *
Pygmpy_t_mod(PyObject *self, PyObject *args)
{
    PyObject *x, *y;
    PympzObject *r, *tempx, *tempy;

    if(PyTuple_GET_SIZE(args) != 2) {
        TYPE_ERROR("t_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("t_mod() division by 0");
            Py_DECREF((PyObject*)r);
            return NULL;
        }
        mpz_tdiv_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("t_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("t_mod() division by 0");
            Py_DECREF((PyObject*)tempx);
            Py_DECREF((PyObject*)tempy);
            Py_DECREF((PyObject*)r);
            return NULL;
        }
        mpz_tdiv_r(r->z, tempx->z, tempy->z);
        Py_DECREF((PyObject*)tempx);
        Py_DECREF((PyObject*)tempy);
    }
    return (PyObject*)r;
}
Exemple #11
0
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;
}
Exemple #12
0
static Py_hash_t
Pympq_hash(PympqObject *self)
{
#ifdef _PyHASH_MODULUS
    Py_hash_t hash = 0;
    mpz_t temp, temp1, mask;

    if (self->hash_cache != -1)
        return self->hash_cache;

    mpz_inoc(temp);
    mpz_inoc(temp1);
    mpz_inoc(mask);
    mpz_set_si(mask, 1);
    mpz_mul_2exp(mask, mask, _PyHASH_BITS);
    mpz_sub_ui(mask, mask, 1);

    if (!mpz_invert(temp, mpq_denref(self->q), mask)) {
        mpz_cloc(temp);
        mpz_cloc(temp1);
        mpz_cloc(mask);
        hash = _PyHASH_INF;
        if (mpz_sgn(mpq_numref(self->q))<0)
            hash = -hash;
        self->hash_cache = hash;
        return hash;
    }
    mpz_set(temp1, mask);
    mpz_sub_ui(temp1, temp1, 2);
    mpz_powm(temp, mpq_denref(self->q), temp1, mask);

    mpz_tdiv_r(temp1, mpq_numref(self->q), mask);
    mpz_mul(temp, temp, temp1);
    hash = (Py_hash_t)mpn_mod_1(temp->_mp_d, mpz_size(temp), _PyHASH_MODULUS);

    if (mpz_sgn(mpq_numref(self->q))<0)
        hash = -hash;
    if (hash==-1) hash = -2;
    mpz_cloc(temp);
    mpz_cloc(temp1);
    mpz_cloc(mask);
    self->hash_cache = hash;
    return hash;
#else
    PyObject *temp;

    if (self->hash_cache != -1)
        return self->hash_cache;

    if (!(temp = Pympq_To_PyFloat(self))) {
        SYSTEM_ERROR("Could not convert 'mpq' to float.");
        return -1;
    }
    self->hash_cache = PyObject_Hash(temp);
    Py_DECREF(temp);
    return self->hash_cache;
#endif
}
void mpz_correct_mod(mpz_t result, mpz_t n, mpz_t d) {
  mpz_tdiv_r(result, n, d);
  mpz_t temp;
  mpz_init(temp);
  mpz_fdiv_q_2exp(temp, d, 1);
  if (mpz_cmp(result, temp) > 0) {
	mpz_sub(result, d, result);
  }
  mpz_clear(temp);
}
int checkpoly_siqs(siqs_poly *poly, mpz_t n)
{
	//check that b^2 == N mod a
	//and that c == (b*b - n)/a
	mpz_t t1,t2,t3,t4;

	mpz_init(t1);
	mpz_init(t2);
	mpz_init(t3);
	mpz_init(t4);

	mpz_set(t1, n);
	mpz_tdiv_r(t3, t1, poly->mpz_poly_a); //zDiv(&t1,&poly->poly_a,&t2,&t3);

	mpz_mul(t2, poly->mpz_poly_b, poly->mpz_poly_b); //zMul(&poly->poly_b,&poly->poly_b,&t2);
	mpz_tdiv_r(t4, t2, poly->mpz_poly_a); //zDiv(&t2,&poly->poly_a,&t1,&t4);

	if (mpz_cmp(t3,t4) != 0)
	{
		printf("\nError in checkpoly: %s^2 !== N mod %s\n", 
			mpz_conv2str(&gstr1.s, 10, poly->mpz_poly_b),
			mpz_conv2str(&gstr2.s, 10, poly->mpz_poly_a));
		if (mpz_sgn(poly->mpz_poly_b) < 0)
			printf("b is negative\n");
	}

	if (mpz_kronecker(n, poly->mpz_poly_a) != 1)
		printf("\nError in checkpoly: (a|N) != 1\n");

	mpz_mul(t2, poly->mpz_poly_b, poly->mpz_poly_b); //zMul(&poly->poly_b,&poly->poly_b,&t2);
	mpz_sub(t2, t2, n);
	mpz_tdiv_q(t4, t2, poly->mpz_poly_a); //zDiv(&t2,&poly->poly_a,&t1,&t4);

	if (mpz_cmp(t4,poly->mpz_poly_c) != 0)
		printf("\nError in checkpoly: c != (b^2 - n)/a\n");
	
	mpz_clear(t1);
	mpz_clear(t2);
	mpz_clear(t3);
	mpz_clear(t4);
	return 0;
}
Exemple #15
0
obj bignum_remainder( obj a, obj b )
{
    mpz_t r, a1, b1;

    OBJ_TO_MPZ(a1, a);
    OBJ_TO_MPZ(b1, b);

    mpz_init(r);
    mpz_tdiv_r(r, a1, b1);
    return bignum_compact(r);
}
Exemple #16
0
void
mpz_divexact (mpz_ptr quot, mpz_srcptr num, mpz_srcptr den)
{
  mp_ptr qp;
  mp_size_t qn;
  mp_srcptr np, dp;
  mp_size_t nn, dn;
  TMP_DECL;

#if WANT_ASSERT
  {
    mpz_t  rem;
    mpz_init (rem);
    mpz_tdiv_r (rem, num, den);
    ASSERT (SIZ(rem) == 0);
    mpz_clear (rem);
  }
#endif

  nn = ABSIZ (num);
  dn = ABSIZ (den);

  if (nn < dn)
    {
      /* This special case avoids segfaults below when the function is
	 incorrectly called with |N| < |D|, N != 0.  It also handles the
	 well-defined case N = 0.  */
      SIZ(quot) = 0;
      return;
    }

  qn = nn - dn + 1;

  TMP_MARK;

  if (quot == num || quot == den)
    qp = TMP_ALLOC_LIMBS (qn);
  else
    qp = MPZ_REALLOC (quot, qn);

  np = PTR(num);
  dp = PTR(den);

  mpn_divexact (qp, np, nn, dp, dn);
  MPN_NORMALIZE (qp, qn);

  if (qp != PTR(quot))
    MPN_COPY (MPZ_REALLOC (quot, qn), qp, qn);

  SIZ(quot) = (SIZ(num) ^ SIZ(den)) >= 0 ? qn : -qn;

  TMP_FREE;
}
/*------------------------------------------------------------------------*/
static void
lift_roots(sieve_fb_t *s, poly_coeff_t *c, uint32 p, uint32 num_roots)
{
	/* we have num_roots arithmetic progressions mod p;
	   convert the progressions to be mod p^2, using
	   Hensel lifting, and then move the origin of the
	   result trans_m0 units to the left. */

	uint32 i;
	unsigned long degree = s->degree;

	mpz_set_ui(s->p, (unsigned long)p);
	mpz_mul(s->pp, s->p, s->p);
	mpz_tdiv_r(s->nmodpp, c->trans_N, s->pp);
	mpz_tdiv_r(s->tmp3, c->trans_m0, s->pp);

	for (i = 0; i < num_roots; i++) {

		uint64_2gmp(s->roots[i], s->gmp_root);

		mpz_powm_ui(s->tmp1, s->gmp_root, degree, s->pp);
		mpz_sub(s->tmp1, s->nmodpp, s->tmp1);
		if (mpz_cmp_ui(s->tmp1, (mp_limb_t)0) < 0)
			mpz_add(s->tmp1, s->tmp1, s->pp);
		mpz_tdiv_q(s->tmp1, s->tmp1, s->p);

		mpz_powm_ui(s->tmp2, s->gmp_root, degree-1, s->p);
		mpz_mul_ui(s->tmp2, s->tmp2, degree);
		mpz_invert(s->tmp2, s->tmp2, s->p);

		mpz_mul(s->tmp1, s->tmp1, s->tmp2);
		mpz_tdiv_r(s->tmp1, s->tmp1, s->p);
		mpz_addmul(s->gmp_root, s->tmp1, s->p);
		mpz_sub(s->gmp_root, s->gmp_root, s->tmp3);
		if (mpz_cmp_ui(s->gmp_root, (unsigned long)0) < 0)
			mpz_add(s->gmp_root, s->gmp_root, s->pp);

		s->roots[i] = gmp2uint64(s->gmp_root);
	}
}
Exemple #18
0
int getRecurringDigits(int n){
	int count = 1;
	mpz_set_si(num, n);		
	mpz_set_si(powTen,10);
	while(1){
	    mpz_sub_ui(powTenMinusOne, powTen, 1UL);
		mpz_tdiv_r(rem, powTenMinusOne, num);
		if(mpz_cmp_ui(rem,0)==0) { break; }
		mpz_mul_ui(powTen,powTen,10);
		count++;
	}
	return count; 
}
Exemple #19
0
static bool EulerLagrangeLifchitzPrimalityTestFast(const mpz_class& n,
                                                   bool fSophieGermain,
                                                   unsigned int& nLength,
                                                   CPrimalityTestParams& testParams)
{
  static const mpz_class mpzTwo = 2;  
  
  // Faster GMP version
  mpz_t& mpzE = testParams.mpzE;
  mpz_t& mpzR = testParams.mpzR;
  mpz_t& mpzRplusOne = testParams.mpzRplusOne;
  
  mpz_sub_ui(mpzE, n.get_mpz_t(), 1);
  mpz_tdiv_q_2exp(mpzE, mpzE, 1);
  mpz_powm(mpzR, mpzTwo.get_mpz_t(), mpzE, n.get_mpz_t());
  unsigned int nMod8 = mpz_get_ui(n.get_mpz_t()) % 8;
  bool fPassedTest = false;
  if (fSophieGermain && (nMod8 == 7)) // Euler & Lagrange
    fPassedTest = !mpz_cmp_ui(mpzR, 1);
  else if (fSophieGermain && (nMod8 == 3)) // Lifchitz
  {
    mpz_add_ui(mpzRplusOne, mpzR, 1);
    fPassedTest = !mpz_cmp(mpzRplusOne, n.get_mpz_t());
  }
  else if ((!fSophieGermain) && (nMod8 == 5)) // Lifchitz
  {
    mpz_add_ui(mpzRplusOne, mpzR, 1);
    fPassedTest = !mpz_cmp(mpzRplusOne, n.get_mpz_t());
  }
  else if ((!fSophieGermain) && (nMod8 == 1)) // LifChitz
    fPassedTest = !mpz_cmp_ui(mpzR, 1);
  
  if (fPassedTest)
  {
    return true;
  }
  
  // Failed test, calculate fractional length
  mpz_mul(mpzE, mpzR, mpzR);
  mpz_tdiv_r(mpzR, mpzE, n.get_mpz_t()); // derive Fermat test remainder
  
  mpz_sub(mpzE, n.get_mpz_t(), mpzR);
  mpz_mul_2exp(mpzR, mpzE, DifficultyFractionalBits);
  mpz_tdiv_q(mpzE, mpzR, n.get_mpz_t());
  unsigned int nFractionalLength = mpz_get_ui(mpzE);
  
  nLength = (nLength & DifficultyChainLengthMask) | nFractionalLength;
  return false;
}
/*------------------------------------------------------------------*/
static void compute_remainder_tree(uint32 first, uint32 last,
				relation_batch_t *rb,
				mpz_t numerator) {

	/* recursively compute numerator % (each relation in 
	   rb->relations) */

	uint32 mid = (first + last) / 2;
	mpz_t relation_prod, remainder;

	/* recursion base case: numerator already fits in
	   an mp_t, so manually compute the remainder and
	   postprocess each relation */

	if (mpz_size(numerator) * GMP_LIMB_BITS/32 <= MAX_MP_WORDS) {
		if (mpz_sgn(numerator) > 0) {
			mp_t num;
			gmp2mp(numerator, &num);
			while (first <= last)
				check_relation(rb, first++, &num);
		}
		return;
	}

	/* multiply together the unfactored parts of all the
	   relations from first to last */

	mpz_init(relation_prod);
	mpz_init(remainder);
	multiply_relations(first, last, rb, relation_prod);

	/* use the remainder to deal with the left and right
	   halves of the relation list */

	if (mpz_cmp(numerator, relation_prod) < 0) {
		mpz_clear(relation_prod);
		compute_remainder_tree(first, mid, rb, numerator);
		compute_remainder_tree(mid + 1, last, rb, numerator);
	}
	else {
		mpz_tdiv_r(remainder, numerator, relation_prod);
		mpz_clear(relation_prod);
		compute_remainder_tree(first, mid, rb, remainder);
		compute_remainder_tree(mid + 1, last, rb, remainder);
	}
	mpz_clear(remainder);
}
Exemple #21
0
/* functions
*/
  u2_weak                                                         //  transfer
  j2_mbc(Pt1, mod)(u2_wire wir_r, 
                   u2_atom a,                                     //  retain
                   u2_atom b)                                     //  retain
  {
    if ( _0 == b ) {
      return u2_none;
    } else {
      mpz_t a_mp, b_mp;

      u2_mp(a_mp, a);
      u2_mp(b_mp, b);

      mpz_tdiv_r(a_mp, a_mp, b_mp);
      mpz_clear(b_mp);

      return u2_rl_mp(wir_r, a_mp);
    }
  }
Exemple #22
0
/* u4_op_mod():
**
**   Produce (b % a).
*/
u4_atom
u4_op_mod(u4_lane lane,
          u4_atom a,
          u4_atom b)
{
  if ( u4_n_zero(a) ) {
    return u4_bull;
  }
  else {
    mpz_t mp_a, mp_b;

    u4_a_gmp(a, mp_a);
    u4_a_gmp(b, mp_b);

    mpz_tdiv_r(mp_b, mp_b, mp_a);
    mpz_clear(mp_a);

    return u4_k_atom_gmp(lane, mp_b);
  }
}
Exemple #23
0
/* u3_zx_mod_c():
*/
u3_fox
u3_zx_mod_c(u3_z   z,
            u3_fox a,
            u3_fox b)
{
  if ( 0 == b ) {
    return u3_zc_tank(z, c3__exit);
  }
  else {
    mpz_t mp_a, mp_b;

    u3_lr_mp(z, mp_a, a);
    u3_lr_mp(z, mp_b, b);

    mpz_tdiv_r(mp_a, mp_a, mp_b);
    mpz_clear(mp_b);

    return u3_zc_mp(z, mp_a);
  }
}
Exemple #24
0
/*-------------------------------------------------------------------------*/
static uint32
check_poly(curr_poly_t *c, mpz_t *coeffs, mpz_t lin0, 
		mpz_t gmp_N, uint32 degree) {

	uint32 i;

	mpz_set(c->gmp_help1, coeffs[degree]);
	mpz_set(c->gmp_help2, c->gmp_p);
	for (i = degree; i; i--) {
		mpz_mul(c->gmp_help1, c->gmp_help1, lin0);
		mpz_neg(c->gmp_help1, c->gmp_help1);
		mpz_addmul(c->gmp_help1, coeffs[i-1], c->gmp_help2);
		mpz_mul(c->gmp_help2, c->gmp_help2, c->gmp_p);
	}
	mpz_tdiv_r(c->gmp_help1, c->gmp_help1, gmp_N);
	if (mpz_cmp_ui(c->gmp_help1, (mp_limb_t)0) != 0) {
		printf("error: corrupt polynomial expand\n");
		return 0;
	}
	return 1;
}
void
sieve_xy_run_deg6(root_sieve_t *rs)
{
	uint32 i;

	sieve_xyz_t *xyz = &rs->xyzdata;
	int64 z_base = xyz->z_base;

	sieve_xy_t *xy = &rs->xydata;
	sieve_prime_t *lattice_primes = xy->lattice_primes;
	uint32 num_lattice_primes;
	msieve_obj *obj = rs->data->obj;

	double direction[3] = {0, 1, 0};
	double line_min, line_max;
	uint16 cutoff_score;
	xydata_t xydata[MAX_CRT_FACTORS];
	plane_heap_t plane_heap;

	uint64 inv_xy;
	uint64 inv_xyz;

	compute_line_size(rs->max_norm, &rs->apoly,
			rs->dbl_p, rs->dbl_d, direction,
			-10000, 10000, &line_min, &line_max);
	if (line_min > line_max)
		return;

	num_lattice_primes = xy->num_lattice_primes = 
				find_lattice_primes(rs->primes, 
					rs->num_primes, xyz->lattice_size, 
					lattice_primes, &xy->lattice_size,
					line_max - line_min);

	inv_xy = mp_modinv_2(xyz->lattice_size, xy->lattice_size);
	inv_xyz = mp_modinv_2(xy->lattice_size, xyz->lattice_size);
	uint64_2gmp(xy->lattice_size, xy->tmp1);
	uint64_2gmp(inv_xy, xy->tmp2);
	uint64_2gmp(xyz->lattice_size, xy->tmp3);
	uint64_2gmp(inv_xyz, xy->tmp4);
	mpz_mul(xy->mp_lattice_size, xy->tmp1, xy->tmp3);
	mpz_mul(xy->crt0, xy->tmp2, xy->tmp3);
	mpz_mul(xy->crt1, xy->tmp1, xy->tmp4);
	xy->dbl_lattice_size = mpz_get_d(xy->mp_lattice_size);

	xydata_alloc(lattice_primes, num_lattice_primes, 
			xyz->lattice_size, xydata);

	plane_heap.num_entries = 0;

	for (i = 0; i < xyz->num_lattices; i++) {

		lattice_t *curr_lattice_xyz = xyz->lattices + i;

		xydata_init(xydata, num_lattice_primes,
				curr_lattice_xyz, z_base);

		find_hits(rs, xydata, num_lattice_primes, 
				i, &plane_heap);
	}

	xydata_free(xydata, num_lattice_primes);

	qsort(plane_heap.entries, plane_heap.num_entries,
			sizeof(plane_t), compare_planes);
	cutoff_score = 0.9 * plane_heap.entries[0].plane.score;

	for (i = 0; i < plane_heap.num_entries; i++) {

		plane_t *curr_plane = plane_heap.entries + i;
		lattice_t *lattice_xy = &curr_plane->plane;
		lattice_t *lattice_xyz = xyz->lattices + 
					curr_plane->which_lattice_xyz;

		if (lattice_xy->score < cutoff_score)
			break;

		line_min = xyz->y_line_min[curr_plane->which_z_block];
		line_max = xyz->y_line_max[curr_plane->which_z_block];
		z_base = xyz->z_base + curr_plane->which_z_block *
					xyz->lattice_size;

		xy->apoly = rs->apoly;
		xy->apoly.coeff[3] += z_base * rs->dbl_p;
		xy->apoly.coeff[2] -= z_base * rs->dbl_d;

		mpz_set_d(xy->tmp1, line_min);
		mpz_tdiv_q(xy->y_base, xy->tmp1, xy->mp_lattice_size);
		mpz_mul(xy->y_base, xy->y_base, xy->mp_lattice_size);
		xy->y_blocks = (line_max - line_min) / xy->dbl_lattice_size;

		uint64_2gmp(lattice_xy->x, xy->tmp1);
		uint64_2gmp(lattice_xyz->x, xy->tmp2);
		mpz_mul(xy->resclass_x, xy->tmp1, xy->crt0);
		mpz_addmul(xy->resclass_x, xy->tmp2, xy->crt1);

		uint64_2gmp(lattice_xy->y, xy->tmp1);
		uint64_2gmp(lattice_xyz->y, xy->tmp2);
		mpz_mul(xy->resclass_y, xy->tmp1, xy->crt0);
		mpz_addmul(xy->resclass_y, xy->tmp2, xy->crt1);

		mpz_tdiv_r(xy->resclass_x, xy->resclass_x, 
				xy->mp_lattice_size);
		mpz_tdiv_r(xy->resclass_y, xy->resclass_y, 
				xy->mp_lattice_size);

		xy->curr_score = lattice_xyz->score + lattice_xy->score;
		rs->curr_z = z_base + lattice_xyz->z; 

		sieve_x_run_deg6(rs);

		if (obj->flags & MSIEVE_FLAG_STOP_SIEVING)
			break;
	}
}
Exemple #26
0
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);
}
Exemple #27
0
/*------------------------------------------------------------------------*/
static uint32 
get_composite_roots(sieve_fb_t *s, curr_poly_t *c,
			uint32 which_poly, uint64 p, 
			uint32 num_factors, 
			uint32 *factors,
			uint32 num_roots_min,
			uint32 num_roots_max)
{
	uint32 i, j, k, i0, i1, i2, i3, i4, i5, i6;
	uint32 crt_p[MAX_P_FACTORS];
	uint32 num_roots[MAX_P_FACTORS];
	uint64 prod[MAX_P_FACTORS];
	uint32 roots[MAX_P_FACTORS][MAX_POLYSELECT_DEGREE];
	aprog_t *aprogs = s->aprog_data.aprogs;
	uint32 degree = s->degree;

	for (i = 0, j = 1; i < num_factors; i++) {
		aprog_t *a;

		if (i > 0 && factors[i] == factors[i-1])
			continue;

		a = aprogs + factors[i];
		if (a->num_roots[which_poly] == 0)
			return 0;

		j *= a->num_roots[which_poly];
	}
	if (j < num_roots_min || j > num_roots_max)
		return INVALID_NUM_ROOTS;

	for (i = j = 0; j < MAX_P_FACTORS && i < num_factors; i++, j++) {
		aprog_t *a = aprogs + factors[i];
		uint32 power_limit;

		num_roots[j] = a->num_roots[which_poly];
		crt_p[j] = a->p;
		power_limit = (uint32)(-1) / a->p;
		for (k = 0; k < num_roots[j]; k++) {
			roots[j][k] = a->roots[which_poly][k];
		}

		while (i < num_factors - 1 && factors[i] == factors[i+1]) {

			uint32 nmodp, new_power;

			if (crt_p[j] > power_limit)
				return 0;

			new_power = crt_p[j] * a->p;
			nmodp = mpz_tdiv_ui(c->trans_N, (mp_limb_t)new_power);

			for (k = 0; k < num_roots[j]; k++) {
				roots[j][k] = lift_root_32(nmodp, roots[j][k],
							crt_p[j], a->p, 
							degree);
			}
			crt_p[j] = new_power;
			i++;
		}
	}
	if (i < num_factors)
		return 0;
	num_factors = j;

	if (num_factors == 1) {
		for (i = 0; i < num_roots[0]; i++)
			mpz_set_ui(s->roots[i], (mp_limb_t)roots[0][i]);

		return num_roots[0];
	}

	for (i = 0; i < num_factors; i++) {
		prod[i] = p / crt_p[i];
		prod[i] = prod[i] * mp_modinv_1((uint32)(prod[i] %
						crt_p[i]), crt_p[i]);
	}
	mpz_set_ui(s->accum[i], (mp_limb_t)0);
	uint64_2gmp(p, s->p);

	i0 = i1 = i2 = i3 = i4 = i5 = i6 = i = 0;
	switch (num_factors) {
	case 7:
		for (i6 = num_roots[6] - 1; (int32)i6 >= 0; i6--) {
			uint64_2gmp(prod[6], s->accum[6]);
			mpz_mul_ui(s->accum[6], s->accum[6], 
						(mp_limb_t)roots[6][i6]);
			mpz_add(s->accum[6], s->accum[6], s->accum[7]);
	case 6:
		for (i5 = num_roots[5] - 1; (int32)i5 >= 0; i5--) {
			uint64_2gmp(prod[5], s->accum[5]);
			mpz_mul_ui(s->accum[5], s->accum[5], 
						(mp_limb_t)roots[5][i5]);
			mpz_add(s->accum[5], s->accum[5], s->accum[6]);
	case 5:
		for (i4 = num_roots[4] - 1; (int32)i4 >= 0; i4--) {
			uint64_2gmp(prod[4], s->accum[4]);
			mpz_mul_ui(s->accum[4], s->accum[4], 
						(mp_limb_t)roots[4][i4]);
			mpz_add(s->accum[4], s->accum[4], s->accum[5]);
	case 4:
		for (i3 = num_roots[3] - 1; (int32)i3 >= 0; i3--) {
			uint64_2gmp(prod[3], s->accum[3]);
			mpz_mul_ui(s->accum[3], s->accum[3], 
						(mp_limb_t)roots[3][i3]);
			mpz_add(s->accum[3], s->accum[3], s->accum[4]);
	case 3:
		for (i2 = num_roots[2] - 1; (int32)i2 >= 0; i2--) {
			uint64_2gmp(prod[2], s->accum[2]);
			mpz_mul_ui(s->accum[2], s->accum[2], 
						(mp_limb_t)roots[2][i2]);
			mpz_add(s->accum[2], s->accum[2], s->accum[3]);
	case 2:
		for (i1 = num_roots[1] - 1; (int32)i1 >= 0; i1--) {
			uint64_2gmp(prod[1], s->accum[1]);
			mpz_mul_ui(s->accum[1], s->accum[1], 
						(mp_limb_t)roots[1][i1]);
			mpz_add(s->accum[1], s->accum[1], s->accum[2]);

		for (i0 = num_roots[0] - 1; (int32)i0 >= 0; i0--) {
			uint64_2gmp(prod[0], s->accum[0]);
			mpz_mul_ui(s->accum[0], s->accum[0], 
						(mp_limb_t)roots[0][i0]);
			mpz_add(s->accum[0], s->accum[0], s->accum[1]);

			mpz_tdiv_r(s->accum[0], s->accum[0], s->p);
			mpz_set(s->roots[i++], s->accum[0]);
		}}}}}}}
	}

	return i;
}
Exemple #28
0
int mbrent(fact_obj_t *fobj)
{
	/*
	run pollard's rho algorithm on n with Brent's modification, 
	returning the first factor found in f, or else 0 for failure.
	use f(x) = x^2 + c
	see, for example, bressoud's book.
	use montgomery arithmetic. 
	*/

	mpz_t x,y,q,g,ys,t1,t2,cc;

	uint32 i=0,k,r,m,c;
	int it;
	int imax = fobj->rho_obj.iterations;

	//initialize local arbs
	mpz_init(x);
	mpz_init(y);
	mpz_init(q);
	mpz_init(g);
	mpz_init(ys);
	mpz_init(t1);
	mpz_init(t2);
	mpz_init(cc);

	//starting state of algorithm.  
	r = 1;
	m = 10;
	i = 0;
	it = 0;
	c = fobj->rho_obj.curr_poly;
	mpz_set_ui(cc, fobj->rho_obj.polynomials[c]);
	mpz_set_ui(q, 1);
	mpz_set_ui(y, 0);
	mpz_set_ui(g, 1); 

	do
	{
		mpz_set(x,y);
		for(i=0;i<=r;i++)
		{
			mpz_mul(t1,y,y);		//y = (y*y + c) mod n
			mpz_add_ui(t1, t1, c);
			mpz_tdiv_r(t1, t1, fobj->rho_obj.gmp_n);			
		}

		k=0;
		do
		{
			mpz_set(ys, y);
			for(i=1;i<=MIN(m,r-k);i++)
			{
				mpz_mul(t1,y,y); //y=(y*y + c)%n
				mpz_add_ui(t1, t1, c);
				mpz_tdiv_r(y, t1, fobj->rho_obj.gmp_n);	

				mpz_sub(t1, x, y); //q = q*abs(x-y) mod n
				if (mpz_sgn(t1) < 0)
					mpz_add(t1, t1, fobj->rho_obj.gmp_n);
				mpz_mul(q, t1, q); 
				mpz_tdiv_r(q, q, fobj->rho_obj.gmp_n);	
			}
			mpz_gcd(g, q, fobj->rho_obj.gmp_n);
			k+=m;
			it++;

			if (it>imax)
			{
				mpz_set_ui(fobj->rho_obj.gmp_f, 0);
				goto free;
			}
			if (mpz_sgn(g) < 0)
				mpz_neg(g, g); 
		} while (k<r && (mpz_get_ui(g) == 1));
		r*=2;
	} while (mpz_get_ui(g) == 1);

	if (mpz_cmp(g,fobj->rho_obj.gmp_n) == 0)
	{
		//back track
		it=0;
		do
		{
			mpz_mul(t1, ys, ys); //ys = (ys*ys + c) mod n
			mpz_add_ui(t1, t1, c);
			mpz_tdiv_r(ys, t1, fobj->rho_obj.gmp_n); 

			mpz_sub(t1, ys, x);
			if (mpz_sgn(t1) < 0)
				mpz_add(t1, t1, fobj->rho_obj.gmp_n);
			mpz_gcd(g, t1, fobj->rho_obj.gmp_n);
			it++;
			if (it>imax)
			{
				mpz_set_ui(fobj->rho_obj.gmp_f, 0);
				goto free;
			}
			if (mpz_sgn(g) < 0)
				mpz_neg(g, g); 
		} while ((mpz_size(g) == 1) && (mpz_get_ui(g) == 1));
		if (mpz_cmp(g,fobj->rho_obj.gmp_n) == 0)
		{
			mpz_set_ui(fobj->rho_obj.gmp_f, 0);
			goto free;
		}
		else
		{
			mpz_set(fobj->rho_obj.gmp_f, g);
			goto free;
		}
	}
	else
	{
		mpz_set(fobj->rho_obj.gmp_f, g);
		goto free;
	}

free:
	if (VFLAG >= 0)
		printf("\n");

	mpz_clear(x);
	mpz_clear(y);
	mpz_clear(q);
	mpz_clear(g);
	mpz_clear(ys);
	mpz_clear(t1);
	mpz_clear(t2);
	mpz_clear(cc);
	
	return it;
}
Exemple #29
0
mpz_t* modBigInt(mpz_t x, mpz_t y) {
    mpz_t* answer = EMALLOC(sizeof(mpz_t));
    mpz_tdiv_r(*answer, x, y);
    return answer;
}
Exemple #30
0
static int
pol_expand(curr_poly_t *c, mpz_t gmp_N, mpz_t high_coeff,
		mpz_t gmp_p, mpz_t gmp_d, 
		double coeff_bound, uint32 degree)
{
	uint32 i, j;

	if (mpz_cmp_ui(c->gmp_p, (mp_limb_t)1) == 0)
		mpz_set_ui(c->gmp_help1, (mp_limb_t)1);
	else {
		if (!mpz_invert(c->gmp_help1, gmp_d, gmp_p))
			return 0;
	}

	mpz_set(c->gmp_b[1], c->gmp_help1);
	for (i = 2; i < degree; i++)
		mpz_mul(c->gmp_b[i], c->gmp_b[i-1], c->gmp_help1);

	mpz_set(c->gmp_c[1], gmp_d);
	for (i = 2; i <= degree; i++)
		mpz_mul(c->gmp_c[i], c->gmp_c[i-1], gmp_d);

	mpz_set(c->gmp_a[degree], high_coeff);
	mpz_set(c->gmp_help2, gmp_N);

	for (i = degree - 1; (int32)i >= 0; i--) {

		mpz_mul(c->gmp_help3, c->gmp_a[i+1], c->gmp_c[i+1]);
		mpz_sub(c->gmp_help3, c->gmp_help2, c->gmp_help3);
		mpz_tdiv_q(c->gmp_help2, c->gmp_help3, gmp_p);

		if (i > 0) {
			mpz_tdiv_q(c->gmp_a[i], c->gmp_help2, c->gmp_c[i]);
			mpz_mul(c->gmp_help3, c->gmp_help2, c->gmp_b[i]);
			mpz_sub(c->gmp_help3, c->gmp_help3, c->gmp_a[i]);
			mpz_tdiv_r(c->gmp_help4, c->gmp_help3, gmp_p);

			if (mpz_sgn(c->gmp_help4) < 0)
				mpz_add(c->gmp_help4, c->gmp_help4, gmp_p);

			mpz_add(c->gmp_a[i], c->gmp_a[i], c->gmp_help4);
		}
	}
	mpz_set(c->gmp_a[0], c->gmp_help2);

	mpz_tdiv_q_2exp(c->gmp_help1, gmp_d, (mp_limb_t)1);
	for (i = 0; i < degree; i++) {
		for (j = 0; j < MAX_CORRECT_STEPS &&
			    mpz_cmpabs(c->gmp_a[i], c->gmp_help1) > 0; j++) {

			if (mpz_sgn(c->gmp_a[i]) < 0) {
				mpz_add(c->gmp_a[i], c->gmp_a[i], gmp_d);
				mpz_sub(c->gmp_a[i+1], c->gmp_a[i+1], gmp_p);
			}
			else {
				mpz_sub(c->gmp_a[i], c->gmp_a[i], gmp_d);
				mpz_add(c->gmp_a[i+1], c->gmp_a[i+1], gmp_p);
			}
		}

		if (j == MAX_CORRECT_STEPS)
			return 0;
	}

#if 0
	gmp_printf("%+Zd\n", c->gmp_lina[0]);
	gmp_printf("%+Zd\n", c->gmp_lina[1]);
	for (i = 0; i <= degree; i++)
		gmp_printf("%+Zd\n", c->gmp_a[i]);

	printf("coeff ratio = %.5lf\n",
		fabs(mpz_get_d(c->gmp_a[degree-2])) / coeff_bound);
#endif

	if (check_poly(c, c->gmp_a, 
			c->gmp_lina[0], gmp_N, degree) != 1) {
		return 0;
	}

	if (mpz_cmpabs_d(c->gmp_a[degree - 2], coeff_bound) > 0) {
		return 1;
	}
	return 2;
}