Example #1
0
static PyObject *
GMPy_MPZ_Function_IsOdd(PyObject *self, PyObject *other)
{
    int res;
    MPZ_Object *tempx;

    if (CHECK_MPZANY(other)) {
        res = mpz_odd_p(MPZ(other));
    }
    else {
        if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
            TYPE_ERROR("is_odd() requires 'mpz' argument");
            return NULL;
        }
        else {
            res = mpz_odd_p(tempx->z);
            Py_DECREF((PyObject*)tempx);
        }
    }

    if (res)
        Py_RETURN_TRUE;
    else
        Py_RETURN_FALSE;
}
Example #2
0
/* 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;
}
Example #3
0
/* Calculate r satisfying r*d == 1 mod 2^n. */
void
mpz_invert_2exp (mpz_t r, mpz_t a, unsigned long n)
{
  unsigned long  i;
  mpz_t  inv, prod;

  assert (mpz_odd_p (a));

  mpz_init_set_ui (inv, 1L);
  mpz_init (prod);

  for (i = 1; i < n; i++)
    {
      mpz_mul (prod, inv, a);
      if (mpz_tstbit (prod, i) != 0)
	mpz_setbit (inv, i);
    }

  mpz_mul (prod, inv, a);
  mpz_tdiv_r_2exp (prod, prod, n);
  assert (mpz_cmp_ui (prod, 1L) == 0);

  mpz_set (r, inv);

  mpz_clear (inv);
  mpz_clear (prod);
}
Example #4
0
void mpfr_squaring_int_exp(mpfr_t R, mpfr_t x, mpz_t a)
{
	if(mpz_cmp_ui(a, 0) < 0)
	{
		mpz_t b;
		mpz_init_set(b, a);
		mpz_neg(b, b);
		mpfr_squaring_int_exp(R, x, b);
		mpfr_ui_div(R, 1, R, MPFR_RNDN);
	}
	else
	{
		mpfr_t y;
		mpz_t n;
		mpfr_init_set(y, x, MPFR_RNDN);
		mpfr_set_ui(R, 1, MPFR_RNDN);
		mpz_init_set(n, a);
		while(mpz_cmp_ui(n, 0) > 0)
		{
			if(mpz_odd_p(n))
			{
				mpfr_mul(R, R, y, MPFR_RNDN);
				mpz_sub_ui(n, n, 1);
			}
			mpfr_mul(y, y, y, MPFR_RNDN);
			mpz_div_ui(n, n, 2);
		}
	}
}
Example #5
0
static void zp_halve(element_ptr n, element_ptr a) {
  mpz_ptr z = a->data;
  if (mpz_odd_p(z)) {
    mpz_add(n->data, z, a->field->order);
    mpz_tdiv_q_2exp(n->data, n->data, 1);
  } else {
    mpz_tdiv_q_2exp(n->data, a->data, 1);
  }
}
Example #6
0
void gmp_halve(mpz_ptr value, mpz_ptr order) {
    if (mpz_odd_p(value)) {
        mpz_add(value, value, order);
        mpz_tdiv_q_2exp(value, value, 1);
    } else {
        mpz_tdiv_q_2exp(value, value, 1);
    }

}
Example #7
0
/*
 * \brief                Encrypts/decrypts a message using the RSA algorithm.
 *
 * \param result         a field to populate with the result of your RSA calculation.
 * \param message        the message to perform RSA on. (probably a cert in this case)
 * \param e              the encryption key from the key_file passed in through the
 *                       command-line arguments
 * \param n              the modulus for RSA from the modulus_file passed in through
 *                       the command-line arguments
 *
 * Fill in this function with your proj0 solution or see staff solutions.
 */
static void
perform_rsa(mpz_t result, mpz_t message, mpz_t e, mpz_t n)
{
  int odd_num;

  mpz_set_str(result, "1", 10);
  odd_num = mpz_odd_p(e);
  while (mpz_cmp_ui(e, 0) > 0) {
    if (odd_num) {
      mpz_mul(result, result, message);
      mpz_mod(result, result, n);
      mpz_sub_ui(e, e, 1);
    }
    mpz_mul(message, message, message);
    mpz_mod(message, message, n);
    mpz_div_ui(e, e, 2);
    odd_num = mpz_odd_p(e);
  }
}
Example #8
0
static PyObject *
GMPy_MPZ_Method_IsOdd(PyObject *self, PyObject *other)
{
    int res;

    res = mpz_odd_p(MPZ(self));

    if (res)
        Py_RETURN_TRUE;
    else
        Py_RETURN_FALSE;
}
Example #9
0
static int fp_sgn_odd(element_ptr a) {
	eptr ad = (eptr)a->data;
	if (!ad->flag) return 0;
	else {
		mpz_t z;
		mpz_init(z);
		int res;
		fp_to_mpz(z, a);
		res = mpz_odd_p(z) ? 1 : -1;
		mpz_clear(z);
		return res;
	}
}
Example #10
0
static PyObject *
GMPy_MPZ_Method_Round(PyObject *self, PyObject *args)
{
    Py_ssize_t round_digits;
    MPZ_Object *result;
    mpz_t temp, rem;

    if (PyTuple_GET_SIZE(args) == 0) {
        Py_INCREF(self);
        return self;
    }

    round_digits = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 0));
    if (round_digits == -1 && PyErr_Occurred()) {
        TYPE_ERROR("__round__() requires 'int' argument");
        return NULL;
    }

    if (round_digits >= 0) {
        Py_INCREF(self);
        return self;
    }

    round_digits = -round_digits;

    if ((result = GMPy_MPZ_New(NULL))) {
        if (round_digits >= mpz_sizeinbase(MPZ(self), 10)) {
            mpz_set_ui(result->z, 0);
        }
        else {
            mpz_inoc(temp);
            mpz_inoc(rem);
            mpz_ui_pow_ui(temp, 10, round_digits);
            mpz_fdiv_qr(result->z, rem, MPZ(self), temp);
            mpz_mul_2exp(rem, rem, 1);
            if (mpz_cmp(rem, temp) > 0) {
                mpz_add_ui(result->z, result->z, 1);
            }
            else if (mpz_cmp(rem, temp) == 0) {
                if (mpz_odd_p(result->z)) {
                    mpz_add_ui(result->z, result->z, 1);
                }
            }
            mpz_mul(result->z, result->z, temp);
            mpz_cloc(rem);
            mpz_cloc(temp);
        }
    }

    return (PyObject*)result;
}
Example #11
0
void field_init_fp(field_ptr f, mpz_t modulus) {
  if (mpz_fits_ulong_p(modulus)) {
    // If this case mattered, I'd have written a F_p implementation specialized
    // for moduli that fits into machine words.
    field_init_naive_fp(f, modulus);
  } else {
    if (mpz_odd_p(modulus)) {
      option_fpinit(f, modulus);
    } else {
      // montfp.c only supports odd moduli.
      field_init_faster_fp(f, modulus);
    }
  }
}
Example #12
0
void field_init_fast_fp(field_ptr f, mpz_t prime) {
  PBC_ASSERT(!mpz_fits_ulong_p(prime), "modulus too small");
  fp_field_data_ptr p;
  field_init(f);
  f->init = fp_init;
  f->clear = fp_clear;
  f->set_si = fp_set_si;
  f->set_mpz = fp_set_mpz;
  f->out_str = fp_out_str;
  f->add = fp_add;
  f->sub = fp_sub;
  f->set = fp_set;
  f->mul = fp_mul;
  f->mul_si = fp_mul_si;
  f->square = fp_square;
  f->doub = fp_double;
  f->halve = fp_halve;
  f->pow_mpz = fp_pow_mpz;
  f->neg = fp_neg;
  f->cmp = fp_cmp;
  f->sign = mpz_odd_p(prime) ? fp_sgn_odd : fp_sgn_even;
  f->invert = fp_invert;
  f->random = fp_random;
  f->from_hash = fp_from_hash;
  f->is1 = fp_is1;
  f->is0 = fp_is0;
  f->set0 = fp_set0;
  f->set1 = fp_set1;
  f->is_sqr = fp_is_sqr;
  f->sqrt = element_tonelli;
  f->field_clear = fp_field_clear;
  f->to_bytes = fp_to_bytes;
  f->from_bytes = fp_from_bytes;
  f->to_mpz = fp_to_mpz;

  p = f->data = pbc_malloc(sizeof(fp_field_data_t));
  p->limbs = mpz_size(prime);
  p->bytes = p->limbs * sizeof(mp_limb_t);
  p->primelimbs = pbc_malloc(p->bytes);
  mpz_export(p->primelimbs, &p->limbs, -1, sizeof(mp_limb_t), 0, 0, prime);

  mpz_set(f->order, prime);
  f->fixed_length_in_bytes = (mpz_sizeinbase(prime, 2) + 7) / 8;
}
Example #13
0
void field_init_naive_fp(field_ptr f, mpz_t prime) {
  field_init(f);
  f->init = zp_init;
  f->clear = zp_clear;
  f->set_si = zp_set_si;
  f->set_mpz = zp_set_mpz;
  f->out_str = zp_out_str;
  f->snprint = zp_snprint;
  f->set_str = zp_set_str;
  f->sign = mpz_odd_p(prime) ? zp_sgn_odd : zp_sgn_even;
  f->add = zp_add;
  f->sub = zp_sub;
  f->set = zp_set;
  f->square = zp_square;
  f->doub = zp_double;
  f->halve = zp_halve;
  f->mul = zp_mul;
  f->mul_mpz = zp_mul_mpz;
  f->mul_si = zp_mul_si;
  f->pow_mpz = zp_pow_mpz;
  f->neg = zp_neg;
  f->cmp = zp_cmp;
  f->invert = zp_invert;
  f->random = zp_random;
  f->from_hash = zp_from_hash;
  f->is1 = zp_is1;
  f->is0 = zp_is0;
  f->set0 = zp_set0;
  f->set1 = zp_set1;
  f->is_sqr = zp_is_sqr;
  f->sqrt = element_tonelli;
  f->field_clear = zp_field_clear;
  f->to_bytes = zp_to_bytes;
  f->from_bytes = zp_from_bytes;
  f->to_mpz = zp_to_mpz;

  f->out_info = zp_out_info;

  mpz_set(f->order, prime);
  f->data = NULL;
  f->fixed_length_in_bytes = (mpz_sizeinbase(prime, 2) + 7) / 8;
}
Example #14
0
void mpfr_naive_exp(mpfr_t R, mpfr_t x, mpz_t n)
{
	assert(mpz_cmp_ui(n, 0) >= 0);
	
	mpfr_t z;
	
	mpfr_init_set(z, x, MPFR_RNDN);
	mpfr_div_z(z, z, n, MPFR_RNDN);
	mpfr_add_ui(z, z, 1, MPFR_RNDN);
	
	if(mpfr_cmp_ui(z, 0) > 0)
		mpfr_squaring_int_exp(R, z, n);
	else
	{
		mpfr_neg(z, z, MPFR_RNDN);
		mpfr_squaring_int_exp(R, z, n);
		
		if(mpz_odd_p(n))
			mpfr_neg(R, R, MPFR_RNDN);
	}
}
Example #15
0
//------------------------------------------------------------------------------
// Name: is_odd
//------------------------------------------------------------------------------
bool knumber_integer::is_odd() const {
	return mpz_odd_p(mpz_);
}
Example #16
0
int chpl_mpz_odd_p(const mpz_t op) {
  return mpz_odd_p(op);
}
/*
   Add two ECC points
   @param P        The point to add
   @param Q        The point to add
   @param R        [out] The destination of the double
   @param a        Curve's a value
   @param modulus  The modulus of the field the ECC curve is in
   @return         GNUTLS_E_SUCCESS on success
*/
int
ecc_projective_add_point (ecc_point * P, ecc_point * Q, ecc_point * R,
                              mpz_t a, mpz_t modulus)
{
  /* Using "(m)add-2004-hmv" algorithm
   * It costs 12M + 4S + half. */
  mpz_t t1, t2, x, y, z;
  int err;

  if (P == NULL || Q == NULL || R == NULL || modulus == NULL)
    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;

  /* check for neutral points */
  if ( (err = ecc_projective_isneutral(Q, modulus)) == 0 ) {
    /* P + Q = P + neutral = P */

    mpz_set (R->x, P->x);
    mpz_set (R->y, P->y);
    mpz_set (R->z, P->z);

    return GNUTLS_E_SUCCESS;
  } else if (err < 0) {
    return err;
  }

  if ( (err = ecc_projective_isneutral(P, modulus)) == 0 ) {
    /* P + Q = neutral + Q = Q */

    mpz_set (R->x, Q->x);
    mpz_set (R->y, Q->y);
    mpz_set (R->z, Q->z);

    return GNUTLS_E_SUCCESS;
  } else if (err < 0) {
    return err;
  }

  if ((err = mp_init_multi (&t1, &t2, &x, &y, &z, NULL)) != 0)
    {
      return err;
    }

  /* Check if P == Q and do doubling in that case
   * If Q == -P then P + Q = neutral element
   */
  if ((mpz_cmp (P->x, Q->x) == 0) &&
      (mpz_cmp (P->z, Q->z) == 0))
    {
      /* x and z coordinates match. Check if P->y = Q->y, or P->y = -Q->y
       */
      if (mpz_cmp (P->y, Q->y) == 0)
        {
          mp_clear_multi (&t1, &t2, &x, &y, &z, NULL);
          return ecc_projective_dbl_point (P, R, a, modulus);
        }

      mpz_sub (t1, modulus, Q->y);
      if (mpz_cmp (P->y, t1) == 0)
        {
          mp_clear_multi (&t1, &t2, &x, &y, &z, NULL);
          mpz_set_ui(R->x, 1);
          mpz_set_ui(R->y, 1);
          mpz_set_ui(R->z, 0);
          return GNUTLS_E_SUCCESS;
        }
    }


  mpz_set (x, P->x);
  mpz_set (y, P->y);
  mpz_set (z, P->z);

  /* if Z is one then these are no-operations */
  if (mpz_cmp_ui (Q->z, 1) != 0)
    {
      /* T1 = Z' * Z' */
      mpz_mul (t1, Q->z, Q->z);
      mpz_mod (t1, t1, modulus);
      /* X = X * T1 */
      mpz_mul (x, x, t1);
      mpz_mod (x, x, modulus);
      /* T1 = Z' * T1 */
      mpz_mul (t1, t1, Q->z);
      mpz_mod (t1, t1, modulus);
      /* Y = Y * T1 */
      mpz_mul (y, y, t1);
      mpz_mod (y, y, modulus);
    }

  /* T1 = Z*Z */
  mpz_mul (t1, z, z);
  mpz_mod (t1, t1, modulus);
  /* T2 = X' * T1 */
  mpz_mul (t2, t1, Q->x);
  mpz_mod (t2, t2, modulus);
  /* T1 = Z * T1 */
  mpz_mul (t1, t1, z);
  mpz_mod (t1, t1, modulus);
  /* T1 = Y' * T1 */
  mpz_mul (t1, t1, Q->y);
  mpz_mod (t1, t1, modulus);

  /* Y = Y - T1 */
  mpz_sub (y, y, t1);
  if (mpz_cmp_ui (y, 0) < 0)
    {
      mpz_add (y, y, modulus);
    }
  /* T1 = 2T1 */
  mpz_add (t1, t1, t1);
  if (mpz_cmp (t1, modulus) >= 0)
    {
      mpz_sub (t1, t1, modulus);
    }
  /* T1 = Y + T1 */
  mpz_add (t1, t1, y);
  if (mpz_cmp (t1, modulus) >= 0)
    {
      mpz_sub (t1, t1, modulus);
    }
  /* X = X - T2 */
  mpz_sub (x, x, t2);
  if (mpz_cmp_ui (x, 0) < 0)
    {
      mpz_add (x, x, modulus);
    }
  /* T2 = 2T2 */
  mpz_add (t2, t2, t2);
  if (mpz_cmp (t2, modulus) >= 0)
    {
      mpz_sub (t2, t2, modulus);
    }
  /* T2 = X + T2 */
  mpz_add (t2, t2, x);
  if (mpz_cmp (t2, modulus) >= 0)
    {
      mpz_sub (t2, t2, modulus);
    }

  /* if Z' != 1 */
  if (mpz_cmp_ui (Q->z, 1) != 0)
    {
      /* Z = Z * Z' */
      mpz_mul (z, z, Q->z);
      mpz_mod (z, z, modulus);
    }

  /* Z = Z * X */
  mpz_mul (z, z, x);
  mpz_mod (z, z, modulus);

  /* T1 = T1 * X  */
  mpz_mul (t1, t1, x);
  mpz_mod (t1, t1, modulus);
  /* X = X * X */
  mpz_mul (x, x, x);
  mpz_mod (x, x, modulus);
  /* T2 = T2 * x */
  mpz_mul (t2, t2, x);
  mpz_mod (t2, t2, modulus);
  /* T1 = T1 * X  */
  mpz_mul (t1, t1, x);
  mpz_mod (t1, t1, modulus);

  /* X = Y*Y */
  mpz_mul (x, y, y);
  mpz_mod (x, x, modulus);
  /* X = X - T2 */
  mpz_sub (x, x, t2);
  if (mpz_cmp_ui (x, 0) < 0)
    {
      mpz_add (x, x, modulus);
    }

  /* T2 = T2 - X */
  mpz_sub (t2, t2, x);
  if (mpz_cmp_ui (t2, 0) < 0)
    {
      mpz_add (t2, t2, modulus);
    }
  /* T2 = T2 - X */
  mpz_sub (t2, t2, x);
  if (mpz_cmp_ui (t2, 0) < 0)
    {
      mpz_add (t2, t2, modulus);
    }
  /* T2 = T2 * Y */
  mpz_mul (t2, t2, y);
  mpz_mod (t2, t2, modulus);
  /* Y = T2 - T1 */
  mpz_sub (y, t2, t1);
  if (mpz_cmp_ui (y, 0) < 0)
    {
      mpz_add (y, y, modulus);
    }
  /* Y = Y/2 */
  if (mpz_odd_p (y))
    {
      mpz_add (y, y, modulus);
    }
  mpz_divexact_ui (y, y, 2);

  mpz_set (R->x, x);
  mpz_set (R->y, y);
  mpz_set (R->z, z);

  err = GNUTLS_E_SUCCESS;

  mp_clear_multi (&t1, &t2, &x, &y, &z, NULL);
  return err;
}
Example #18
0
static PyObject *
Pympz_mpmath_normalize(PyObject *self, PyObject *args)
{
    long sign = 0;
    mpir_si bc = 0, prec = 0, shift, zbits, carry = 0;
    PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0, *rndstr = 0;
    PympzObject *man = 0, *upper = 0, *lower = 0;
    char rnd = 0;

    if (PyTuple_GET_SIZE(args) == 6) {
        /* Need better error-checking here. Under Python 3.0, overflow into
           C-long is possible. */
        sign = clong_From_Integer(PyTuple_GET_ITEM(args, 0));
        man = (PympzObject *)PyTuple_GET_ITEM(args, 1);
        exp = PyTuple_GET_ITEM(args, 2);
        bc = SI_From_Integer(PyTuple_GET_ITEM(args, 3));
        prec = SI_From_Integer(PyTuple_GET_ITEM(args, 4));
        rndstr = PyTuple_GET_ITEM(args, 5);
        if (PyErr_Occurred()) {
            TYPE_ERROR("arguments long, PympzObject*, PyObject*, long, long, char needed");
            return NULL;
        }
    }
    else {
        TYPE_ERROR("6 arguments required");
        return NULL;
    }

    if (!Pympz_Check(man)) {
        TYPE_ERROR("argument is not an mpz");
        return NULL;
    }

    /* If rndstr really is a string, extract the first character. */
    if (Py2or3String_Check(rndstr)) {
        rnd = Py2or3String_AsString(rndstr)[0];
    }
    else {
        VALUE_ERROR("invalid rounding mode specified");
        return NULL;
    }

    /* If the mantissa is 0, return the normalized representation. */
    if (!mpz_sgn(man->z)) {
        Py_INCREF((PyObject*)man);
        return mpmath_build_mpf(0, man, 0, 0);
    }

    /* if bc <= prec and the number is odd return it */
    if ((bc <= prec) && mpz_odd_p(man->z)) {
        Py_INCREF((PyObject*)man);
        Py_INCREF((PyObject*)exp);
        return mpmath_build_mpf(sign, man, exp, bc);
    }

    if (!(upper = (PympzObject*)Pympz_new()) ||
        !(lower = (PympzObject*)Pympz_new())) {
        Py_XDECREF((PyObject*)upper);
        Py_XDECREF((PyObject*)lower);
    }

    shift = bc - prec;
    if (shift>0) {
        switch (rnd) {
            case 'f':
                if(sign) {
                    mpz_cdiv_q_2exp(upper->z, man->z, shift);
                }
                else {
                    mpz_fdiv_q_2exp(upper->z, man->z, shift);
                }
                break;
            case 'c':
                if(sign) {
                    mpz_fdiv_q_2exp(upper->z, man->z, shift);
                }
                else {
                    mpz_cdiv_q_2exp(upper->z, man->z, shift);
                }
                break;
            case 'd':
                mpz_fdiv_q_2exp(upper->z, man->z, shift);
                break;
            case 'u':
                mpz_cdiv_q_2exp(upper->z, man->z, shift);
                break;
            case 'n':
            default:
                mpz_tdiv_r_2exp(lower->z, man->z, shift);
                mpz_tdiv_q_2exp(upper->z, man->z, shift);
                if (mpz_sgn(lower->z)) {
                    /* lower is not 0 so it must have at least 1 bit set */
                    if (mpz_sizeinbase(lower->z, 2) == shift) {
                        /* lower is >= 1/2 */
                        if (mpz_scan1(lower->z, 0) == shift-1) {
                            /* lower is exactly 1/2 */
                            if (mpz_odd_p(upper->z))
                                carry = 1;
                        }
                        else {
                            carry = 1;
                        }
                    }
                }
                if (carry)
                    mpz_add_ui(upper->z, upper->z, 1);
        }

        if (!(tmp = PyIntOrLong_FromSI(shift))) {
            Py_DECREF((PyObject*)upper);
            Py_DECREF((PyObject*)lower);
            return NULL;
        }

        if (!(newexp = PyNumber_Add(exp, tmp))) {
            Py_DECREF((PyObject*)upper);
            Py_DECREF((PyObject*)lower);
            Py_DECREF(tmp);
            return NULL;
        }
        Py_DECREF(tmp);
        bc = prec;
    }
    else {
        mpz_set(upper->z, man->z);
        newexp = exp;
        Py_INCREF(newexp);
    }

    /* Strip trailing 0 bits. */
    if ((zbits = mpz_scan1(upper->z, 0)))
        mpz_tdiv_q_2exp(upper->z, upper->z, zbits);

    if (!(tmp = PyIntOrLong_FromSI(zbits))) {
        Py_DECREF((PyObject*)upper);
        Py_DECREF((PyObject*)lower);
        Py_DECREF(newexp);
        return NULL;
    }
    if (!(newexp2 = PyNumber_Add(newexp, tmp))) {
        Py_DECREF((PyObject*)upper);
        Py_DECREF((PyObject*)lower);
        Py_DECREF(tmp);
        Py_DECREF(newexp);
        return NULL;
    }
    Py_DECREF(newexp);
    Py_DECREF(tmp);

    bc -= zbits;
    /* Check if one less than a power of 2 was rounded up. */
    if (!mpz_cmp_ui(upper->z, 1))
        bc = 1;

    Py_DECREF((PyObject*)lower);
    return mpmath_build_mpf(sign, upper, newexp2, bc);
}
Example #19
0
static PyObject *
Pympz_mpmath_create(PyObject *self, PyObject *args)
{
    long sign;
    mpir_si bc, shift, zbits, carry = 0, prec = 0;
    PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0;
    PympzObject *man = 0, *upper = 0, *lower = 0;

    const char *rnd = "f";

    if (PyTuple_GET_SIZE(args) < 2) {
        TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments");
        return NULL;
    }

    switch (PyTuple_GET_SIZE(args)) {
        case 4:
            rnd = Py2or3String_AsString(PyTuple_GET_ITEM(args, 3));
        case 3:
            prec = SI_From_Integer(PyTuple_GET_ITEM(args, 2));
            if (prec == -1 && PyErr_Occurred())
                return NULL;
            prec = ABS(prec);
        case 2:
            exp = PyTuple_GET_ITEM(args, 1);
        case 1:
            man = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0));
            if (!man) {
                TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments");
                return NULL;
            }
    }

    /* If the mantissa is 0, return the normalized representation. */
    if (!mpz_sgn(man->z)) {
        return mpmath_build_mpf(0, man, 0, 0);
    }

    upper = (PympzObject*)Pympz_new();
    lower = (PympzObject*)Pympz_new();
    if (!upper || !lower) {
        Py_DECREF((PyObject*)man);
        Py_XDECREF((PyObject*)upper);
        Py_XDECREF((PyObject*)lower);
        return NULL;
    }

    /* Extract sign, make man positive, and set bit count */
    sign = (mpz_sgn(man->z) == -1);
    mpz_abs(upper->z, man->z);
    bc = mpz_sizeinbase(upper->z, 2);

    if (!prec) prec = bc;

    shift = bc - prec;
    if (shift > 0) {
        switch (rnd[0]) {
            case 'f':
                if(sign) {
                    mpz_cdiv_q_2exp(upper->z, upper->z, shift);
                }
                else {
                    mpz_fdiv_q_2exp(upper->z, upper->z, shift);
                }
                break;
            case 'c':
                if(sign) {
                    mpz_fdiv_q_2exp(upper->z, upper->z, shift);
                }
                else {
                    mpz_cdiv_q_2exp(upper->z, upper->z, shift);
                }
                break;
            case 'd':
                mpz_fdiv_q_2exp(upper->z, upper->z, shift);
                break;
            case 'u':
                mpz_cdiv_q_2exp(upper->z, upper->z, shift);
                break;
            case 'n':
            default:
                mpz_tdiv_r_2exp(lower->z, upper->z, shift);
                mpz_tdiv_q_2exp(upper->z, upper->z, shift);
                if (mpz_sgn(lower->z)) {
                    /* lower is not 0 so it must have at least 1 bit set */
                    if (mpz_sizeinbase(lower->z, 2)==shift) {
                        /* lower is >= 1/2 */
                        if (mpz_scan1(lower->z, 0)==shift-1) {
                            /* lower is exactly 1/2 */
                            if (mpz_odd_p(upper->z))
                                carry = 1;
                        }
                        else {
                            carry = 1;
                        }
                    }
                }
                if (carry)
                    mpz_add_ui(upper->z, upper->z, 1);
        }
        if (!(tmp = PyIntOrLong_FromSI(shift))) {
            Py_DECREF((PyObject*)upper);
            Py_DECREF((PyObject*)lower);
            return NULL;
        }
        if (!(newexp = PyNumber_Add(exp, tmp))) {
            Py_DECREF((PyObject*)man);
            Py_DECREF((PyObject*)upper);
            Py_DECREF((PyObject*)lower);
            Py_DECREF(tmp);
            return NULL;
        }
        Py_DECREF(tmp);
        bc = prec;
    }
    else {
        newexp = exp;
        Py_INCREF(newexp);
    }

    /* Strip trailing 0 bits. */
    if ((zbits = mpz_scan1(upper->z, 0)))
        mpz_tdiv_q_2exp(upper->z, upper->z, zbits);

    if (!(tmp = PyIntOrLong_FromSI(zbits))) {
        Py_DECREF((PyObject*)man);
        Py_DECREF((PyObject*)upper);
        Py_DECREF((PyObject*)lower);
        Py_DECREF(newexp);
        return NULL;
    }
    if (!(newexp2 = PyNumber_Add(newexp, tmp))) {
        Py_DECREF((PyObject*)man);
        Py_DECREF((PyObject*)upper);
        Py_DECREF((PyObject*)lower);
        Py_DECREF(tmp);
        Py_DECREF(newexp);
        return NULL;
    }
    Py_DECREF(newexp);
    Py_DECREF(tmp);

    bc -= zbits;
    /* Check if one less than a power of 2 was rounded up. */
    if (!mpz_cmp_ui(upper->z, 1))
        bc = 1;

    Py_DECREF((PyObject*)lower);
    Py_DECREF((PyObject*)man);
    return mpmath_build_mpf(sign, upper, newexp2, bc);
}
Example #20
0
static int zp_sgn_odd(element_ptr a) {
  mpz_ptr z = a->data;

  return mpz_is0(z) ? 0 : (mpz_odd_p(z) ? 1 : -1);
}
Example #21
0
bool
is_odd<mpz_class>(const mpz_class &x)
{
	return mpz_odd_p(x.get_mpz_t());
}
Example #22
0
void field_init_curve_ab(field_ptr f, element_ptr a, element_ptr b, mpz_t order, mpz_t cofac) {
  /*
  if (element_is0(a)) {
    c->double_nocheck = cc_double_no_check_ais0;
  } else {
    c->double_nocheck = cc_double_no_check;
  }
  */
  curve_data_ptr cdp;
  field_init(f);
  mpz_set(f->order, order);
  f->data = pbc_malloc(sizeof(*cdp));
  cdp = (curve_data_ptr)f->data;
  cdp->field = a->field;
  element_init(cdp->a, cdp->field);
  element_init(cdp->b, cdp->field);
  element_set(cdp->a, a);
  element_set(cdp->b, b);

  f->init = curve_init;
  f->clear = curve_clear;
  f->neg = f->invert = curve_invert;
  f->square = f->doub = curve_double;
  f->multi_doub = multi_double;
  f->add = f->mul = curve_mul;
  f->multi_add = multi_add;
  f->mul_mpz = element_pow_mpz;
  f->cmp = curve_cmp;
  f->set0 = f->set1 = curve_set1;
  f->is0 = f->is1 = curve_is1;
  f->sign = curve_sign;
  f->set = curve_set;
  f->random = curve_random_pointmul;
  //f->random = curve_random_solvefory;
  f->from_hash = curve_from_hash;
  f->out_str = curve_out_str;
  f->snprint = curve_snprint;
  f->set_multiz = curve_set_multiz;
  f->set_str = curve_set_str;
  f->field_clear = field_clear_curve;
  if (cdp->field->fixed_length_in_bytes < 0) {
    f->length_in_bytes = curve_length_in_bytes;
  } else {
    f->fixed_length_in_bytes = 2 * cdp->field->fixed_length_in_bytes;
  }
  f->to_bytes = curve_to_bytes;
  f->from_bytes = curve_from_bytes;
  f->out_info = curve_out_info;
  f->item_count = curve_item_count;
  f->item = curve_item;
  f->get_x = curve_get_x;
  f->get_y = curve_get_y;

  if (mpz_odd_p(order)) {
    f->is_sqr = odd_curve_is_sqr;
  } else {
    f->is_sqr = even_curve_is_sqr;
  }

  element_init(cdp->gen_no_cofac, f);
  element_init(cdp->gen, f);
  curve_random_no_cofac_solvefory(cdp->gen_no_cofac);
  if (cofac) {
    cdp->cofac = (mpz_ptr)pbc_malloc(sizeof(mpz_t));
    mpz_init(cdp->cofac);
    mpz_set(cdp->cofac, cofac);
    element_mul_mpz(cdp->gen, cdp->gen_no_cofac, cofac);
  } else{
    cdp->cofac = NULL;
    element_set(cdp->gen, cdp->gen_no_cofac);
  }
  cdp->quotient_cmp = NULL;
}
Example #23
0
static int
e_mpz_odd_p (mpz_srcptr x)
{
  return mpz_odd_p (x);
}
Example #24
0
static PyObject *
Pympq_round(PyObject *self, PyObject *args)
{
    Py_ssize_t round_digits = 0;
    PympqObject *resultq;
    PympzObject *resultz;
    mpz_t temp, rem;

    /* If args is NULL or the size of args is 0, we just return an mpz. */

    if (!args || PyTuple_GET_SIZE(args) == 0) {
        if (!(resultz = (PympzObject*)Pympz_new()))
            return NULL;

        mpz_inoc(rem);
        mpz_fdiv_qr(resultz->z, rem, mpq_numref(Pympq_AS_MPQ(self)),
                    mpq_denref(Pympq_AS_MPQ(self)));
        mpz_mul_2exp(rem, rem, 1);
        if (mpz_cmp(rem, mpq_denref(Pympq_AS_MPQ(self))) > 0) {
            mpz_add_ui(resultz->z, resultz->z, 1);
        }
        else if (mpz_cmp(rem, mpq_denref(Pympq_AS_MPQ(self))) == 0) {
            if (mpz_odd_p(resultz->z)) {
                mpz_add_ui(resultz->z, resultz->z, 1);
            }
        }
        mpz_cloc(rem);
        return (PyObject*)resultz;
    }

    if (PyTuple_GET_SIZE(args) > 1) {
        TYPE_ERROR("Too many arguments for __round__().");
        return NULL;
    }

    if (PyTuple_GET_SIZE(args) == 1) {
        round_digits = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 0));
        if (round_digits == -1 && PyErr_Occurred()) {
            TYPE_ERROR("__round__() requires 'int' argument");
            return NULL;
        }
    }

    if (!(resultq = (PympqObject*)Pympq_new()))
        return NULL;

    mpz_inoc(temp);
    mpz_ui_pow_ui(temp, 10, round_digits > 0 ? round_digits : -round_digits);

    mpq_set(resultq->q, Pympq_AS_MPQ(self));
    if (round_digits > 0) {
        mpz_mul(mpq_numref(resultq->q), mpq_numref(resultq->q), temp);
        mpq_canonicalize(resultq->q);
        if (!(resultz = (PympzObject*)Pympq_round((PyObject*)resultq, NULL))) {
            mpz_cloc(temp);
            return NULL;
        }
        mpz_set(mpq_numref(resultq->q), resultz->z);
        Py_DECREF((PyObject*)resultz);
        mpz_set(mpq_denref(resultq->q), temp);
        mpz_cloc(temp);
        mpq_canonicalize(resultq->q);
    }
    else {
        mpz_mul(mpq_denref(resultq->q), mpq_denref(resultq->q), temp);
        mpq_canonicalize(resultq->q);
        if (!(resultz = (PympzObject*)Pympq_round((PyObject*)resultq, NULL))) {
            mpz_cloc(temp);
            return NULL;
        }
        mpq_set_ui(resultq->q, 0, 1);
        mpz_mul(mpq_numref(resultq->q), resultz->z, temp);
        Py_DECREF((PyObject*)resultz);
        mpz_cloc(temp);
        mpq_canonicalize(resultq->q);
    }
    return (PyObject*)resultq;
}
/*
   Double an ECC point
   @param P   The point to double
   @param R   [out] The destination of the double
   @param modulus  The modulus of the field the ECC curve is in
   @param mp       The "b" value from montgomery_setup()
   @return 0 on success
*/
int
ecc_projective_dbl_point (ecc_point * P, ecc_point * R, mpz_t a /* a is -3 */,
                              mpz_t modulus)
{
   mpz_t t1, t2;
   int   err;

   if (P == NULL || R == NULL || modulus == NULL)
     return -1;

   if ((err = mp_init_multi(&t1, &t2, NULL)) != 0) {
      return err;
   }

   if (P != R) {
      mpz_set(R->x, P->x);
      mpz_set(R->y, P->y);
      mpz_set(R->z, P->z);
   }

   /* t1 = Z * Z */
   mpz_mul(t1, R->z, R->z);
   mpz_mod(t1, t1, modulus);
   /* Z = Y * Z */
   mpz_mul(R->z, R->y, R->z);
   mpz_mod(R->z, R->z, modulus);
   /* Z = 2Z */
   mpz_add(R->z, R->z, R->z);
   if (mpz_cmp(R->z, modulus) >= 0) {
      mpz_sub(R->z, R->z, modulus);
   }
   
   /* T2 = X - T1 */
   mpz_sub(t2, R->x, t1);
   if (mpz_cmp_ui(t2, 0) < 0) {
      mpz_add(t2, t2, modulus);
   }
   /* T1 = X + T1 */
   mpz_add(t1, t1, R->x);
   if (mpz_cmp(t1, modulus) >= 0) {
      mpz_sub(t1, t1, modulus);
   }
   /* T2 = T1 * T2 */
   mpz_mul(t2, t1, t2);
   mpz_mod(t2, t2, modulus);
   /* T1 = 2T2 */
   mpz_add(t1, t2, t2);
   if (mpz_cmp(t1, modulus) >= 0) {
      mpz_sub(t1, t1, modulus);
   }
   /* T1 = T1 + T2 */
   mpz_add(t1, t1, t2);
   if (mpz_cmp(t1, modulus) >= 0) {
      mpz_sub(t1, t1, modulus);
   }

   /* Y = 2Y */
   mpz_add(R->y, R->y, R->y);
   if (mpz_cmp(R->y, modulus) >= 0) {
      mpz_sub(R->y, R->y, modulus);
   }
   /* Y = Y * Y */
   mpz_mul(R->y, R->y, R->y);
   mpz_mod(R->y, R->y, modulus);
   /* T2 = Y * Y */
   mpz_mul(t2, R->y, R->y);
   mpz_mod(t2, t2, modulus);
   /* T2 = T2/2 */
   if (mpz_odd_p(t2)) {
      mpz_add(t2, t2, modulus);
   }
   mpz_divexact_ui(t2, t2, 2);
   /* Y = Y * X */
   mpz_mul(R->y, R->y, R->x);
   mpz_mod(R->y, R->y, modulus);

   /* X  = T1 * T1 */
   mpz_mul(R->x, t1, t1);
   mpz_mod(R->x, R->x, modulus);
   /* X = X - Y */
   mpz_sub(R->x, R->x, R->y);
   if (mpz_cmp_ui(R->x, 0) < 0) {
      mpz_add(R->x, R->x, modulus);
   }
   /* X = X - Y */
   mpz_sub(R->x, R->x, R->y);
   if (mpz_cmp_ui(R->x, 0) < 0) {
      mpz_add(R->x, R->x, modulus);
   }

   /* Y = Y - X */     
   mpz_sub(R->y, R->y, R->x);
   if (mpz_cmp_ui(R->y, 0) < 0) {
      mpz_add(R->y, R->y, modulus);
   }
   /* Y = Y * T1 */
   mpz_mul(R->y, R->y, t1);
   mpz_mod(R->y, R->y, modulus);
   /* Y = Y - T2 */
   mpz_sub(R->y, R->y, t2);
   if (mpz_cmp_ui(R->y, 0) < 0) {
      mpz_add( R->y, R->y, modulus);
   }
 
   err = 0;

   mp_clear_multi(&t1, &t2, NULL);
   return err;
}
/*
   Add two ECC points
   @param P        The point to add
   @param Q        The point to add
   @param R        [out] The destination of the double
   @param a        Curve's a value
   @param modulus  The modulus of the field the ECC curve is in
   @return 0 on success
*/
int
ecc_projective_add_point (ecc_point * P, ecc_point * Q, ecc_point * R,
                              mpz_t a, mpz_t modulus)
{
  mpz_t t1, t2, x, y, z;
  int err;

  if (P == NULL || Q == NULL || R == NULL || modulus == NULL)
    return -1;

  if ((err = mp_init_multi (&t1, &t2, &x, &y, &z, NULL)) != 0)
    {
      return err;
    }

  /* Check if P == Q and do doubling in that case 
   * If Q == -P then P+Q=point at infinity
   */
  if ((mpz_cmp (P->x, Q->x) == 0) &&
      (mpz_cmp (P->z, Q->z) == 0))
    {
      /* x and z coordinates match. Check if P->y = Q->y, or P->y = -Q->y
       */
      if (mpz_cmp (P->y, Q->y) == 0)
        {
          mp_clear_multi (&t1, &t2, &x, &y, &z, NULL);
          return ecc_projective_dbl_point (P, R, a, modulus);
        }
      
      mpz_sub (t1, modulus, Q->y);
      if (mpz_cmp (P->y, t1) == 0)
        {
          mp_clear_multi (&t1, &t2, &x, &y, &z, NULL);
          mpz_set_ui(R->x, 1);
          mpz_set_ui(R->y, 1);
          mpz_set_ui(R->z, 0);
          return 0;
        }
    }


  mpz_set (x, P->x);
  mpz_set (y, P->y);
  mpz_set (z, P->z);

  /* if Z is one then these are no-operations */
  if (mpz_cmp_ui (Q->z, 1) != 0)
    {
      /* T1 = Z' * Z' */
      mpz_mul (t1, Q->z, Q->z);
      mpz_mod (t1, t1, modulus);
      /* X = X * T1 */
      mpz_mul (x, x, t1);
      mpz_mod (x, x, modulus);
      /* T1 = Z' * T1 */
      mpz_mul (t1, t1, Q->z);
      mpz_mod (t1, t1, modulus);
      /* Y = Y * T1 */
      mpz_mul (y, y, t1);
      mpz_mod (y, y, modulus);
    }

  /* T1 = Z*Z */
  mpz_mul (t1, z, z);
  mpz_mod (t1, t1, modulus);
  /* T2 = X' * T1 */
  mpz_mul (t2, t1, Q->x);
  mpz_mod (t2, t2, modulus);
  /* T1 = Z * T1 */
  mpz_mul (t1, t1, z);
  mpz_mod (t1, t1, modulus);
  /* T1 = Y' * T1 */
  mpz_mul (t1, t1, Q->y);
  mpz_mod (t1, t1, modulus);

  /* Y = Y - T1 */
  mpz_sub (y, y, t1);
  if (mpz_cmp_ui (y, 0) < 0)
    {
      mpz_add (y, y, modulus);
    }
  /* T1 = 2T1 */
  mpz_add (t1, t1, t1);
  if (mpz_cmp (t1, modulus) >= 0)
    {
      mpz_sub (t1, t1, modulus);
    }
  /* T1 = Y + T1 */
  mpz_add (t1, t1, y);
  if (mpz_cmp (t1, modulus) >= 0)
    {
      mpz_sub (t1, t1, modulus);
    }
  /* X = X - T2 */
  mpz_sub (x, x, t2);
  if (mpz_cmp_ui (x, 0) < 0)
    {
      mpz_add (x, x, modulus);
    }
  /* T2 = 2T2 */
  mpz_add (t2, t2, t2);
  if (mpz_cmp (t2, modulus) >= 0)
    {
      mpz_sub (t2, t2, modulus);
    }
  /* T2 = X + T2 */
  mpz_add (t2, t2, x);
  if (mpz_cmp (t2, modulus) >= 0)
    {
      mpz_sub (t2, t2, modulus);
    }

  /* if Z' != 1 */
  if (mpz_cmp_ui (Q->z, 1) != 0)
    {
      /* Z = Z * Z' */
      mpz_mul (z, z, Q->z);
      mpz_mod (z, z, modulus);
    }

  /* Z = Z * X */
  mpz_mul (z, z, x);
  mpz_mod (z, z, modulus);

  /* T1 = T1 * X  */
  mpz_mul (t1, t1, x);
  mpz_mod (t1, t1, modulus);
  /* X = X * X */
  mpz_mul (x, x, x);
  mpz_mod (x, x, modulus);
  /* T2 = T2 * x */
  mpz_mul (t2, t2, x);
  mpz_mod (t2, t2, modulus);
  /* T1 = T1 * X  */
  mpz_mul (t1, t1, x);
  mpz_mod (t1, t1, modulus);

  /* X = Y*Y */
  mpz_mul (x, y, y);
  mpz_mod (x, x, modulus);
  /* X = X - T2 */
  mpz_sub (x, x, t2);
  if (mpz_cmp_ui (x, 0) < 0)
    {
      mpz_add (x, x, modulus);
    }

  /* T2 = T2 - X */
  mpz_sub (t2, t2, x);
  if (mpz_cmp_ui (t2, 0) < 0)
    {
      mpz_add (t2, t2, modulus);
    }
  /* T2 = T2 - X */
  mpz_sub (t2, t2, x);
  if (mpz_cmp_ui (t2, 0) < 0)
    {
      mpz_add (t2, t2, modulus);
    }
  /* T2 = T2 * Y */
  mpz_mul (t2, t2, y);
  mpz_mod (t2, t2, modulus);
  /* Y = T2 - T1 */
  mpz_sub (y, t2, t1);
  if (mpz_cmp_ui (y, 0) < 0)
    {
      mpz_add (y, y, modulus);
    }
  /* Y = Y/2 */
  if (mpz_odd_p (y))
    {
      mpz_add (y, y, modulus);
    }
  mpz_divexact_ui (y, y, 2);

  mpz_set (R->x, x);
  mpz_set (R->y, y);
  mpz_set (R->z, z);

  err = 0;

  mp_clear_multi (&t1, &t2, &x, &y, &z, NULL);
  return err;
}
void mpz_sqrtmp_r
	(mpz_ptr root, mpz_srcptr a, mpz_srcptr p)
{
	/* ? a \neq 0 */
	if (mpz_get_ui(a) != 0)
	{
		/* ? p = 3 (mod 4) */
		if (mpz_congruent_ui_p(p, 3L, 4L))
		{
			mpz_t foo;
			mpz_init_set(foo, p);
			mpz_add_ui(foo, foo, 1L);
			mpz_fdiv_q_2exp(foo, foo, 2L);
			mpz_powm(root, a, foo, p);
			mpz_clear(foo);
			return;
		}
		/* ! p = 1 (mod 4) */
		else
		{
			/* ! s = (p-1)/4 */
			mpz_t s;
			mpz_init_set(s, p);
			mpz_sub_ui(s, s, 1L);
			mpz_fdiv_q_2exp(s, s, 2L);
			/* ? p = 5 (mod 8) */
			if (mpz_congruent_ui_p(p, 5L, 8L))
			{
				mpz_t foo, b;
				mpz_init(foo);
				mpz_powm(foo, a, s, p);
				mpz_init_set(b, p);
				mpz_add_ui(b, b, 3L);
				mpz_fdiv_q_2exp(b, b, 3L);
				mpz_powm(root, a, b, p);
				/* ? a^{(p-1)/4} = 1 (mod p) */
				if (mpz_cmp_ui(foo, 1L) == 0)
				{
					mpz_clear(foo), mpz_clear(s), mpz_clear(b);
					return;
				}
				/* ! a^{(p-1)/4} = -1 (mod p) */
				else
				{
					do
						mpz_wrandomm(b, p);
					while (mpz_jacobi(b, p) != -1);
					mpz_powm(b, b, s, p);
					mpz_mul(root, root, b);
					mpz_mod(root, root, p);
					mpz_clear(foo), mpz_clear(s), mpz_clear(b);
					return;
				}
			}
			/* ! p = 1 (mod 8) */
			else
			{
				mpz_t foo, bar, b, t;
				mpz_init(foo), mpz_init(bar);
				mpz_powm(foo, a, s, p);
				/* while a^s = 1 (mod p) */
				while (mpz_cmp_ui(foo, 1L) == 0)
				{
					/* ? s odd */
					if (mpz_odd_p(s))
					{
						mpz_add_ui(s, s, 1L);
						mpz_fdiv_q_2exp(s, s, 1L);
						mpz_powm(root, a, s, p);
						mpz_clear(foo), mpz_clear(s);
						return;
					}
					/* ! s even */
					else
					{
						mpz_fdiv_q_2exp(s, s, 1L);
					}
					mpz_powm(foo, a, s, p);
				}
				/* ! a^s = -1 (mod p) */
				mpz_init(b);
				do
					mpz_wrandomm(b, p);
				while (mpz_jacobi(b, p) != -1);
				mpz_init_set(t, p);
				mpz_sub_ui(t, t, 1L);
				mpz_fdiv_q_2exp(t, t, 1L);
				/* while s even */
				while (mpz_even_p(s))
				{
					mpz_fdiv_q_2exp(s, s, 1L);
					mpz_fdiv_q_2exp(t, t, 1L);
					mpz_powm(foo, a, s, p);
					mpz_powm(bar, b, t, p);
					mpz_mul(foo, foo, bar);
					mpz_mod(foo, foo, p);
					mpz_set_si(bar, -1L);
					/* ? a^s * b^t = -1 (mod p) */
					if (mpz_congruent_p(foo, bar, p))
					{
						mpz_set(bar, p);
						mpz_sub_ui(bar, bar, 1L);
						mpz_fdiv_q_2exp(bar, bar, 1L);
						mpz_add(t, t, bar);
					}
				}
				mpz_add_ui(s, s, 1L);
				mpz_fdiv_q_2exp(s, s, 1L);
				mpz_fdiv_q_2exp(t, t, 1L);
				mpz_powm(foo, a, s, p);
				mpz_powm(bar, b, t, p);
				mpz_mul(root, foo, bar);
				mpz_mod(root, root, p);
				mpz_clear(foo), mpz_clear(bar);
				mpz_clear(s), mpz_clear(b), mpz_clear(t);
				return;
			}
		}
	}
	/* error, return zero root */
	mpz_set_ui(root, 0L);
}
/*
   Double an ECC point
   @param P         The point to double
   @param R   [out] The destination of the double
   @param a         Curve's a value
   @param modulus   The modulus of the field the ECC curve is in
   @return          GNUTLS_E_SUCCESS on success
*/
int
ecc_projective_dbl_point (ecc_point * P, ecc_point * R, mpz_t a,
                              mpz_t modulus)
{
   /* Using "dbl-2004-hmv" algorithm.
    * It costs 4M + 4S + half. */
   mpz_t t1, t2;
   int err;

   if (P == NULL || R == NULL || modulus == NULL)
     return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;

   if ( (err = ecc_projective_isneutral(P, modulus)) == 1 ) {

     if ((err = mp_init_multi(&t1, &t2, NULL)) != 0) {
        return err;
     }

     if (P != R) {
       mpz_set(R->x, P->x);
       mpz_set(R->y, P->y);
       mpz_set(R->z, P->z);
     }

     if (mpz_cmp_ui (P->z, 1) != 0) {
         /* t1 = Z * Z */
         mpz_mul(t1, R->z, R->z);
         mpz_mod(t1, t1, modulus);
         /* Z = Y * Z */
         mpz_mul(R->z, R->y, R->z);
         mpz_mod(R->z, R->z, modulus);
         /* Z = 2Z */
         mpz_add(R->z, R->z, R->z);
         if (mpz_cmp(R->z, modulus) >= 0) {
            mpz_sub(R->z, R->z, modulus);
         }
     } else {
         /* t1 = 1 */
         mpz_set(t1, P->z);
         /* Z = 2Y */
         mpz_add(R->z, R->y, R->y);
         if (mpz_cmp(R->z, modulus) >= 0) {
            mpz_sub(R->z, R->z, modulus);
         }
     }

     /* T2 = X - T1 */
     mpz_sub(t2, R->x, t1);
     if (mpz_cmp_ui(t2, 0) < 0) {
        mpz_add(t2, t2, modulus);
     }
     /* T1 = X + T1 */
     mpz_add(t1, t1, R->x);
     if (mpz_cmp(t1, modulus) >= 0) {
        mpz_sub(t1, t1, modulus);
     }
     /* T2 = T1 * T2 */
     mpz_mul(t2, t1, t2);
     mpz_mod(t2, t2, modulus);
     /* T1 = 2T2 */
     mpz_add(t1, t2, t2);
     if (mpz_cmp(t1, modulus) >= 0) {
        mpz_sub(t1, t1, modulus);
     }
     /* T1 = T1 + T2 */
     mpz_add(t1, t1, t2);
     if (mpz_cmp(t1, modulus) >= 0) {
        mpz_sub(t1, t1, modulus);
     }

     /* Y = 2Y */
     mpz_add(R->y, R->y, R->y);
     if (mpz_cmp(R->y, modulus) >= 0) {
        mpz_sub(R->y, R->y, modulus);
     }
     /* Y = Y * Y */
     mpz_mul(R->y, R->y, R->y);
     mpz_mod(R->y, R->y, modulus);
     /* T2 = Y * Y */
     mpz_mul(t2, R->y, R->y);
     mpz_mod(t2, t2, modulus);
     /* T2 = T2/2 */
     if (mpz_odd_p(t2)) {
        mpz_add(t2, t2, modulus);
     }
     mpz_divexact_ui(t2, t2, 2);
     /* Y = Y * X */
     mpz_mul(R->y, R->y, R->x);
     mpz_mod(R->y, R->y, modulus);

     /* X  = T1 * T1 */
     mpz_mul(R->x, t1, t1);
     mpz_mod(R->x, R->x, modulus);
     /* X = X - Y */
     mpz_sub(R->x, R->x, R->y);
     if (mpz_cmp_ui(R->x, 0) < 0) {
        mpz_add(R->x, R->x, modulus);
     }
     /* X = X - Y */
     mpz_sub(R->x, R->x, R->y);
     if (mpz_cmp_ui(R->x, 0) < 0) {
        mpz_add(R->x, R->x, modulus);
     }

     /* Y = Y - X */
     mpz_sub(R->y, R->y, R->x);
     if (mpz_cmp_ui(R->y, 0) < 0) {
        mpz_add(R->y, R->y, modulus);
     }
     /* Y = Y * T1 */
     mpz_mul(R->y, R->y, t1);
     mpz_mod(R->y, R->y, modulus);
     /* Y = Y - T2 */
     mpz_sub(R->y, R->y, t2);
     if (mpz_cmp_ui(R->y, 0) < 0) {
        mpz_add( R->y, R->y, modulus);
     }

     err = GNUTLS_E_SUCCESS;

     mp_clear_multi(&t1, &t2, NULL);
     return err;
   } else if (err == 0) {
     /* 2*neutral = neutral */
     mpz_set_ui(R->x, 1);
     mpz_set_ui(R->y, 1);
     mpz_set_ui(R->z, 0);

     return GNUTLS_E_SUCCESS;
   } else {
     return err;
   }
}