Beispiel #1
0
// Same as above, but with affine coordinates.
static void cc_miller_no_denom_affine(element_t res, mpz_t q, element_t P,
    element_ptr Qx, element_ptr Qy) {
  mp_bitcnt_t m;
  element_t v;
  element_t Z;
  element_t a, b, c;
  element_t t0;
  element_t e0;
  const element_ptr cca = curve_a_coeff(P);
  const element_ptr Px = curve_x_coord(P);
  const element_ptr Py = curve_y_coord(P);
  element_ptr Zx, Zy;

  /* TODO: when exactly is this not needed?
  void do_vertical() {
    mapbase(e0, Z->x);
    element_sub(e0, Qx, e0);
    element_mul(v, v, e0);
  }
  */

  #define do_tangent() {                  \
    /* a = -(3 Zx^2 + cc->a) */           \
    /* b = 2 * Zy */                      \
    /* c = -(2 Zy^2 + a Zx); */           \
                                          \
    element_square(a, Zx);                \
    element_mul_si(a, a, 3);              \
    element_add(a, a, cca);               \
    element_neg(a, a);                    \
                                          \
    element_add(b, Zy, Zy);               \
                                          \
    element_mul(t0, b, Zy);               \
    element_mul(c, a, Zx);                \
    element_add(c, c, t0);                \
    element_neg(c, c);                    \
                                          \
    d_miller_evalfn(e0, a, b, c, Qx, Qy); \
    element_mul(v, v, e0);                \
  }

  #define do_line() {                                     \
    /* a = -(B.y - A.y) / (B.x - A.x); */                 \
    /* b = 1; */                                          \
    /* c = -(A.y + a * A.x); */                           \
    /* but we multiply by B.x - A.x to avoid division. */ \
                                                          \
    element_sub(b, Px, Zx);                               \
    element_sub(a, Zy, Py);                               \
    element_mul(t0, b, Zy);                               \
    element_mul(c, a, Zx);                                \
    element_add(c, c, t0);                                \
    element_neg(c, c);                                    \
                                                          \
    d_miller_evalfn(e0, a, b, c, Qx, Qy);                 \
    element_mul(v, v, e0);                                \
  }

  element_init(a, Px->field);
  element_init(b, a->field);
  element_init(c, a->field);
  element_init(t0, a->field);
  element_init(e0, res->field);

  element_init(v, res->field);
  element_init(Z, P->field);

  element_set(Z, P);
  Zx = curve_x_coord(Z);
  Zy = curve_y_coord(Z);

  element_set1(v);
  m = (mp_bitcnt_t)mpz_sizeinbase(q, 2);
  m = (m > 2 ? m - 2 : 0);

  for(;;) {
    do_tangent();

    if (!m) break;

    element_double(Z, Z);
    if (mpz_tstbit(q, m)) {
      do_line();
      element_add(Z, Z, P);
    }
    m--;
    element_square(v, v);
  }

  element_set(res, v);

  element_clear(v);
  element_clear(Z);
  element_clear(a);
  element_clear(b);
  element_clear(c);
  element_clear(t0);
  element_clear(e0);
  #undef do_tangent
  #undef do_line
}
Beispiel #2
0
static PyObject *
GMPY_mpz_lucasv_mod(PyObject *self, PyObject *args)
{
    /* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf
     * calculate v[k] (modulo n) of Lucas V sequence for p,q.
     * Note: p^2-4q=0 is not tested, not a proper Lucas sequence!!
     */

    PympzObject *result = 0, *p, *q, *k, *n;

    size_t s = 0, j = 0;
    mpz_t vl, vh, ql, qh, tmp;

    if (PyTuple_Size(args) != 4) {
        TYPE_ERROR("lucasv_mod() requires 4 integer arguments");
        return NULL;
    }

    /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to
     * avoid memory allocations. */

    mpz_inoc(vl);
    mpz_inoc(vh);
    mpz_inoc(ql);
    mpz_inoc(qh);
    mpz_inoc(tmp);

    p = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0));
    q = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1));
    k = Pympz_From_Integer(PyTuple_GET_ITEM(args, 2));
    n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 3));
    if (!p || !q || !k || !n) {
        TYPE_ERROR("lucasv_mod() requires 4 integer arguments");
        goto cleanup;
    }

    /* Check if p*p - 4*q == 0. */

    mpz_mul(tmp, p->z, p->z);
    mpz_mul_ui(qh, q->z, 4);
    mpz_sub(tmp, tmp, qh);
    if (mpz_sgn(tmp) == 0) {
        VALUE_ERROR("invalid values for p,q in lucasv_mod()");
        goto cleanup;
    }

    /* Check if k < 0. */

    if (mpz_sgn(k->z) < 0) {
        VALUE_ERROR("invalid value for k in lucasv_mod()");
        goto cleanup;
    }

    /* Check if n > 0. */

    if (mpz_sgn(n->z) <= 0) {
        VALUE_ERROR("invalid value for n in lucasv_mod()");
        goto cleanup;
    }

    mpz_set_si(vl, 2);
    mpz_set(vh, p->z);
    mpz_set_si(ql, 1);
    mpz_set_si(qh, 1);
    mpz_set_si(tmp,0);

    s = mpz_scan1(k->z, 0);
    for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) {
        /* ql = ql*qh (mod n) */
        mpz_mul(ql, ql, qh);
        mpz_mod(ql, ql, n->z);
        if (mpz_tstbit(k->z,j) == 1) {
            /* qh = ql*q */
            mpz_mul(qh, ql, q->z);

            /* vl = vh*vl - p*ql (mod n) */
            mpz_mul(vl, vh, vl);
            mpz_mul(tmp, ql, p->z);
            mpz_sub(vl, vl, tmp);
            mpz_mod(vl, vl, n->z);

            /* vh = vh*vh - 2*qh (mod n) */
            mpz_mul(vh, vh, vh);
            mpz_mul_si(tmp, qh, 2);
            mpz_sub(vh, vh, tmp);
            mpz_mod(vh, vh, n->z);
        }
        else {
            /* qh = ql */
            mpz_set(qh, ql);

            /* vh = vh*vl - p*ql (mod n) */
            mpz_mul(vh, vh, vl);
            mpz_mul(tmp, ql, p->z);
            mpz_sub(vh, vh, tmp);
            mpz_mod(vh, vh, n->z);

            /* vl = vl*vl - 2*ql (mod n) */
            mpz_mul(vl, vl, vl);
            mpz_mul_si(tmp, ql, 2);
            mpz_sub(vl, vl, tmp);
            mpz_mod(vl, vl, n->z);
        }
    }
    /* ql = ql*qh */
    mpz_mul(ql, ql, qh);

    /* qh = ql*q */
    mpz_mul(qh, ql, q->z);

    /* vl = vh*vl - p*ql */
    mpz_mul(vl, vh, vl);
    mpz_mul(tmp, ql, p->z);
    mpz_sub(vl, vl, tmp);

    /* ql = ql*qh */
    mpz_mul(ql, ql, qh);

    for (j = 1; j <= s; j++) {
        /* vl = vl*vl - 2*ql (mod n) */
        mpz_mul(vl, vl, vl);
        mpz_mul_si(tmp, ql, 2);
        mpz_sub(vl, vl, tmp);
        mpz_mod(vl, vl, n->z);

        /* ql = ql*ql (mod n) */
        mpz_mul(ql, ql, ql);
        mpz_mod(ql, ql, n->z);
    }

    if (!(result = (PympzObject*)Pympz_new()))
        goto cleanup;

    /* vl contains our return value */
    mpz_mod(result->z, vl, n->z);

  cleanup:
    mpz_cloc(vl);
    mpz_cloc(vh);
    mpz_cloc(ql);
    mpz_cloc(qh);
    mpz_cloc(tmp);
    Py_XDECREF((PyObject*)p);
    Py_XDECREF((PyObject*)q);
    Py_XDECREF((PyObject*)k);
    Py_XDECREF((PyObject*)n);

    return (PyObject*)result;
}
// scalar multiplication on Surf127_735.
// key is 4 limb long.
void KSmul(mpfq_p_127_735_field k, dst_KSpoint res, src_KSpoint P, mpz_t key,
    src_KSparam KS) {
  KSpoint Pm, Pp;
  mpfq_p_127_735_elt tmpy, tmpz, tmpt;
  mpfq_p_127_735_elt YY, ZZ, TT;
  KSpoint_struct *pm, *pp, *tmp;
  int i, l;

  if (mpz_cmp_ui(key, 0)==0) {
    // implement me!
    assert (0);
  }

  if (mpz_cmp_ui(key, 1)==0) {
    KScopy(k, res, P);
    return;
  }

  KSinit(k, Pm); KSinit(k, Pp);
  KScopy(k, Pm, P);
  KSdouble(k, Pp, Pm, KS);

  if (mpz_cmp_ui(key, 2)==0) {
    KScopy(k, res, Pp);
    KSclear(k, Pm);
    KSclear(k, Pp);
    return;
  }

  mpfq_p_127_735_init(k, &tmpy);
  mpfq_p_127_735_init(k, &tmpz);
  mpfq_p_127_735_init(k, &tmpt);

  mpfq_p_127_735_init(k, &YY);
  mpfq_p_127_735_init(k, &ZZ);
  mpfq_p_127_735_init(k, &TT);

  mpfq_p_127_735_mul(k, tmpy, P->y, P->z);
  mpfq_p_127_735_mul(k, tmpz, tmpy, P->t);
  mpfq_p_127_735_inv(k, tmpz, tmpz);
  mpfq_p_127_735_mul(k, tmpz, tmpz, P->x);
  mpfq_p_127_735_mul(k, TT, tmpz, tmpy); // x/t
  mpfq_p_127_735_mul(k, tmpy, P->z, P->t);
  mpfq_p_127_735_mul(k, YY, tmpz, tmpy); // x/y
  mpfq_p_127_735_mul(k, tmpy, P->y, P->t);
  mpfq_p_127_735_mul(k, ZZ, tmpz, tmpy); // x/z

  // initialize loop
  pm = Pm;
  pp = Pp;

  // loop
  l = mpz_sizeinbase(key, 2);
  assert (mpz_tstbit(key, l-1) == 1);
  for (i = l-2; i >= 0; --i) {
    int swap;
    swap = (mpz_tstbit(key, i) == 1);
    if (swap) {
      tmp = pp; pp = pm; pm = tmp;
    }
    // pseudo add(pm, pp)  -> pp  ;   dble(pm) -> pm
    // Total: 32A + 16P + 9S

    KShadamard(k, pm);					// 8A
    mpfq_p_127_735_mul(k, tmpy, pm->y, KS->y0p);	
    mpfq_p_127_735_mul(k, tmpz, pm->z, KS->z0p);
    mpfq_p_127_735_mul(k, tmpt, pm->t, KS->t0p);	// 3P
    
    KShadamard(k, pp);					// 8A

    mpfq_p_127_735_mul(k, pp->x, pp->x, pm->x);
    mpfq_p_127_735_mul(k, pp->y, pp->y, tmpy);
    mpfq_p_127_735_mul(k, pp->z, pp->z, tmpz);
    mpfq_p_127_735_mul(k, pp->t, pp->t, tmpt);		// 4P
    
    KShadamard(k, pp);					// 8A

    mpfq_p_127_735_sqr(k, pp->x, pp->x);
    mpfq_p_127_735_sqr(k, pp->y, pp->y);
    mpfq_p_127_735_sqr(k, pp->z, pp->z);
    mpfq_p_127_735_sqr(k, pp->t, pp->t);		// 4S

    mpfq_p_127_735_mul(k, pp->y, pp->y, YY);
    mpfq_p_127_735_mul(k, pp->z, pp->z, ZZ);
    mpfq_p_127_735_mul(k, pp->t, pp->t, TT);		// 3P

    mpfq_p_127_735_sqr(k, pm->x, pm->x);		// 1S

    mpfq_p_127_735_mul(k, pm->y, pm->y, tmpy); 
    mpfq_p_127_735_mul(k, pm->z, pm->z, tmpz);
    mpfq_p_127_735_mul(k, pm->t, pm->t, tmpt);		// 3P

    KShadamard(k, pm);					// 8A
    
    mpfq_p_127_735_sqr(k, pm->x, pm->x);
    mpfq_p_127_735_sqr(k, pm->y, pm->y); 
    mpfq_p_127_735_sqr(k, pm->z, pm->z);
    mpfq_p_127_735_sqr(k, pm->t, pm->t);		// 4S

    mpfq_p_127_735_mul(k, pm->y, pm->y, KS->y0);
    mpfq_p_127_735_mul(k, pm->z, pm->z, KS->z0);
    mpfq_p_127_735_mul(k, pm->t, pm->t, KS->t0);	// 3P
    if (swap) {
      tmp = pp; pp = pm; pm = tmp;
    }
  }

  KScopy(k, res, pm);
  KSclear(k, Pm);
  KSclear(k, Pp);
 
  mpfq_p_127_735_clear(k, &YY);
  mpfq_p_127_735_clear(k, &ZZ);
  mpfq_p_127_735_clear(k, &TT);
  mpfq_p_127_735_clear(k, &tmpy);
  mpfq_p_127_735_clear(k, &tmpz);
  mpfq_p_127_735_clear(k, &tmpt);
}
Beispiel #4
0
int
rsa_generate_keypair(struct rsa_public_key *pub,
		     struct rsa_private_key *key,
		     void *random_ctx, nettle_random_func *random,
		     void *progress_ctx, nettle_progress_func *progress,
		     unsigned n_size,
		     unsigned e_size)
{
  mpz_t p1;
  mpz_t q1;
  mpz_t phi;
  mpz_t tmp;

  if (e_size)
    {
      /* We should choose e randomly. Is the size reasonable? */
      if ((e_size < 16) || (e_size >= n_size) )
	return 0;
    }
  else
    {
      /* We have a fixed e. Check that it makes sense */

      /* It must be odd */
      if (!mpz_tstbit(pub->e, 0))
	return 0;

      /* And 3 or larger */
      if (mpz_cmp_ui(pub->e, 3) < 0)
	return 0;

      /* And size less than n */
      if (mpz_sizeinbase(pub->e, 2) >= n_size)
	return 0;
    }

  if (n_size < RSA_MINIMUM_N_BITS)
    return 0;
  
  mpz_init(p1); mpz_init(q1); mpz_init(phi); mpz_init(tmp);

  /* Generate primes */
  for (;;)
    {
      /* Generate p, such that gcd(p-1, e) = 1 */
      for (;;)
	{
	  nettle_random_prime(key->p, (n_size+1)/2, 1,
			      random_ctx, random,
			      progress_ctx, progress);

	  mpz_sub_ui(p1, key->p, 1);
      
	  /* If e was given, we must chose p such that p-1 has no factors in
	   * common with e. */
	  if (e_size)
	    break;
	  
	  mpz_gcd(tmp, pub->e, p1);

	  if (mpz_cmp_ui(tmp, 1) == 0)
	    break;
	  else if (progress) progress(progress_ctx, 'c');
	} 

      if (progress)
	progress(progress_ctx, '\n');
      
      /* Generate q, such that gcd(q-1, e) = 1 */
      for (;;)
	{
	  nettle_random_prime(key->q, n_size/2, 1,
			      random_ctx, random,
			      progress_ctx, progress);

	  /* Very unlikely. */
	  if (mpz_cmp (key->q, key->p) == 0)
	    continue;

	  mpz_sub_ui(q1, key->q, 1);
      
	  /* If e was given, we must chose q such that q-1 has no factors in
	   * common with e. */
	  if (e_size)
	    break;
	  
	  mpz_gcd(tmp, pub->e, q1);

	  if (mpz_cmp_ui(tmp, 1) == 0)
	    break;
	  else if (progress) progress(progress_ctx, 'c');
	}

      /* Now we have the primes. Is the product of the right size? */
      mpz_mul(pub->n, key->p, key->q);

      assert (mpz_sizeinbase(pub->n, 2) == n_size);

      if (progress)
	progress(progress_ctx, '\n');

      /* c = q^{-1} (mod p) */
      if (mpz_invert(key->c, key->q, key->p))
	/* This should succeed everytime. But if it doesn't,
	 * we try again. */
	break;
      else if (progress) progress(progress_ctx, '?');
    }

  mpz_mul(phi, p1, q1);
  
  /* If we didn't have a given e, generate one now. */
  if (e_size)
    {
      int retried = 0;
      for (;;)
	{
	  nettle_mpz_random_size(pub->e,
				 random_ctx, random,
				 e_size);
	
	  /* Make sure it's odd and that the most significant bit is
	   * set */
	  mpz_setbit(pub->e, 0);
	  mpz_setbit(pub->e, e_size - 1);

	  /* Needs gmp-3, or inverse might be negative. */
	  if (mpz_invert(key->d, pub->e, phi))
	    break;

	  if (progress) progress(progress_ctx, 'e');
	  retried = 1;
	}
      if (retried && progress)
	progress(progress_ctx, '\n');	
    }
  else
    {
      /* Must always succeed, as we already that e
       * doesn't have any common factor with p-1 or q-1. */
      int res = mpz_invert(key->d, pub->e, phi);
      assert(res);
    }

  /* Done! Almost, we must compute the auxillary private values. */
  /* a = d % (p-1) */
  mpz_fdiv_r(key->a, key->d, p1);

  /* b = d % (q-1) */
  mpz_fdiv_r(key->b, key->d, q1);

  /* c was computed earlier */

  pub->size = key->size = (n_size + 7) / 8;
  assert(pub->size >= RSA_MINIMUM_N_OCTETS);
  
  mpz_clear(p1); mpz_clear(q1); mpz_clear(phi); mpz_clear(tmp);

  return 1;
}
Beispiel #5
0
static int
mpfr_rem1 (mpfr_ptr rem, long *quo, mpfr_rnd_t rnd_q,
           mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd)
{
  mpfr_exp_t ex, ey;
  int compare, inex, q_is_odd, sign, signx = MPFR_SIGN (x);
  mpz_t mx, my, r;
  int tiny = 0;

  MPFR_ASSERTD (rnd_q == MPFR_RNDN || rnd_q == MPFR_RNDZ);

  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x) || MPFR_IS_SINGULAR (y)))
    {
      if (MPFR_IS_NAN (x) || MPFR_IS_NAN (y) || MPFR_IS_INF (x)
          || MPFR_IS_ZERO (y))
        {
          /* for remquo, quo is undefined */
          MPFR_SET_NAN (rem);
          MPFR_RET_NAN;
        }
      else                      /* either y is Inf and x is 0 or non-special,
                                   or x is 0 and y is non-special,
                                   in both cases the quotient is zero. */
        {
          if (quo)
            *quo = 0;
          return mpfr_set (rem, x, rnd);
        }
    }

  /* now neither x nor y is NaN, Inf or zero */

  mpz_init (mx);
  mpz_init (my);
  mpz_init (r);

  ex = mpfr_get_z_2exp (mx, x);  /* x = mx*2^ex */
  ey = mpfr_get_z_2exp (my, y);  /* y = my*2^ey */

  /* to get rid of sign problems, we compute it separately:
     quo(-x,-y) = quo(x,y), rem(-x,-y) = -rem(x,y)
     quo(-x,y) = -quo(x,y), rem(-x,y)  = -rem(x,y)
     thus quo = sign(x/y)*quo(|x|,|y|), rem = sign(x)*rem(|x|,|y|) */
  sign = (signx == MPFR_SIGN (y)) ? 1 : -1;
  mpz_abs (mx, mx);
  mpz_abs (my, my);
  q_is_odd = 0;

  /* divide my by 2^k if possible to make operations mod my easier */
  {
    unsigned long k = mpz_scan1 (my, 0);
    ey += k;
    mpz_fdiv_q_2exp (my, my, k);
  }

  if (ex <= ey)
    {
      /* q = x/y = mx/(my*2^(ey-ex)) */

      /* First detect cases where q=0, to avoid creating a huge number
         my*2^(ey-ex): if sx = mpz_sizeinbase (mx, 2) and sy =
         mpz_sizeinbase (my, 2), we have x < 2^(ex + sx) and
         y >= 2^(ey + sy - 1), thus if ex + sx <= ey + sy - 1
         the quotient is 0 */
      if (ex + (mpfr_exp_t) mpz_sizeinbase (mx, 2) <
          ey + (mpfr_exp_t) mpz_sizeinbase (my, 2))
        {
          tiny = 1;
          mpz_set (r, mx);
          mpz_set_ui (mx, 0);
        }
      else
        {
          mpz_mul_2exp (my, my, ey - ex);   /* divide mx by my*2^(ey-ex) */

          /* since mx > 0 and my > 0, we can use mpz_tdiv_qr in all cases */
          mpz_tdiv_qr (mx, r, mx, my);
          /* 0 <= |r| <= |my|, r has the same sign as mx */
        }

      if (rnd_q == MPFR_RNDN)
        q_is_odd = mpz_tstbit (mx, 0);
      if (quo)                  /* mx is the quotient */
        {
          mpz_tdiv_r_2exp (mx, mx, WANTED_BITS);
          *quo = mpz_get_si (mx);
        }
    }
  else                          /* ex > ey */
    {
      if (quo) /* remquo case */
        /* for remquo, to get the low WANTED_BITS more bits of the quotient,
           we first compute R =  X mod Y*2^WANTED_BITS, where X and Y are
           defined below. Then the low WANTED_BITS of the quotient are
           floor(R/Y). */
        mpz_mul_2exp (my, my, WANTED_BITS);     /* 2^WANTED_BITS*Y */

      else if (rnd_q == MPFR_RNDN) /* remainder case */
        /* Let X = mx*2^(ex-ey) and Y = my. Then both X and Y are integers.
           Assume X = R mod Y, then x = X*2^ey = R*2^ey mod (Y*2^ey=y).
           To be able to perform the rounding, we need the least significant
           bit of the quotient, i.e., one more bit in the remainder,
           which is obtained by dividing by 2Y. */
        mpz_mul_2exp (my, my, 1);       /* 2Y */

      mpz_set_ui (r, 2);
      mpz_powm_ui (r, r, ex - ey, my);  /* 2^(ex-ey) mod my */
      mpz_mul (r, r, mx);
      mpz_mod (r, r, my);

      if (quo)                  /* now 0 <= r < 2^WANTED_BITS*Y */
        {
          mpz_fdiv_q_2exp (my, my, WANTED_BITS);   /* back to Y */
          mpz_tdiv_qr (mx, r, r, my);
          /* oldr = mx*my + newr */
          *quo = mpz_get_si (mx);
          q_is_odd = *quo & 1;
        }
      else if (rnd_q == MPFR_RNDN) /* now 0 <= r < 2Y in the remainder case */
        {
          mpz_fdiv_q_2exp (my, my, 1);     /* back to Y */
          /* least significant bit of q */
          q_is_odd = mpz_cmpabs (r, my) >= 0;
          if (q_is_odd)
            mpz_sub (r, r, my);
        }
      /* now 0 <= |r| < |my|, and if needed,
         q_is_odd is the least significant bit of q */
    }

  if (mpz_cmp_ui (r, 0) == 0)
    {
      inex = mpfr_set_ui (rem, 0, MPFR_RNDN);
      /* take into account sign of x */
      if (signx < 0)
        mpfr_neg (rem, rem, MPFR_RNDN);
    }
  else
    {
      if (rnd_q == MPFR_RNDN)
        {
          /* FIXME: the comparison 2*r < my could be done more efficiently
             at the mpn level */
          mpz_mul_2exp (r, r, 1);
          /* if tiny=1, we should compare r with my*2^(ey-ex) */
          if (tiny)
            {
              if (ex + (mpfr_exp_t) mpz_sizeinbase (r, 2) <
                  ey + (mpfr_exp_t) mpz_sizeinbase (my, 2))
                compare = 0; /* r*2^ex < my*2^ey */
              else
                {
                  mpz_mul_2exp (my, my, ey - ex);
                  compare = mpz_cmpabs (r, my);
                }
            }
          else
            compare = mpz_cmpabs (r, my);
          mpz_fdiv_q_2exp (r, r, 1);
          compare = ((compare > 0) ||
                     ((rnd_q == MPFR_RNDN) && (compare == 0) && q_is_odd));
          /* if compare != 0, we need to subtract my to r, and add 1 to quo */
          if (compare)
            {
              mpz_sub (r, r, my);
              if (quo && (rnd_q == MPFR_RNDN))
                *quo += 1;
            }
        }
      /* take into account sign of x */
      if (signx < 0)
        mpz_neg (r, r);
      inex = mpfr_set_z_2exp (rem, r, ex > ey ? ey : ex, rnd);
    }

  if (quo)
    *quo *= sign;

  mpz_clear (mx);
  mpz_clear (my);
  mpz_clear (r);

  return inex;
}
//~ Note: Here, (N, T, c) = (1, 0, 0)
//~ Also, 'rop' is supposed to be already initialised (see glv_scalar.h)
void build_glvScalar(GLVScalar *rop, mpz_t k3, mpz_t aa, mpz_t bb, mpz_t Na){
	
	int j;
	mpz_t x1, x2, y1, y2, k1, k2;
	mpz_inits (x1, x2, y1, y2, k1, k2, NULL);


	mpz_mul (x1, k3, aa);
	mpz_mul (x2, k3, bb);
	mpz_neg (x2, x2);

	mpz_fdiv_q (y1, x1, Na);
	mpz_fdiv_q (y2, x2, Na);
	
	
	mpz_mul (x1, bb, y2);
	mpz_mul (k1, aa, y1);
	mpz_sub (k1, k1, x1);
	mpz_sub (k1, k3, k1);
	
	mpz_mul (x2, aa, y2);
	mpz_mul (k2, bb, y1);
	mpz_add (k2, k2, x2);
	mpz_neg (k2, k2);
	
	

	j = 0;
	while((mpz_cmp_ui (k1, 0)!=0) || (mpz_cmp_ui (k2, 0)!=0)){
		if(mpz_tstbit (k1, 0)) rop->tk1[j] = 1;
		if(mpz_tstbit (k2, 0)) rop->tk2[j] = 1;
		
		if((rop->tk1[j]==1) && (rop->tk2[j]==1)){
			if(mpz_tstbit (k1, 1)) rop->tk1[j] = -1;
			if(mpz_tstbit (k2, 1)) rop->tk2[j] = -1;
		}
		else if(rop->tk1[j] != rop->tk2[j]){
			if(mpz_tstbit (k1, 1) != mpz_tstbit (k2, 1)){
				rop->tk1[j] = -(rop->tk1[j]); 
				rop->tk2[j] = -(rop->tk2[j]);
			}
		}
		
		if(rop->tk1[j] == 1)
			mpz_sub_ui (k1, k1, 1);
		else if(rop->tk1[j] == -1)
			mpz_add_ui (k1, k1, 1);
		
		//~ Correspond to shiftRight(1)
		mpz_clrbit (k1, 0);
		mpz_divexact_ui (k1, k1, 2);
		
		if(rop->tk2[j] == 1)
			mpz_sub_ui (k2, k2, 1);
		else if(rop->tk2[j] == -1)
			mpz_add_ui (k2, k2, 1);
		
		//~ Correspond to shiftRight(1)
		mpz_clrbit (k2, 0);
		mpz_divexact_ui (k2, k2, 2);
		
		j +=1;
	}
	j -=1;

	rop->j = j;

	mpz_clears (x1, x2, y1, y2, k1, k2, NULL);
}
Beispiel #7
0
int genrsa(char* priv_out, char* pub_out)
{
	/*TODO: How will the numbers chosen be of "similar bit length" ?
	 */
		mpz_t p, q, n, phi, decp, decq, e, d, c, m, t , m2, res, k, qinverseModP, exponent1, exponent2;
		gmp_randstate_t randomState;
		int isPrimeP = 0, isPrimeQ = 0,  extraOctetAdded, numOctetsAdded = 0,  totalLength = 0, levelLength = 0;
		int* pubKeyBuf = (int*)malloc(PUB_KEY_BUF_LEN* sizeof(int));
		int* privKeyBuf = (int*)malloc(PRIV_KEY_BUF_LEN* sizeof(int));
		int priv_key_ptr = PRIV_KEY_BUF_LEN - 1;
		int pub_key_ptr = PUB_KEY_BUF_LEN - 1;
		int len_e_octets = E_NUM_BITS / 8;
		//initialising random values
		mpz_init(p);
		
		mpz_init(qinverseModP);
		mpz_init(exponent1);
		mpz_init(exponent2);
		mpz_init(k);
		mpz_init(m);
		mpz_init(c);
		mpz_init(res);
		mpz_init(q);
		mpz_init(n);
		mpz_init(t);
		mpz_init(m2);
		mpz_init(decp);
		mpz_init(decq);
		mpz_init(phi);
		mpz_init(e);
		mpz_init(d);
		mpz_init_set_si(e, 65537L);
		mpz_init_set_si(m , 5L);
		mpz_init_set_si(m2 , 5L);
		//seeding random value
		gmp_randinit_default(randomState);
		gmp_randseed_ui(randomState, time(0));
		int foundE = 0;

		while(!foundE)
		{
		//generatnig primes
			do
			{
				mpz_urandomb(p, randomState ,RSA_NUM_BITS);
				isPrimeP = mpz_probab_prime_p(p, 10);
			}
			while(!isPrimeP);
			
			do
			{
				mpz_urandomb(q, randomState ,RSA_NUM_BITS);
				isPrimeQ = mpz_probab_prime_p(q, 10);
			}
			while(!isPrimeQ);
			
			//p*q
			mpz_mul(n , p , q);
			
			//Assures that we have 1024 bit key
			if(mpz_tstbit(n, N_NUM_BITS - 1) == 0) continue;
			#if DEBUG
				mpz_out_str(NULL, 10, p);
				printf("\n");
				mpz_out_str(NULL, 10, q);
				printf("\n");
				mpz_out_str(NULL, 10, n);
				printf("\n");
				mpz_out_str(NULL, 10, decp);
				printf("\n");
				mpz_out_str(NULL, 10, decq);
				printf("\n");
			#endif
			
			//p - 1
			mpz_sub_ui(decp, p, 1);
			
			// q - 1 
			mpz_sub_ui(decq, q, 1);
			
			//Euler's totient function
			mpz_mul(phi, decp, decq);
			
			
			foundE = applyExtendedEuclid(e, phi, d);

			
			#if DEBUG
				mpz_out_str(NULL, 10, e);
				printf("\n");
				mpz_out_str(NULL, 10, d);
				printf("\n");
			#endif
			
			if(mpz_cmp_si(d, 0L) < 0)
			{
				mpz_add(d, phi, d);
			}
		
		}
				#if DEBUG
			printf("Positive D\n");
			mpz_out_str(NULL, 10, d);
			printf("\n");
		#endif
		//encrypt(m, e, c, n);
		
	//	mpz_powm(res, m2 ,e, n);
		
		#if DEBUG
			printf("Cipher1\n");
			mpz_out_str(NULL, 10, c);
			
			printf("Cipher2\n");
			mpz_out_str(NULL, 10, res);
			
			
			printf("\n");
		#endif
	//	mpz_init_set(k, c);
		
		//encrypt(c, d, t, n); 
		
	//	mpz_powm(res, k ,d, n);
		#if DEBUG
			printf("dec\n");
			mpz_out_str(NULL, 10, t);
			printf("\n");
			//printf("dec 2\n");
			//mpz_out_str(NULL, 10, res);
		#endif

		//Adding E
		{
			addEToPublicKeyBuffer(e, pubKeyBuf, &pub_key_ptr);
			totalLength = len_e_octets;
			
			numOctetsAdded = appendLengthToBuffer(len_e_octets, pubKeyBuf, &pub_key_ptr);
			totalLength+= numOctetsAdded;
			
			appendIdentifierOctet(TAG_INT, PRIMITIVE, UNIVERSAL, pubKeyBuf, &pub_key_ptr);
			totalLength++;
			
			extraOctetAdded = addMpz_tToBuffer(n, pubKeyBuf, &pub_key_ptr, N_NUM_BITS);
			totalLength = totalLength + (N_NUM_BITS/8) + extraOctetAdded ;
			
			numOctetsAdded = appendLengthToBuffer( ( (N_NUM_BITS/8) + extraOctetAdded ) , pubKeyBuf, &pub_key_ptr);
			totalLength+= numOctetsAdded;
			
			appendIdentifierOctet(TAG_INT, PRIMITIVE, UNIVERSAL, pubKeyBuf, &pub_key_ptr);
			totalLength++;
			
			numOctetsAdded = appendLengthToBuffer( totalLength , pubKeyBuf, &pub_key_ptr);
			totalLength+= numOctetsAdded;
			
			appendIdentifierOctet(TAG_SEQUENCE, CONSTRUCTED, UNIVERSAL, pubKeyBuf, &pub_key_ptr);
			totalLength++;
			
			//An octet of 00 is added always, since the content always has multiple of 8 bits, so unused bits is 0
			addNullOctet(pubKeyBuf, &pub_key_ptr);
			totalLength++;
			
			numOctetsAdded = appendLengthToBuffer( totalLength , pubKeyBuf, &pub_key_ptr);
			totalLength+= numOctetsAdded;
			
			appendIdentifierOctet(TAG_BIT_STRING, PRIMITIVE, UNIVERSAL, pubKeyBuf, &pub_key_ptr);
			totalLength++;
		
		addUsualPublicKeyHeaders(pubKeyBuf, &pub_key_ptr, &totalLength);
		// The Key is contained within the pubKeyBuf at this stage
		
		writeKeyBuffer(pub_out, pubKeyBuf, pub_key_ptr +1, PUB_KEY_BUF_LEN);
		
		free(pubKeyBuf);
		}
		
		//printf("Total octets %d", totalLength);
		
		{
				totalLength = 0;
				mpz_invert (qinverseModP, q, p);
				
				//Adding q^-1 mod p
				extraOctetAdded = addMpz_tToBuffer(qinverseModP, privKeyBuf, &priv_key_ptr, RSA_NUM_BITS);
				levelLength = (RSA_NUM_BITS/8) + extraOctetAdded ;
				totalLength+= levelLength;
				numOctetsAdded = appendLengthToBuffer(levelLength, privKeyBuf, &priv_key_ptr);
				totalLength+=numOctetsAdded;
				appendIdentifierOctet(TAG_INT, PRIMITIVE, UNIVERSAL, privKeyBuf, &priv_key_ptr);
				totalLength++;
				
				mpz_mod(exponent1, d, decp);
				mpz_mod(exponent2, d, decq);
				
				//Adding exponent2
				extraOctetAdded = addMpz_tToBuffer(exponent2, privKeyBuf, &priv_key_ptr, RSA_NUM_BITS);
				levelLength = (RSA_NUM_BITS/8) + extraOctetAdded ;
				totalLength+= levelLength;
				
				numOctetsAdded = appendLengthToBuffer(levelLength, privKeyBuf, &priv_key_ptr);
				totalLength+=numOctetsAdded;
				appendIdentifierOctet(TAG_INT, PRIMITIVE, UNIVERSAL, privKeyBuf, &priv_key_ptr);
				totalLength++;
				
				//Adding exponent1
				extraOctetAdded = addMpz_tToBuffer(exponent1, privKeyBuf, &priv_key_ptr, RSA_NUM_BITS);
				levelLength = (RSA_NUM_BITS/8) + extraOctetAdded ;
				totalLength+= levelLength;
				
				numOctetsAdded = appendLengthToBuffer(levelLength, privKeyBuf, &priv_key_ptr);
				totalLength+=numOctetsAdded;
				appendIdentifierOctet(TAG_INT, PRIMITIVE, UNIVERSAL, privKeyBuf, &priv_key_ptr);
				totalLength++;
				
				//Adding prime2
				extraOctetAdded = addMpz_tToBuffer(q, privKeyBuf, &priv_key_ptr, RSA_NUM_BITS);
				levelLength = (RSA_NUM_BITS/8) + extraOctetAdded ;
				totalLength+= levelLength;
				
				numOctetsAdded = appendLengthToBuffer(levelLength, privKeyBuf, &priv_key_ptr);
				totalLength+=numOctetsAdded;
				appendIdentifierOctet(TAG_INT, PRIMITIVE, UNIVERSAL, privKeyBuf, &priv_key_ptr);
				totalLength++;
				
				//Adding prime1
				extraOctetAdded = addMpz_tToBuffer(p, privKeyBuf, &priv_key_ptr, RSA_NUM_BITS);
				levelLength = (RSA_NUM_BITS/8) + extraOctetAdded ;
				totalLength+= levelLength;
				
				numOctetsAdded = appendLengthToBuffer(levelLength, privKeyBuf, &priv_key_ptr);
				totalLength+=numOctetsAdded;
				appendIdentifierOctet(TAG_INT, PRIMITIVE, UNIVERSAL, privKeyBuf, &priv_key_ptr);
				totalLength++;
				
				//Adding d
				extraOctetAdded = addMpz_tToBuffer(d, privKeyBuf, &priv_key_ptr, N_NUM_BITS);
				levelLength = (N_NUM_BITS/8) + extraOctetAdded ;
				totalLength+= levelLength;
				
				numOctetsAdded = appendLengthToBuffer(levelLength, privKeyBuf, &priv_key_ptr);
				totalLength+=numOctetsAdded;
				appendIdentifierOctet(TAG_INT, PRIMITIVE, UNIVERSAL, privKeyBuf, &priv_key_ptr);
				totalLength++;
				
				//Adding e
				extraOctetAdded = addMpz_tToBuffer(e, privKeyBuf, &priv_key_ptr, E_NUM_BITS);
				levelLength = (E_NUM_BITS/8) + extraOctetAdded ;
				totalLength+= levelLength;
				
				numOctetsAdded = appendLengthToBuffer(levelLength, privKeyBuf, &priv_key_ptr);
				totalLength+=numOctetsAdded;
				appendIdentifierOctet(TAG_INT, PRIMITIVE, UNIVERSAL, privKeyBuf, &priv_key_ptr);
				totalLength++;
				
				//Adding n
				extraOctetAdded = addMpz_tToBuffer(n, privKeyBuf, &priv_key_ptr, N_NUM_BITS);
				levelLength = (N_NUM_BITS/8) + extraOctetAdded ;
				totalLength+= levelLength;
				
				numOctetsAdded = appendLengthToBuffer(levelLength, privKeyBuf, &priv_key_ptr);
				totalLength+=numOctetsAdded;
				appendIdentifierOctet(TAG_INT, PRIMITIVE, UNIVERSAL, privKeyBuf, &priv_key_ptr);
				totalLength++;
				
				//Appending version - 0
				addNullOctet(privKeyBuf, &priv_key_ptr);
				totalLength++;
				numOctetsAdded = appendLengthToBuffer(1, privKeyBuf, &priv_key_ptr);
				totalLength+=numOctetsAdded;
				appendIdentifierOctet(TAG_INT, PRIMITIVE, UNIVERSAL, privKeyBuf, &priv_key_ptr);
				totalLength++;
				
				numOctetsAdded = appendLengthToBuffer(totalLength, privKeyBuf, &priv_key_ptr);
				appendIdentifierOctet(TAG_SEQUENCE, CONSTRUCTED, UNIVERSAL, privKeyBuf, &priv_key_ptr);
				
				writeKeyBuffer(priv_out, privKeyBuf, priv_key_ptr +1, PRIV_KEY_BUF_LEN);
				free(privKeyBuf);

		}
		//writeSampleFile();
		//free this somewhere
		
		return 0;
}
Beispiel #8
0
/* return in z a lower bound (for rnd = RNDD) or upper bound (for rnd = RNDU)
   of |zeta(s)|/2, using:
   log(|zeta(s)|/2) = (s-1)*log(2*Pi) + lngamma(1-s)
   + log(|sin(Pi*s/2)| * zeta(1-s)).
   Assumes s < 1/2 and s1 = 1-s exactly, thus s1 > 1/2.
   y and p are temporary variables.
   At input, p is Pi rounded down.
   The comments in the code are for rnd = RNDD. */
static void
mpfr_reflection_overflow (mpfr_t z, mpfr_t s1, const mpfr_t s, mpfr_t y,
                          mpfr_t p, mpfr_rnd_t rnd)
{
  mpz_t sint;

  MPFR_ASSERTD (rnd == MPFR_RNDD || rnd == MPFR_RNDU);

  /* Since log is increasing, we want lower bounds on |sin(Pi*s/2)| and
     zeta(1-s). */
  mpz_init (sint);
  mpfr_get_z (sint, s, MPFR_RNDD); /* sint = floor(s) */
  /* We first compute a lower bound of |sin(Pi*s/2)|, which is a periodic
     function of period 2. Thus:
     if 2k < s < 2k+1, then |sin(Pi*s/2)| is increasing;
     if 2k-1 < s < 2k, then |sin(Pi*s/2)| is decreasing.
     These cases are distinguished by testing bit 0 of floor(s) as if
     represented in two's complement (or equivalently, as an unsigned
     integer mod 2):
     0: sint = 0 mod 2, thus 2k < s < 2k+1 and |sin(Pi*s/2)| is increasing;
     1: sint = 1 mod 2, thus 2k-1 < s < 2k and |sin(Pi*s/2)| is decreasing.
     Let's recall that the comments are for rnd = RNDD. */
  if (mpz_tstbit (sint, 0) == 0) /* |sin(Pi*s/2)| is increasing: round down
                                    Pi*s to get a lower bound. */
    {
      mpfr_mul (y, p, s, rnd);
      if (rnd == MPFR_RNDD)
        mpfr_nextabove (p); /* we will need p rounded above afterwards */
    }
  else /* |sin(Pi*s/2)| is decreasing: round up Pi*s to get a lower bound. */
    {
      if (rnd == MPFR_RNDD)
        mpfr_nextabove (p);
      mpfr_mul (y, p, s, MPFR_INVERT_RND(rnd));
    }
  mpfr_div_2ui (y, y, 1, MPFR_RNDN); /* exact, rounding mode doesn't matter */
  /* The rounding direction of sin depends on its sign. We have:
     if -4k-2 < s < -4k, then -2k-1 < s/2 < -2k, thus sin(Pi*s/2) < 0;
     if -4k < s < -4k+2, then -2k < s/2 < -2k+1, thus sin(Pi*s/2) > 0.
     These cases are distinguished by testing bit 1 of floor(s) as if
     represented in two's complement (or equivalently, as an unsigned
     integer mod 4):
     0: sint = {0,1} mod 4, thus -2k < s/2 < -2k+1 and sin(Pi*s/2) > 0;
     1: sint = {2,3} mod 4, thus -2k-1 < s/2 < -2k and sin(Pi*s/2) < 0.
     Let's recall that the comments are for rnd = RNDD. */
  if (mpz_tstbit (sint, 1) == 0) /* -2k < s/2 < -2k+1; sin(Pi*s/2) > 0 */
    {
      /* Round sin down to get a lower bound of |sin(Pi*s/2)|. */
      mpfr_sin (y, y, rnd);
    }
  else /* -2k-1 < s/2 < -2k; sin(Pi*s/2) < 0 */
    {
      /* Round sin up to get a lower bound of |sin(Pi*s/2)|. */
      mpfr_sin (y, y, MPFR_INVERT_RND(rnd));
      mpfr_abs (y, y, MPFR_RNDN); /* exact, rounding mode doesn't matter */
    }
  mpz_clear (sint);
  /* now y <= |sin(Pi*s/2)| when rnd=RNDD, y >= |sin(Pi*s/2)| when rnd=RNDU */
  mpfr_zeta_pos (z, s1, rnd); /* zeta(1-s) */
  mpfr_mul (z, z, y, rnd);
  /* now z <= |sin(Pi*s/2)|*zeta(1-s) */
  mpfr_log (z, z, rnd);
  /* now z <= log(|sin(Pi*s/2)|*zeta(1-s)) */
  mpfr_lngamma (y, s1, rnd);
  mpfr_add (z, z, y, rnd);
  /* z <= lngamma(1-s) + log(|sin(Pi*s/2)|*zeta(1-s)) */
  /* since s-1 < 0, we want to round log(2*pi) upwards */
  mpfr_mul_2ui (y, p, 1, MPFR_INVERT_RND(rnd));
  mpfr_log (y, y, MPFR_INVERT_RND(rnd));
  mpfr_mul (y, y, s1, MPFR_INVERT_RND(rnd));
  mpfr_sub (z, z, y, rnd);
  mpfr_exp (z, z, rnd);
  if (rnd == MPFR_RNDD)
    mpfr_nextbelow (p); /* restore original p */
}
Beispiel #9
0
void
check_single (void)
{
  mpz_t  x;
  int    limb, offset, initial;
  unsigned long  bit;

  mpz_init (x);

  for (limb = 0; limb < 4; limb++)
    {
      for (offset = (limb==0 ? 0 : -2); offset <= 2; offset++)
	{
	  for (initial = 0; initial >= -1; initial--)
	    {
	      mpz_set_si (x, (long) initial);

	      bit = (unsigned long) limb*BITS_PER_MP_LIMB + offset;

	      mpz_clrbit (x, bit);
	      MPZ_CHECK_FORMAT (x);
	      if (mpz_tstbit (x, bit) != 0)
		{
		  printf ("check_single(): expected 0\n");
		  abort ();
		}

	      mpz_setbit (x, bit);
	      MPZ_CHECK_FORMAT (x);
	      if (mpz_tstbit (x, bit) != 1)
		{
		  printf ("check_single(): expected 1\n");
		  abort ();
		}

	      mpz_clrbit (x, bit);
	      MPZ_CHECK_FORMAT (x);
	      if (mpz_tstbit (x, bit) != 0)
		{
		  printf ("check_single(): expected 0\n");
		  abort ();
		}

	      mpz_combit (x, bit);
	      MPZ_CHECK_FORMAT (x);
	      if (mpz_tstbit (x, bit) != 1)
		{
		  printf ("check_single(): expected 1\n");
		  abort ();
		}

	      mpz_combit (x, bit);
	      MPZ_CHECK_FORMAT (x);
	      if (mpz_tstbit (x, bit) != 0)
		{
		  printf ("check_single(): expected 0\n");
		  abort ();
		}
	    }
	}
    }

  mpz_clear (x);
}
Beispiel #10
0
int quadratic_residue(mpz_t x,mpz_t q,mpz_t n)
{
    int                        leg;
    mpz_t                        tmp,ofac,nr,t,r,c,b;
    unsigned int            mod4;
    mp_bitcnt_t                twofac=0,m,i,ix;

    mod4=mpz_tstbit(n,0);
    if(!mod4) // must be odd
        return 0;

    mod4+=2*mpz_tstbit(n,1);

    leg=mpz_legendre(q,n);
    if(leg!=1)
        return leg;

    mpz_init_set(tmp,n);
	
    if(mod4==3) // directly, x = q^(n+1)/4 mod n
        {
	printf("diretamente\n\n");
        mpz_add_ui(tmp,tmp,1UL);
        mpz_tdiv_q_2exp(tmp,tmp,2);
        mpz_powm(x,q,tmp,n);
	gmp_printf("NUMERO X %Zd \n\n",x);
        mpz_clear(tmp);
        }
    else // Tonelli-Shanks
        {
	printf("Tonelli shanks!!!\n");
        mpz_inits(ofac,t,r,c,b,NULL);

        // split n - 1 into odd number times power of 2 ofac*2^twofac
        mpz_sub_ui(tmp,tmp,1UL);
        twofac=mpz_scan1(tmp,twofac); // largest power of 2 divisor
        if(twofac)
            mpz_tdiv_q_2exp(ofac,tmp,twofac); // shift right

        // look for non-residue
        mpz_init_set_ui(nr,2UL);
        while(mpz_legendre(nr,n)!=-1)
            mpz_add_ui(nr,nr,1UL);

        mpz_powm(c,nr,ofac,n); // c = nr^ofac mod n

        mpz_add_ui(tmp,ofac,1UL);
        mpz_tdiv_q_2exp(tmp,tmp,1);
        mpz_powm(r,q,tmp,n); // r = q^(ofac+1)/2 mod n

        mpz_powm(t,q,ofac,n);
        mpz_mod(t,t,n); // t = q^ofac mod n

        if(mpz_cmp_ui(t,1UL)!=0) // if t = 1 mod n we're done
            {
            m=twofac;
            do
                {
                i=2;
                ix=1;
                while(ix<m)
                    {
                    // find lowest 0 < ix < m | t^2^ix = 1 mod n
                    mpz_powm_ui(tmp,t,i,n); // repeatedly square t
                    if(mpz_cmp_ui(tmp,1UL)==0)
                        break;
                    i<<=1; // i = 2, 4, 8, ...
                    ix++; // ix is log2 i
                    }
                mpz_powm_ui(b,c,1<<(m-ix-1),n); // b = c^2^(m-ix-1) mod n
                mpz_mul(r,r,b);
                mpz_mod(r,r,n); // r = r*b mod n
                mpz_mul(c,b,b);
                mpz_mod(c,c,n); // c = b^2 mod n
                mpz_mul(t,t,c);
                mpz_mod(t,t,n); // t = t b^2 mod n
                m=ix;
                }while(mpz_cmp_ui(t,1UL)!=0); // while t mod n != 1
            }
        mpz_set(x,r);
        mpz_clears(tmp,ofac,nr,t,r,c,b,NULL);
        }

    return 1;
}
Beispiel #11
0
static int
big_bitp(object x, ufixnum p)
{
  return mpz_tstbit(MP(x),p);
}
Beispiel #12
0
static void d_pairing_pp_init(pairing_pp_t p, element_ptr in1, pairing_t pairing) {
  element_ptr P = in1;
  const element_ptr Px = curve_x_coord(P);
  const element_ptr Py = curve_y_coord(P);
  element_t Z;
  mp_bitcnt_t m;
  pptr info = pairing->data;
  element_t t0;
  element_t a, b, c;
  field_ptr Fq = info->Fq;
  pp_coeff_t *coeff;
  mpz_ptr q = pairing->r;
  pp_coeff_ptr pp;
  const element_ptr cca = curve_a_coeff(P);
  element_ptr Zx;
  element_ptr Zy;

  #define store_abc() {      \
    element_init(pp->a, Fq); \
    element_init(pp->b, Fq); \
    element_init(pp->c, Fq); \
    element_set(pp->a, a);   \
    element_set(pp->b, b);   \
    element_set(pp->c, c);   \
    pp++;                    \
  }

  #define do_tangent() {                               \
    /* a = -slope_tangent(Z.x, Z.y); */                \
    /* b = 1; */                                       \
    /* c = -(Z.y + a * Z.x); */                        \
    /* but we multiply by 2*Z.y to avoid division. */  \
                                                       \
    /* a = -Zx * (3 Zx + twicea_2) - a_4; */           \
    /* Common curves: a2 = 0 (and cc->a is a_4), so */ \
    /* a = -(3 Zx^2 + cc->a) */                        \
    /* b = 2 * Zy */                                   \
    /* c = -(2 Zy^2 + a Zx); */                        \
                                                       \
    element_square(a, Zx);                             \
    element_double(t0, a);                             \
    element_add(a, a, t0);                             \
    element_add(a, a, cca);                            \
    element_neg(a, a);                                 \
                                                       \
    element_add(b, Zy, Zy);                            \
                                                       \
    element_mul(t0, b, Zy);                            \
    element_mul(c, a, Zx);                             \
    element_add(c, c, t0);                             \
    element_neg(c, c);                                 \
                                                       \
    store_abc();                                       \
  }

  #define do_line() {                                       \
    /* a = -(B.y - A.y) / (B.x - A.x); */                   \
    /* b = 1; */                                            \
    /* c = -(A.y + a * A.x); */                             \
    /* but we'll multiply by B.x - A.x to avoid division */ \
                                                            \
    element_sub(b, Px, Zx);                                 \
    element_sub(a, Zy, Py);                                 \
    element_mul(t0, b, Zy);                                 \
    element_mul(c, a, Zx);                                  \
    element_add(c, c, t0);                                  \
    element_neg(c, c);                                      \
                                                            \
    store_abc();                                            \
  }

  element_init(Z, P->field);
  element_set(Z, P);
  Zx = curve_x_coord(Z);
  Zy = curve_y_coord(Z);

  element_init(t0, Fq);
  element_init(a, Fq);
  element_init(b, Fq);
  element_init(c, Fq);

  m = (mp_bitcnt_t)mpz_sizeinbase(q, 2);
  m = (m > 2 ? m - 2 : 0);
  p->data = pbc_malloc(sizeof(pp_coeff_t) * 2 * m);
  coeff = (pp_coeff_t *) p->data;
  pp = coeff[0];

  for(;;) {
    do_tangent();

    if (!m) break;

    element_double(Z, Z);
    if (mpz_tstbit(q, m)) {
      do_line();
      element_add(Z, Z, P);
    }
    m--;
  }

  element_clear(t0);
  element_clear(a);
  element_clear(b);
  element_clear(c);
  element_clear(Z);
  #undef store_abc
  #undef do_tangent
  #undef do_line
}
Beispiel #13
0
//do many millers at one time with affine coordinates.
static void cc_millers_no_denom_affine(element_t res, mpz_t q, element_t P[],
    element_t Qx[], element_t Qy[], int n_prod) {
  mp_bitcnt_t m;
  int i;
  element_t v;
  element_t a, b, c;
  element_t t0;
  element_t e0;
  const element_ptr cca = curve_a_coeff(P[0]);
  element_ptr Px, Py;
  element_t* Z = pbc_malloc(sizeof(element_t)*n_prod);
  element_ptr Zx, Zy;

  /* TODO: when exactly is this not needed?
  void do_vertical() {
    mapbase(e0, Z->x);
    element_sub(e0, Qx, e0);
    element_mul(v, v, e0);
  }
  */

  #define do_tangents() {                         \
    /* a = -(3 Zx^2 + cc->a) */                   \
    /* b = 2 * Zy */                              \
    /* c = -(2 Zy^2 + a Zx); */                   \
    for(i=0; i<n_prod; i++){                      \
      Px = curve_x_coord(P[i]);                   \
      Py = curve_y_coord(P[i]);                   \
      Zx = curve_x_coord(Z[i]);                   \
      Zy = curve_y_coord(Z[i]);                   \
                                                  \
      element_square(a, Zx);                      \
      element_mul_si(a, a, 3);                    \
      element_add(a, a, cca);                     \
      element_neg(a, a);                          \
                                                  \
      element_add(b, Zy, Zy);                     \
                                                  \
      element_mul(t0, b, Zy);                     \
      element_mul(c, a, Zx);                      \
      element_add(c, c, t0);                      \
      element_neg(c, c);                          \
                                                  \
      d_miller_evalfn(e0, a, b, c, Qx[i], Qy[i]); \
      element_mul(v, v, e0);                      \
    }                                             \
  }

  #define do_lines() {                                    \
    /* a = -(B.y - A.y) / (B.x - A.x); */                 \
    /* b = 1; */                                          \
    /* c = -(A.y + a * A.x); */                           \
    /* but we multiply by B.x - A.x to avoid division. */ \
    for(i=0; i<n_prod; i++){                              \
      Px = curve_x_coord(P[i]);                           \
      Py = curve_y_coord(P[i]);                           \
      Zx = curve_x_coord(Z[i]);                           \
      Zy = curve_y_coord(Z[i]);                           \
                                                          \
      element_sub(b, Px, Zx);                             \
      element_sub(a, Zy, Py);                             \
      element_mul(t0, b, Zy);                             \
      element_mul(c, a, Zx);                              \
      element_add(c, c, t0);                              \
      element_neg(c, c);                                  \
                                                          \
      d_miller_evalfn(e0, a, b, c, Qx[i], Qy[i]);         \
      element_mul(v, v, e0);                              \
    }                                                     \
  }

  Px= curve_x_coord(P[0]); //temporally used to initial a,b, c and etc.
  element_init(a, Px->field);
  element_init(b, a->field);
  element_init(c, a->field);
  element_init(t0, a->field);
  element_init(e0, res->field);

  element_init(v, res->field);
  for(i=0; i<n_prod; i++){
    element_init(Z[i], P[i]->field);
    element_set(Z[i], P[i]);
  }

  element_set1(v);
  m = (mp_bitcnt_t)mpz_sizeinbase(q, 2);
  m = (m > 2 ? m - 2 : 0);

  for(;;) {
    do_tangents();

    if (!m) break;
    element_multi_double(Z, Z, n_prod); //Z_i=Z_i+Z_i for all i.

    if (mpz_tstbit(q, m)) {
      do_lines();
      element_multi_add(Z, Z, P, n_prod); //Z_i=Z_i+P_i for all i.
    }
    m--;
    element_square(v, v);
  }

  element_set(res, v);

  element_clear(v);
  for(i=0; i<n_prod; i++){
    element_clear(Z[i]);
  }
  pbc_free(Z);
  element_clear(a);
  element_clear(b);
  element_clear(c);
  element_clear(t0);
  element_clear(e0);
  #undef do_tangents
  #undef do_lines
}
Beispiel #14
0
// Requires cofactor is even. TODO: This seems to contradict a comment below.
// Requires in != out.
// Mangles in.
static void lucas_even(element_ptr out, element_ptr in, mpz_t cofactor) {
  if (element_is1(in)) {
    element_set(out, in);
    return;
  }
  element_t temp;
  element_init_same_as(temp, out);
  element_ptr in0 = element_x(in);
  element_ptr in1 = element_y(in);
  element_ptr v0 = element_x(out);
  element_ptr v1 = element_y(out);
  element_ptr t0 = element_x(temp);
  element_ptr t1 = element_y(temp);
  size_t j;

  element_set_si(t0, 2);
  element_double(t1, in0);

  element_set(v0, t0);
  element_set(v1, t1);

  j = mpz_sizeinbase(cofactor, 2) - 1;
  for (;;) {
    if (!j) {
      element_mul(v1, v0, v1);
      element_sub(v1, v1, t1);
      element_square(v0, v0);
      element_sub(v0, v0, t0);
      break;
    }
    if (mpz_tstbit(cofactor, j)) {
      element_mul(v0, v0, v1);
      element_sub(v0, v0, t1);
      element_square(v1, v1);
      element_sub(v1, v1, t0);
    } else {
      element_mul(v1, v0, v1);
      element_sub(v1, v1, t1);
      element_square(v0, v0);
      element_sub(v0, v0, t0);
    }
    j--;
  }

  // Assume cofactor = (q^2 - q + 1) / r is odd
  // thus v1 = V_k, v0 = V_{k-1}
  //   U = (P v1 - 2 v0) / (P^2 - 4)

  element_double(v0, v0);
  element_mul(in0, t1, v1);
  element_sub(in0, in0, v0);

  element_square(t1, t1);
  element_sub(t1, t1, t0);
  element_sub(t1, t1, t0);

  element_halve(v0, v1);
  element_div(v1, in0, t1);
  element_mul(v1, v1, in1);

  element_clear(temp);
}
Beispiel #15
0
int
mpfr_cbrt (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
{
  mpz_t m;
  mp_exp_t e, r, sh;
  mp_prec_t n, size_m, tmp;
  int inexact, negative;
  MPFR_SAVE_EXPO_DECL (expo);

  /* special values */
  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
    {
      if (MPFR_IS_NAN (x))
        {
          MPFR_SET_NAN (y);
          MPFR_RET_NAN;
        }
      else if (MPFR_IS_INF (x))
        {
          MPFR_SET_INF (y);
          MPFR_SET_SAME_SIGN (y, x);
          MPFR_RET (0);
        }
      /* case 0: cbrt(+/- 0) = +/- 0 */
      else /* x is necessarily 0 */
        {
          MPFR_ASSERTD (MPFR_IS_ZERO (x));
          MPFR_SET_ZERO (y);
          MPFR_SET_SAME_SIGN (y, x);
          MPFR_RET (0);
        }
    }

  /* General case */
  MPFR_SAVE_EXPO_MARK (expo);
  mpz_init (m);

  e = mpfr_get_z_exp (m, x);                /* x = m * 2^e */
  if ((negative = MPFR_IS_NEG(x)))
    mpz_neg (m, m);
  r = e % 3;
  if (r < 0)
    r += 3;
  /* x = (m*2^r) * 2^(e-r) = (m*2^r) * 2^(3*q) */

  MPFR_MPZ_SIZEINBASE2 (size_m, m);
  n = MPFR_PREC (y) + (rnd_mode == GMP_RNDN);

  /* we want 3*n-2 <= size_m + 3*sh + r <= 3*n
     i.e. 3*sh + size_m + r <= 3*n */
  sh = (3 * (mp_exp_t) n - (mp_exp_t) size_m - r) / 3;
  sh = 3 * sh + r;
  if (sh >= 0)
    {
      mpz_mul_2exp (m, m, sh);
      e = e - sh;
    }
  else if (r > 0)
    {
      mpz_mul_2exp (m, m, r);
      e = e - r;
    }

  /* invariant: x = m*2^e, with e divisible by 3 */

  /* we reuse the variable m to store the cube root, since it is not needed
     any more: we just need to know if the root is exact */
  inexact = mpz_root (m, m, 3) == 0;

  MPFR_MPZ_SIZEINBASE2 (tmp, m);
  sh = tmp - n;
  if (sh > 0) /* we have to flush to 0 the last sh bits from m */
    {
      inexact = inexact || ((mp_exp_t) mpz_scan1 (m, 0) < sh);
      mpz_div_2exp (m, m, sh);
      e += 3 * sh;
    }

  if (inexact)
    {
      if (negative)
        rnd_mode = MPFR_INVERT_RND (rnd_mode);
      if (rnd_mode == GMP_RNDU
          || (rnd_mode == GMP_RNDN && mpz_tstbit (m, 0)))
        inexact = 1, mpz_add_ui (m, m, 1);
      else
        inexact = -1;
    }

  /* either inexact is not zero, and the conversion is exact, i.e. inexact
     is not changed; or inexact=0, and inexact is set only when
     rnd_mode=GMP_RNDN and bit (n+1) from m is 1 */
  inexact += mpfr_set_z (y, m, GMP_RNDN);
  MPFR_SET_EXP (y, MPFR_GET_EXP (y) + e / 3);

  if (negative)
    {
      MPFR_CHANGE_SIGN (y);
      inexact = -inexact;
    }

  mpz_clear (m);
  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (y, inexact, rnd_mode);
}
Beispiel #16
0
void find_candidates(mpz_t num, mpz_t gmp_root)
{
	num_cands = 0;
	mpz_add_ui(gmp_root, gmp_root, 1);

	size_t sieve_size = primes[B-1]*100;

	double *table = malloc(sizeof(double)*sieve_size);
	uint64_t root = mpz_get_ui(gmp_root);
	double approx = mpz_get_d(num);

	mpz_t tmp, tmp2;
	mpz_init(tmp); mpz_init(tmp2);

	mpz_set_ui(tmp, root);

	mpz_pow_ui(tmp, tmp, 2);
	mpz_sub(tmp, tmp, num);
	mpz_set(first_cands[0], tmp);

	unsigned int used_primes[B];
	double used_log[B];
	used_primes[0] = 2;
	used_log[0] = log_primes[0];
	size_t next_prime = 1;
	size_t offsets[B][2];
	uint64_t cand_offsets[B+1];
	size_t next_cand = 1;

	// Find prime numbers that appear in the candidate series
	for(size_t p = 1; p < B; ++p)
	{
		unsigned int prime = primes[p];
		mpz_set_ui(tmp2, prime);
		mpz_powm_ui(tmp, num, (prime-1)/2, tmp2);

		if(mpz_cmp_ui(tmp, 1)) // Skip non-quadratic residues
			continue;

		used_primes[next_prime] = prime;
		used_log[next_prime] = log_primes[p];

		// Generate more exact candidates
		for(int i = next_cand; i < prime; ++i)
		{
			mpz_set_ui(tmp, root + i);
			mpz_pow_ui(tmp, tmp, 2);
			mpz_sub(tmp, tmp, num);
			mpz_set(first_cands[i], tmp);
		}
		next_cand = prime;

		// find offsets for them
		// TODO Shanks-tonelli
		unsigned int foo = tonelli_shanks(num, prime);
		printf("root for %u is %u and %u\n", prime, foo, prime-foo);
		size_t idx = 0;
		for(int i = 0; i < prime; ++i)
		{
			if(mpz_divisible_ui_p(first_cands[i], prime))
			{
				offsets[next_prime][idx++] = i;

				if(idx == 2)
					break;
			}
		}
		assert(idx == 2);
		++next_prime;
	}

	// sieve until we find more than B candidates, guarantees linear dependence
	size_t sieve_offset = 0;
	while(num_cands <= B)
	{
		for(size_t i = 0; i < sieve_size; ++i)
		{
			double d = root + i;
			d += sieve_offset;
			table[i] = log(d*d-approx);
		}
		// cross out even ones
		for(size_t i = mpz_tstbit(tmp, 1)^(sieve_offset & 1); i < sieve_size; i+=2)
			table[i] -= log_primes[0];

		for(int p = 1; p < next_prime && num_cands <= B; ++p)
		{
			unsigned int prime = used_primes[p];
			double log_prime = used_log[p];
//			fprintf(stderr, "offsets[%d] are %d and %d\n", used_primes[p], offsets[p][0], offsets[p][1]);

			for(int x = 0; x < 2; ++x)
			{
				size_t off = (offsets[p][x] + sieve_offset + prime-1) % prime;
				for(int a = off; a < sieve_size; a += prime)
				{
					table[a] -= log_prime;
	
					if(table[a] > LIMIT)
						continue;
	
					cand_offsets[num_cands++] = root + a + sieve_offset;
					if(num_cands > B)
						break;
				}
			}
		}
		sieve_offset += sieve_size;
	}

	for(size_t i = 0; i < num_cands; ++i)
	{
		//fprintf(stderr, "%llu\n", cand_offsets[i]);
		// TODO REMOVE VERY SLOW STUFF
		mpz_set_ui(tmp, root + i);
		mpz_pow_ui(tmp, tmp, 2);
		mpz_sub(tmp, tmp, num);
//		mpz_out_str(stderr, 10, tmp);
//		fputc('\n', stderr);
	}

	fprintf(stderr, "%d used candidates\n", num_cands);

	free(table);
	mpz_clear(tmp); mpz_clear(tmp2);
}
Beispiel #17
0
Datei: sing.c Projekt: blynn/pbc
static void miller(element_t res, element_t P, element_t Q, element_t R, int n)
{
    //collate divisions
    mp_bitcnt_t m;
    element_t v, vd;
    element_t Z;
    element_t a, b, c;
    element_t e0, e1;
    mpz_t q;
    element_ptr Zx, Zy;
    const element_ptr Px = curve_x_coord(P);
    const element_ptr Py = curve_y_coord(P);
    const element_ptr numx = curve_x_coord(Q);
    const element_ptr numy = curve_y_coord(Q);
    const element_ptr denomx = curve_x_coord(R);
    const element_ptr denomy = curve_y_coord(R);

    #define do_vertical(e, edenom) {         \
        element_sub(e0, numx, Zx);           \
        element_mul((e), (e), e0);           \
                                             \
        element_sub(e0, denomx, Zx);         \
        element_mul((edenom), (edenom), e0); \
    }

    #define do_tangent(e, edenom) {                  \
        /*a = -slope_tangent(A.x, A.y);              \
          b = 1;                                     \
          c = -(A.y + a * A.x);                      \
          but we multiply by 2*A.y to avoid division \
                                                     \
          a = -Ax * (Ax + Ax + Ax + twicea_2) - a_4; \
          This curve is special:                     \
          a = -(3 Ax^2 + 2Ax)                        \
          b = 2 * Ay                                 \
          c = -(2 Ay^2 + a Ax);                   */ \
                                                     \
        if (element_is0(Zy)) {                       \
            do_vertical((e), (edenom));              \
        } else {                                     \
          element_square(a, Zx);                     \
          element_mul_si(a, a, 3);                   \
          element_add(a, a, Zx);                     \
          element_add(a, a, Zx);                     \
          element_neg(a, a);                         \
                                                     \
          element_add(b, Zy, Zy);                    \
                                                     \
          element_mul(e0, b, Zy);                    \
          element_mul(c, a, Zx);                     \
          element_add(c, c, e0);                     \
          element_neg(c, c);                         \
                                                     \
          element_mul(e0, a, numx);                  \
          element_mul(e1, b, numy);                  \
          element_add(e0, e0, e1);                   \
          element_add(e0, e0, c);                    \
          element_mul((e), (e), e0);                 \
                                                     \
          element_mul(e0, a, denomx);                \
          element_mul(e1, b, denomy);                \
          element_add(e0, e0, e1);                   \
          element_add(e0, e0, c);                    \
          element_mul((edenom), (edenom), e0);       \
        }                                            \
    }

    #define do_line(e, edenom) {               \
        if (!element_cmp(Zx, Px)) {            \
            if (!element_cmp(Zy, Py)) {        \
                do_tangent((e), (edenom));     \
            } else {                           \
                do_vertical((e), (edenom));    \
            }                                  \
        } else {                               \
          element_sub(b, Px, Zx);              \
          element_sub(a, Zy, Py);              \
          element_mul(c, Zx, Py);              \
          element_mul(e0, Zy, Px);             \
          element_sub(c, c, e0);               \
                                               \
          element_mul(e0, a, numx);            \
          element_mul(e1, b, numy);            \
          element_add(e0, e0, e1);             \
          element_add(e0, e0, c);              \
          element_mul((e), (e), e0);           \
                                               \
          element_mul(e0, a, denomx);          \
          element_mul(e1, b, denomy);          \
          element_add(e0, e0, e1);             \
          element_add(e0, e0, c);              \
          element_mul((edenom), (edenom), e0); \
       }                                       \
    }

    element_init(a, res->field);
    element_init(b, res->field);
    element_init(c, res->field);
    element_init(e0, res->field);
    element_init(e1, res->field);

    element_init(v, res->field);
    element_init(vd, res->field);
    element_init(Z, P->field);

    element_set(Z, P);
    Zx = curve_x_coord(Z);
    Zy = curve_y_coord(Z);

    element_set1(v);
    element_set1(vd);

    mpz_init(q);
    mpz_set_ui(q, n);
    m = (mp_bitcnt_t)mpz_sizeinbase(q, 2);
    m = (m > 2 ? m - 2 : 0);

    for (;;) {
        element_square(v, v);
        element_square(vd, vd);
        do_tangent(v, vd);
        element_double(Z, Z);
        do_vertical(vd, v);

        if (mpz_tstbit(q, m)) {
            do_line(v, vd);
            element_add(Z, Z, P);
            if (m) {
                do_vertical(vd, v);
            }
        }
        if (!m) break;
        m--;
    }

    mpz_clear(q);

    element_invert(vd, vd);
    element_mul(res, v, vd);

    element_clear(v);
    element_clear(vd);
    element_clear(Z);
    element_clear(a);
    element_clear(b);
    element_clear(c);
    element_clear(e0);
    element_clear(e1);
    #undef do_vertical
    #undef do_tangent
    #undef do_line
}
Beispiel #18
0
int
mpfr_grandom (mpfr_ptr rop1, mpfr_ptr rop2, gmp_randstate_t rstate,
              mpfr_rnd_t rnd)
{
  int inex1, inex2, s1, s2;
  mpz_t x, y, xp, yp, t, a, b, s;
  mpfr_t sfr, l, r1, r2;
  mpfr_prec_t tprec, tprec0;

  inex2 = inex1 = 0;

  if (rop2 == NULL) /* only one output requested. */
    {
      tprec0 = MPFR_PREC (rop1);
    }
  else
    {
      tprec0 = MAX (MPFR_PREC (rop1), MPFR_PREC (rop2));
    }

  tprec0 += 11;

  /* We use "Marsaglia polar method" here (cf.
     George Marsaglia, Normal (Gaussian) random variables for supercomputers
     The Journal of Supercomputing, Volume 5, Number 1, 49–55
     DOI: 10.1007/BF00155857).

     First we draw uniform x and y in [0,1] using mpz_urandomb (in
     fixed precision), and scale them to [-1, 1].
  */

  mpz_init (xp);
  mpz_init (yp);
  mpz_init (x);
  mpz_init (y);
  mpz_init (t);
  mpz_init (s);
  mpz_init (a);
  mpz_init (b);
  mpfr_init2 (sfr, MPFR_PREC_MIN);
  mpfr_init2 (l, MPFR_PREC_MIN);
  mpfr_init2 (r1, MPFR_PREC_MIN);
  if (rop2 != NULL)
    mpfr_init2 (r2, MPFR_PREC_MIN);

  mpz_set_ui (xp, 0);
  mpz_set_ui (yp, 0);

  for (;;)
    {
      tprec = tprec0;
      do
        {
          mpz_urandomb (xp, rstate, tprec);
          mpz_urandomb (yp, rstate, tprec);
          mpz_mul (a, xp, xp);
          mpz_mul (b, yp, yp);
          mpz_add (s, a, b);
        }
      while (mpz_sizeinbase (s, 2) > tprec * 2); /* x^2 + y^2 <= 2^{2tprec} */

      for (;;)
        {
          /* FIXME: compute s as s += 2x + 2y + 2 */
          mpz_add_ui (a, xp, 1);
          mpz_add_ui (b, yp, 1);
          mpz_mul (a, a, a);
          mpz_mul (b, b, b);
          mpz_add (s, a, b);
          if ((mpz_sizeinbase (s, 2) <= 2 * tprec) ||
              ((mpz_sizeinbase (s, 2) == 2 * tprec + 1) &&
               (mpz_scan1 (s, 0) == 2 * tprec)))
            goto yeepee;
          /* Extend by 32 bits */
          mpz_mul_2exp (xp, xp, 32);
          mpz_mul_2exp (yp, yp, 32);
          mpz_urandomb (x, rstate, 32);
          mpz_urandomb (y, rstate, 32);
          mpz_add (xp, xp, x);
          mpz_add (yp, yp, y);
          tprec += 32;

          mpz_mul (a, xp, xp);
          mpz_mul (b, yp, yp);
          mpz_add (s, a, b);
          if (mpz_sizeinbase (s, 2) > tprec * 2)
            break;
        }
    }
 yeepee:

  /* FIXME: compute s with s -= 2x + 2y + 2 */
  mpz_mul (a, xp, xp);
  mpz_mul (b, yp, yp);
  mpz_add (s, a, b);
  /* Compute the signs of the output */
  mpz_urandomb (x, rstate, 2);
  s1 = mpz_tstbit (x, 0);
  s2 = mpz_tstbit (x, 1);
  for (;;)
    {
      /* s = xp^2 + yp^2 (loop invariant) */
      mpfr_set_prec (sfr, 2 * tprec);
      mpfr_set_prec (l, tprec);
      mpfr_set_z (sfr, s, MPFR_RNDN); /* exact */
      mpfr_mul_2si (sfr, sfr, -2 * tprec, MPFR_RNDN); /* exact */
      mpfr_log (l, sfr, MPFR_RNDN);
      mpfr_neg (l, l, MPFR_RNDN);
      mpfr_mul_2si (l, l, 1, MPFR_RNDN);
      mpfr_div (l, l, sfr, MPFR_RNDN);
      mpfr_sqrt (l, l, MPFR_RNDN);

      mpfr_set_prec (r1, tprec);
      mpfr_mul_z (r1, l, xp, MPFR_RNDN);
      mpfr_div_2ui (r1, r1, tprec, MPFR_RNDN); /* exact */
      if (s1)
        mpfr_neg (r1, r1, MPFR_RNDN);
      if (MPFR_CAN_ROUND (r1, tprec - 2, MPFR_PREC (rop1), rnd))
        {
          if (rop2 != NULL)
            {
              mpfr_set_prec (r2, tprec);
              mpfr_mul_z (r2, l, yp, MPFR_RNDN);
              mpfr_div_2ui (r2, r2, tprec, MPFR_RNDN); /* exact */
              if (s2)
                mpfr_neg (r2, r2, MPFR_RNDN);
              if (MPFR_CAN_ROUND (r2, tprec - 2, MPFR_PREC (rop2), rnd))
                break;
            }
          else
            break;
        }
      /* Extend by 32 bits */
      mpz_mul_2exp (xp, xp, 32);
      mpz_mul_2exp (yp, yp, 32);
      mpz_urandomb (x, rstate, 32);
      mpz_urandomb (y, rstate, 32);
      mpz_add (xp, xp, x);
      mpz_add (yp, yp, y);
      tprec += 32;
      mpz_mul (a, xp, xp);
      mpz_mul (b, yp, yp);
      mpz_add (s, a, b);
    }
  inex1 = mpfr_set (rop1, r1, rnd);
  if (rop2 != NULL)
    {
      inex2 = mpfr_set (rop2, r2, rnd);
      inex2 = mpfr_check_range (rop2, inex2, rnd);
    }
  inex1 = mpfr_check_range (rop1, inex1, rnd);

  if (rop2 != NULL)
    mpfr_clear (r2);
  mpfr_clear (r1);
  mpfr_clear (l);
  mpfr_clear (sfr);
  mpz_clear (b);
  mpz_clear (a);
  mpz_clear (s);
  mpz_clear (t);
  mpz_clear (y);
  mpz_clear (x);
  mpz_clear (yp);
  mpz_clear (xp);

  return INEX (inex1, inex2);
}
/* assuming slaves (workers)) are all homogenous, let them all do the calculations
 regarding primes sieving, calculating the smoothness base and the modular roots */
int main(int argc, char **argv) {
	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
	MPI_Comm_size(MPI_COMM_WORLD, &mpi_group_size);
	int len;
	MPI_Get_processor_name(processor_name, &len);

	gettimeofday(&start_global, NULL);
	print_lib_version();

	mpz_init(N);
	mpz_t B;
	mpz_init(B);

	unsigned long int uBase;
	int64_t nb_primes;
	modular_root_t *modular_roots;

	uint64_t i, j;

	if (argc < 2) {
		PRINT(my_rank, "usage: %s Number_to_factorize\n", argv[0]);
		exit(2);
	}

	if (mpz_init_set_str(N, argv[1], 10) == -1) {
		PRINT(my_rank, "Cannot load N %s\n", argv[1]);
		exit(2);
	}

	mpz_t sqrtN, rem;
	mpz_init(sqrtN);
	mpz_init(rem);
	mpz_sqrtrem(sqrtN, rem, N);

	if (mpz_cmp_ui(rem, 0) != 0) /* if not perfect square, calculate the ceiling */
		mpz_add_ui(sqrtN, sqrtN, 1);
	else /* N is a perfect square, factored! */
	{
		PRINT(my_rank, "\n<<<[FACTOR]>>> %s\n", mpz_get_str(NULL, 10, sqrtN));
		return 0;
	}

	if (mpz_probab_prime_p(N, 10) > 0) /* don't bother factoring */
	{
		PRINT(my_rank, "N:%s is prime\n", mpz_get_str(NULL, 10, N));
		exit(0);
	}

	OPEN_LOG_FILE("freq");

//--------------------------------------------------------
//  calculate the smoothness base for the given N
//--------------------------------------------------------
	get_smoothness_base(B, N); /* if N is too small, the program will surely fail, please consider a pen and paper instead */
	uBase = mpz_get_ui(B);
	PRINT(my_rank, "n: %s\tBase: %s\n",
			mpz_get_str(NULL, 10, N), mpz_get_str(NULL, 10, B));

//--------------------------------------------------------
// sieve primes that are less than the smoothness base using Eratosthenes sieve
//--------------------------------------------------------
	START_TIMER();
	nb_primes = sieve_primes_up_to((int64_t) (uBase));

	PRINT(my_rank, "\tPrimes found %" PRId64 " [Smoothness Base %lu]\n",
			nb_primes, uBase);
	STOP_TIMER_PRINT_TIME("\tEratosthenes Sieving done");

//--------------------------------------------------------
// fill the primes array with primes to which n is a quadratic residue
//--------------------------------------------------------
	START_TIMER();
	primes = calloc(nb_primes, sizeof(int64_t));
	nb_qr_primes = fill_primes_with_quadratic_residue(primes, N);

	/*for(i=0; i<nb_qr_primes; i++)
	 PRINT(my_rank, "%" PRId64 "\n", primes[i]);*/

	PRINT(my_rank, "\tN-Quadratic primes found %" PRId64 "\n", nb_qr_primes);
	STOP_TIMER_PRINT_TIME("\tQuadratic prime filtering done");

//--------------------------------------------------------
// calculate modular roots
//--------------------------------------------------------
	START_TIMER();
	modular_roots = calloc(nb_qr_primes, sizeof(modular_root_t));
	mpz_t tmp, r1, r2;
	mpz_init(tmp);
	mpz_init(r1);
	mpz_init(r2);

	for (i = 0; i < nb_qr_primes; i++) {
		mpz_set_ui(tmp, (unsigned long) primes[i]);
		mpz_sqrtm(r1, N, tmp); /* calculate the modular root */
		mpz_neg(r2, r1); /* -q mod n */
		mpz_mod(r2, r2, tmp);

		modular_roots[i].root1 = mpz_get_ui(r1);
		modular_roots[i].root2 = mpz_get_ui(r2);
	}
	mpz_clear(tmp);
	mpz_clear(r1);
	mpz_clear(r2);
	STOP_TIMER_PRINT_TIME("Modular roots calculation done");

//--------------------------------------------------------
//         ***** initialize the matrix *****
//--------------------------------------------------------
	if (my_rank == 0) /* only the master have the matrix */
	{
		START_TIMER();
		init_matrix(&matrix, nb_qr_primes + NB_VECTORS_OFFSET, nb_qr_primes);
		mpz_init2(tmp_matrix_row, nb_qr_primes);
		STOP_TIMER_PRINT_TIME("Matrix initialized");
	}

//--------------------------------------------------------
// [Sieving] - everyones sieves including the master
//--------------------------------------------------------
	START_TIMER();

	mpz_t x, sieving_index, next_sieving_index, relative_start, global_step;
	unsigned long ui_index, SIEVING_STEP = 50000; /* we sieve for 50000 elements at each loop */
	int LOCAL_SIEVING_ROUNDS = 10; /* number of iterations a worker sieves before communicating results to the master */
	unsigned long sieving_round = 0;
	unsigned long nb_big_rounds = 0;

	uint64_t p_pow;
	smooth_number_t *x_squared;

	x_squared = calloc(SIEVING_STEP, sizeof(smooth_number_t));

	if (my_rank == 0)
		smooth_numbers = calloc(nb_qr_primes + NB_VECTORS_OFFSET,
				sizeof(smooth_number_t));
	else
		temp_slaves_smooth_numbers = calloc(500, sizeof(smooth_number_t));
	/* TODO: this is not properly correct, using a linkedlist is better to keep track of temporary
	 * smooth numbers at the slaves nodes however it's pretty rare to find 500 smooth numbers in
	 * 50000 * 10 interval. */

	mpz_init_set(x, sqrtN);
	mpz_init(global_step);
	mpz_init(relative_start);
	mpz_init(sieving_index);
	mpz_init(next_sieving_index);

	mpz_t p;
	mpz_init(p);
	mpz_t str;
	mpz_init_set(str, sieving_index);
	PRINT(my_rank, "\n[%s] Sieving ...\n", processor_name);

//--------------------------------------------------------
// Init before sieving
//--------------------------------------------------------
	for (i = 0; i < SIEVING_STEP; i++) {
		mpz_init(x_squared[i].value_x);
		mpz_init(x_squared[i].value_x_squared);

		mpz_init2(x_squared[i].factors_vect, nb_qr_primes);
		mpz_add_ui(x, x, 1);
	}

	int nb_smooth_per_round = 0;
	char s[512];

//--------------------------------------------------------
// WHILE smooth numbers found less than the primes in the smooth base + NB_VECTORS_OFFSET for master
// Or master asked for more smooth numbers from slaves
//--------------------------------------------------------
	while (1) {
		mpz_set_ui(global_step, nb_big_rounds); /* calculates the coordinate where the workers start sieving from */
		mpz_mul_ui(global_step, global_step, (unsigned long) mpi_group_size);
		mpz_mul_ui(global_step, global_step, SIEVING_STEP);
		mpz_mul_ui(global_step, global_step, LOCAL_SIEVING_ROUNDS);
		mpz_add(global_step, global_step, sqrtN);

		mpz_set_ui(relative_start, SIEVING_STEP);
		mpz_mul_ui(relative_start, relative_start, LOCAL_SIEVING_ROUNDS);
		mpz_mul_ui(relative_start, relative_start, (unsigned long) my_rank);
		mpz_add(relative_start, relative_start, global_step);

		mpz_set(sieving_index, relative_start);
		mpz_set(next_sieving_index, relative_start);

		for (sieving_round = 0; sieving_round < LOCAL_SIEVING_ROUNDS; /* each slave sieves for LOCAL_SIEVING_ROUNDS rounds */
		sieving_round++) {
			nb_smooth_per_round = 0;
			mpz_set(x, next_sieving_index); /* sieve numbers from sieving_index to sieving_index + sieving_step */
			mpz_set(sieving_index, next_sieving_index);

			if (my_rank == 0) {
				printf("\r");
				printf(
						"\t\tSieving at: %s30 <--> Smooth numbers found: %" PRId64 "/%" PRId64 "",
						mpz_get_str(NULL, 10, sieving_index),
						nb_global_smooth_numbers_found, nb_qr_primes);
				fflush(stdout);
			}

			for (i = 0; i < SIEVING_STEP; i++) {
				mpz_set(x_squared[i].value_x, x);

				mpz_pow_ui(x_squared[i].value_x_squared, x, 2); /* calculate value_x_squared <- x²-n */
				mpz_sub(x_squared[i].value_x_squared,
						x_squared[i].value_x_squared, N);

				mpz_clear(x_squared[i].factors_vect);
				mpz_init2(x_squared[i].factors_vect, nb_qr_primes); /* reconstruct a new fresh 0ed vector of size nb_qr_primes bits */

				mpz_add_ui(x, x, 1);
			}
			mpz_set(next_sieving_index, x);

//--------------------------------------------------------
// eliminate factors in the x_squared array, those who are 'destructed' to 1 are smooth
//--------------------------------------------------------
			for (i = 0; i < nb_qr_primes; i++) {
				mpz_set_ui(p, (unsigned long) primes[i]);
				mpz_set(x, sieving_index);

				/* get the first multiple of p that is directly larger that sieving_index
				 * Quadratic SIEVING: all elements from this number and in positions multiples of root1 and root2
				 * are also multiples of p */
				get_sieving_start_index(x, x, p, modular_roots[i].root1);
				mpz_set(str, x);
				mpz_sub(x, x, sieving_index); /* x contains index of first number that is divisible by p */

				for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) {
					p_pow = mpz_remove(x_squared[j].value_x_squared,
							x_squared[j].value_x_squared, p); /* eliminate all factors of p */

					if (p_pow & 1) /* mark bit if odd power of p exists in this x_squared[j] */
					{
						mpz_setbit(x_squared[j].factors_vect, i);
					}

					if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) {
						save_smooth_number(x_squared[j]);
						nb_smooth_per_round++;
					}
					/* sieve next element located p steps from here */
				}

				/* same goes for root2 */
				if (modular_roots[i].root2 == modular_roots[i].root1)
					continue;

				mpz_set(x, sieving_index);

				get_sieving_start_index(x, x, p, modular_roots[i].root2);
				mpz_set(str, x);
				mpz_sub(x, x, sieving_index);

				for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) {
					p_pow = mpz_remove(x_squared[j].value_x_squared,
							x_squared[j].value_x_squared, p);

					if (p_pow & 1) {
						mpz_setbit(x_squared[j].factors_vect, i);
					}

					if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) {
						save_smooth_number(x_squared[j]);
						nb_smooth_per_round++;
					}
				}
			}
		}

		if (my_rank == 0) /* master gathers smooth numbers from slaves */
		{
			gather_smooth_numbers();
			notify_slaves();
		} else /* slaves send their smooth numbers to master */
		{
			send_smooth_numbers_to_master();
			nb_global_smooth_numbers_found = get_server_notification();
		}

		if (nb_global_smooth_numbers_found >= nb_qr_primes + NB_VECTORS_OFFSET)
			break;

		nb_big_rounds++;
	}

	STOP_TIMER_PRINT_TIME("\nSieving DONE");

	if (my_rank == 0) {
		uint64_t t = 0;

//--------------------------------------------------------
//the matrix ready, start Gauss elimination. The Matrix is filled on the call of save_smooth_number()
//--------------------------------------------------------
		START_TIMER();
		gauss_elimination(&matrix);
		STOP_TIMER_PRINT_TIME("\nGauss elimination done");

		uint64_t row_index = nb_qr_primes + NB_VECTORS_OFFSET - 1; /* last row in the matrix */
		int nb_linear_relations = 0;
		mpz_t linear_relation_z, solution_z;
		mpz_init(linear_relation_z);
		mpz_init(solution_z);

		get_matrix_row(linear_relation_z, &matrix, row_index--); /* get the last few rows in the Gauss eliminated matrix*/
		while (mpz_cmp_ui(linear_relation_z, 0) == 0) {
			nb_linear_relations++;
			get_matrix_row(linear_relation_z, &matrix, row_index--);
		}

		PRINT(my_rank, "\tLinear dependent relations found : %d\n",
				nb_linear_relations);

//--------------------------------------------------------
// Factor
//--------------------------------------------------------
		//We use the last linear relation to reconstruct our solution
		START_TIMER();
		PRINT(my_rank, "%s", "\nFactorizing..\n");
		mpz_t solution_X, solution_Y;
		mpz_init(solution_X);
		mpz_init(solution_Y);

		/* we start testing from the first linear relation encountered in the matrix */
		for (j = nb_linear_relations; j > 0; j--) {
			PRINT(my_rank, "Trying %d..\n", nb_linear_relations - j + 1);
			mpz_set_ui(solution_X, 1);
			mpz_set_ui(solution_Y, 1);

			get_identity_row(solution_z, &matrix,
					nb_qr_primes + NB_VECTORS_OFFSET - j + 1);

			for (i = 0; i < nb_qr_primes; i++) {
				if (mpz_tstbit(solution_z, i)) {
					mpz_mul(solution_X, solution_X, smooth_numbers[i].value_x);
					mpz_mod(solution_X, solution_X, N); /* reduce x to modulo N */

					mpz_mul(solution_Y, solution_Y,
							smooth_numbers[i].value_x_squared);
					/*TODO: handling huge stuff here, there is no modulo N like in the solution_X case!
					 * eliminate squares as long as you go*/
				}
			}

			mpz_sqrt(solution_Y, solution_Y);
			mpz_mod(solution_Y, solution_Y, N); /* y = sqrt(MUL(xi²-n)) mod N */

			mpz_sub(solution_X, solution_X, solution_Y);

			mpz_gcd(solution_X, solution_X, N);

			if (mpz_cmp(solution_X, N) != 0 && mpz_cmp_ui(solution_X, 1) != 0) /* factor can be 1 or N, try another relation */
				break;
		}
		mpz_cdiv_q(solution_Y, N, solution_X);

		PRINT(my_rank, "\n>>>>>>>>>>> FACTORED %s =\n",
				mpz_get_str(NULL, 10, N));
		PRINT(
				my_rank,
				"\tFactor 1: %s \n\tFactor 2: %s",
				mpz_get_str(NULL, 10, solution_X), mpz_get_str(NULL, 10, solution_Y));

		sprintf(s, "\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N));
		APPEND_TO_LOG_FILE(s);
		sprintf(s, "\tFactor 1: %s \n\tFactor 2: %s",
				mpz_get_str(NULL, 10, solution_X),
				mpz_get_str(NULL, 10, solution_Y));
		APPEND_TO_LOG_FILE(s);

		gettimeofday(&end_global, NULL);
		timersub(&end_global, &start_global, &elapsed);
		sprintf(s, "****** TOTAL TIME: %.3f ms\n",
				elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000);
		APPEND_TO_LOG_FILE(s);

		STOP_TIMER_PRINT_TIME("\nFactorizing done");
	}

	PRINT(my_rank, "%s", "\nCleaning memory..\n");

	/********************** clear the x_squared array **********************/
	for (i = 0; i < SIEVING_STEP; i++) {
		mpz_clear(x_squared[i].value_x);
		mpz_clear(x_squared[i].value_x_squared);
		//free(x_squared[i].factors_exp);
		mpz_clear(x_squared[i].factors_vect);
	}
	free(x_squared);
	/********************** clear the x_squared array **********************/

	free(modular_roots);
	/********************** clear the smooth_numbers array **********************/
	if (my_rank == 0) {
		for (i = 0; i < nb_qr_primes + NB_VECTORS_OFFSET; i++) {
			mpz_clear(smooth_numbers[i].value_x);
			mpz_clear(smooth_numbers[i].value_x_squared);
			mpz_clear(smooth_numbers[i].factors_vect);
			//free(smooth_numbers[i].factors_exp);
		}
		free(smooth_numbers);
	} else {
		for (i = 0; i < 500; i++) {
			mpz_clear(temp_slaves_smooth_numbers[i].value_x);
			mpz_clear(temp_slaves_smooth_numbers[i].value_x_squared);
			mpz_clear(temp_slaves_smooth_numbers[i].factors_vect);
		}
		free(temp_slaves_smooth_numbers);
	}
	/********************** clear the smooth_numbers array **********************/

	free(primes);
	/********************** clear mpz _t **********************/mpz_clear(B);
	mpz_clear(N);
	sqrtN, rem;
	mpz_clear(x);
	mpz_clear(sieving_index);
	mpz_clear(next_sieving_index);
	mpz_clear(p);
	mpz_clear(str);
	/********************** clear mpz _t **********************/

	free_matrix(&matrix);

	gettimeofday(&end_global, NULL);
	timersub(&end_global, &start_global, &elapsed);
	PRINT(my_rank, "****** TOTAL TIME: %.3f ms\n",
			elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000);
	show_mem_usage();

	MPI_Finalize();

	return 0;
}
Beispiel #20
0
/* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4.
 * 
 * The hash function used is SHA384.
 * The exponent e used is the value in pub->e.
 */
int
_rsa_generate_fips186_4_keypair(struct rsa_public_key *pub,
				struct rsa_private_key *key,
				unsigned seed_length, uint8_t * seed,
				void *progress_ctx,
				nettle_progress_func * progress,
				/* Desired size of modulo, in bits */
				unsigned n_size)
{
	mpz_t t, r, p1, q1, lcm;
	int ret;
	struct dss_params_validation_seeds cert;
	unsigned l = n_size / 2;

	FIPS_RULE(n_size == 2048 && seed_length != 14 * 2, 0, "seed length other than 28 bytes\n");
	FIPS_RULE(n_size == 3072 && seed_length != 16 * 2, 0, "seed length other than 32 bytes\n");
	FIPS_RULE(n_size != 2048 && n_size != 3072, 0, "unsupported size for modulus\n");

	if (!mpz_tstbit(pub->e, 0)) {
		_gnutls_debug_log("Unacceptable e (it is even)\n");
		return 0;
	}

	if (mpz_cmp_ui(pub->e, 65536) <= 0) {
		_gnutls_debug_log("Unacceptable e\n");
		return 0;
	}

	mpz_init(p1);
	mpz_init(q1);
	mpz_init(lcm);
	mpz_init(t);
	mpz_init(r);

	mpz_set_ui(t, 1);
	mpz_mul_2exp(t, t, 256);

	if (mpz_cmp(pub->e, t) >= 0) {
		ret = 0;
		goto cleanup;
	}

	cert.pseed_length = sizeof(cert.pseed);
	ret = rsa_provable_prime(key->p, &cert.pseed_length, cert.pseed,
				l, seed_length,
				seed, pub->e, progress_ctx, progress);
	if (ret == 0) {
		goto cleanup;
	}

	mpz_set_ui(r, 1);
	mpz_mul_2exp(r, r, (l) - 100);

	do {
		cert.qseed_length = sizeof(cert.qseed);
		ret = rsa_provable_prime(key->q, &cert.qseed_length, cert.qseed,
					l, cert.pseed_length, cert.pseed,
					pub->e,
					progress_ctx, progress);
		if (ret == 0) {
			goto cleanup;
		}


		cert.pseed_length = cert.qseed_length;
		memcpy(cert.pseed, cert.qseed, cert.qseed_length);


		if (mpz_cmp(key->p, key->q) > 0)
			mpz_sub(t, key->p, key->q);
		else
			mpz_sub(t, key->q, key->p);
	} while (mpz_cmp(t, r) <= 0);

	memset(&cert, 0, sizeof(cert));

	mpz_mul(pub->n, key->p, key->q);

	if (mpz_sizeinbase(pub->n, 2) != n_size) {
		ret = 0;
		goto cleanup;
	}

	/* c = q^{-1} (mod p) */
	if (mpz_invert(key->c, key->q, key->p) == 0) {
		ret = 0;
		goto cleanup;
	}

	mpz_sub_ui(p1, key->p, 1);
	mpz_sub_ui(q1, key->q, 1);

	mpz_lcm(lcm, p1, q1);

	if (mpz_invert(key->d, pub->e, lcm) == 0) {
		ret = 0;
		goto cleanup;
	}

	/* check whether d > 2^(nlen/2) -- FIPS186-4 5.3.1 */
	if (mpz_sizeinbase(key->d, 2) < n_size/2) {
		ret = 0;
		goto cleanup;
	}

	/* Done! Almost, we must compute the auxiliary private values. */
	/* a = d % (p-1) */
	mpz_fdiv_r(key->a, key->d, p1);

	/* b = d % (q-1) */
	mpz_fdiv_r(key->b, key->d, q1);

	/* c was computed earlier */

	pub->size = key->size = (n_size + 7) / 8;
	if (pub->size < RSA_MINIMUM_N_OCTETS) {
		ret = 0;
		goto cleanup;
	}

	ret = 1;
 cleanup:
	mpz_clear(p1);
	mpz_clear(q1);
	mpz_clear(lcm);
	mpz_clear(t);
	mpz_clear(r);
	return ret;
}
Beispiel #21
0
static PyObject *
GMPY_mpz_lucasv(PyObject *self, PyObject *args)
{
    /* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf
     * calculate v[k] of Lucas V sequence for p,q.
     * Note: p^2-4q=0 is not tested, not a proper Lucas sequence!!
     */

    MPZ_Object *result = 0, *p, *q, *k;
    size_t s = 0, j = 0;
    mpz_t vl, vh, ql, qh, tmp;

    if (PyTuple_Size(args) != 3) {
        TYPE_ERROR("lucasv() requires 3 integer arguments");
        return NULL;
    }

    mpz_init(vl);
    mpz_init(vh);
    mpz_init(ql);
    mpz_init(qh);
    mpz_init(tmp);

    p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
    q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
    k = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
    if (!p || !q || !k) {
        TYPE_ERROR("lucasv() requires 3 integer arguments");
        goto cleanup;
    }

    /* Check if p*p - 4*q == 0. */

    mpz_mul(tmp, p->z, p->z);
    mpz_mul_ui(qh, q->z, 4);
    mpz_sub(tmp, tmp, qh);
    if (mpz_sgn(tmp) == 0) {
        VALUE_ERROR("invalid values for p,q in lucasv()");
        goto cleanup;
    }

    /* Check if k < 0. */

    if (mpz_sgn(k->z) < 0) {
        VALUE_ERROR("invalid value for k in lucasv()");
        goto cleanup;
    }

    mpz_set_si(vl, 2);
    mpz_set(vh, p->z);
    mpz_set_si(ql, 1);
    mpz_set_si(qh, 1);
    mpz_set_si(tmp,0);

    s = mpz_scan1(k->z, 0);
    for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) {
        /* ql = ql*qh */
        mpz_mul(ql, ql, qh);
        if (mpz_tstbit(k->z,j) == 1) {
            /* qh = ql*q */
            mpz_mul(qh, ql, q->z);

            /* vl = vh*vl - p*ql */
            mpz_mul(vl, vh, vl);
            mpz_mul(tmp, ql, p->z);
            mpz_sub(vl, vl, tmp);

            /* vh = vh*vh - 2*qh */
            mpz_mul(vh, vh, vh);
            mpz_mul_si(tmp, qh, 2);
            mpz_sub(vh, vh, tmp);
        }
        else {
            /* qh = ql */
            mpz_set(qh, ql);

            /* vh = vh*vl - p*ql */
            mpz_mul(vh, vh, vl);
            mpz_mul(tmp, ql, p->z);
            mpz_sub(vh, vh, tmp);

            /* vl = vl*vl - 2*ql */
            mpz_mul(vl, vl, vl);
            mpz_mul_si(tmp, ql, 2);
            mpz_sub(vl, vl, tmp);
        }
    }
    /* ql = ql*qh */
    mpz_mul(ql, ql, qh);

    /* qh = ql*q */
    mpz_mul(qh, ql, q->z);

    /* vl = vh*vl - p*ql */
    mpz_mul(vl, vh, vl);
    mpz_mul(tmp, ql, p->z);
    mpz_sub(vl, vl, tmp);

    /* ql = ql*qh */
    mpz_mul(ql, ql, qh);

    for (j = 1; j <= s; j++) {
        /* vl = vl*vl - 2*ql */
        mpz_mul(vl, vl, vl);
        mpz_mul_si(tmp, ql, 2);
        mpz_sub(vl, vl, tmp);

        /* ql = ql*ql */
        mpz_mul(ql, ql, ql);
    }

    if (!(result = GMPy_MPZ_New(NULL)))
        goto cleanup;

    /* vl contains our return value */
    mpz_set(result->z, vl);

  cleanup:
    mpz_clear(vl);
    mpz_clear(vh);
    mpz_clear(ql);
    mpz_clear(qh);
    mpz_clear(tmp);
    Py_XDECREF((PyObject*)p);
    Py_XDECREF((PyObject*)q);
    Py_XDECREF((PyObject*)k);

    return (PyObject*)result;
}
Beispiel #22
0
/*
For now we don't take into account go stop_asap and chkfilename
*/
int
ecm_stage1_batch (mpz_t f, mpres_t x, mpres_t A, mpmod_t n, double B1,
                  double *B1done, int batch, mpz_t s)
{
  mp_limb_t d_1;
  mpz_t d_2;

  mpres_t x1, z1, x2, z2;
  unsigned long i;
  mpres_t t, u;
  int ret = ECM_NO_FACTOR_FOUND;

  MEMORY_TAG;
  mpres_init (x1, n);
  MEMORY_TAG;
  mpres_init (z1, n);
  MEMORY_TAG;
  mpres_init (x2, n);
  MEMORY_TAG;
  mpres_init (z2, n);
  MEMORY_TAG;
  mpres_init (t, n);
  MEMORY_TAG;
  mpres_init (u, n);
  if (batch == 2)
    {
      MEMORY_TAG;
      mpres_init (d_2, n);
    }
  MEMORY_UNTAG;

  /* initialize P */
  mpres_set (x1, x, n);
  mpres_set_ui (z1, 1, n); /* P1 <- 1P */

  /* Compute d=(A+2)/4 from A and d'=B*d thus d' = 2^(GMP_NUMB_BITS-2)*(A+2) */
  if (batch == 1)
  {
      mpres_get_z (u, A, n);
      mpz_add_ui (u, u, 2);
      mpz_mul_2exp (u, u, GMP_NUMB_BITS - 2);
      mpres_set_z_for_gcd (u, u, n); /* reduces u mod n */
      if (mpz_size (u) > 1)
        {
          mpres_get_z (u, A, n);
          outputf (OUTPUT_ERROR,
               "Error, d'=B*(A+2)/4 should fit in a mp_limb_t, A=%Zd\n", u);
          return ECM_ERROR;
        }
      d_1 = mpz_getlimbn (u, 0);
    }
  else
    {
      /* b = (A0+2)*B/4, where B=2^(k*GMP_NUMB_BITS)
         for MODMULN or REDC, B=2^GMP_NUMB_BITS for batch1,
         and B=1 otherwise */
      mpres_add_ui (d_2, A, 2, n);
      mpres_div_2exp (d_2, d_2, 2, n); 
    }

  /* Compute 2P : no need to duplicate P, the coordinates are simple. */
  mpres_set_ui (x2, 9, n);
  if (batch == 1) /* here d = d_1 / GMP_NUMB_BITS */
    {
      /* warning: mpres_set_ui takes an unsigned long which has only 32 bits
         on Windows, while d_1 might have 64 bits */
      ASSERT_ALWAYS (mpz_size (u) == 1 && mpz_getlimbn (u, 0) == d_1);
      mpres_set_z (z2, u, n);
      mpres_div_2exp (z2, z2, GMP_NUMB_BITS, n);
    }
  else
      mpres_set (z2, d_2, n);
 
  mpres_mul_2exp (z2, z2, 6, n);
  mpres_add_ui (z2, z2, 8, n); /* P2 <- 2P = (9 : : 64d+8) */

  /* invariant: if j represents the upper bits of s,
     then P1 = j*P and P2=(j+1)*P */

  mpresn_pad (x1, n);
  mpresn_pad (z1, n);
  mpresn_pad (x2, n);
  mpresn_pad (z2, n);

  /* now perform the double-and-add ladder */
  if (batch == 1)
    {
      for (i = mpz_sizeinbase (s, 2) - 1; i-- > 0;)
        {
          if (mpz_tstbit (s, i) == 0) /* (j,j+1) -> (2j,2j+1) */
            /* P2 <- P1+P2    P1 <- 2*P1 */
            dup_add_batch1 (x1, z1, x2, z2, t, u, d_1, n);
          else /* (j,j+1) -> (2j+1,2j+2) */
              /* P1 <- P1+P2     P2 <- 2*P2 */
            dup_add_batch1 (x2, z2, x1, z1, t, u, d_1, n);
        }
    }
  else /* batch = 2 */
    {
      mpresn_pad (d_2, n);
      for (i = mpz_sizeinbase (s, 2) - 1; i-- > 0;)
        {
          if (mpz_tstbit (s, i) == 0) /* (j,j+1) -> (2j,2j+1) */
            /* P2 <- P1+P2    P1 <- 2*P1 */
            dup_add_batch2 (x1, z1, x2, z2, t, u, d_2, n);
          else /* (j,j+1) -> (2j+1,2j+2) */
              /* P1 <- P1+P2     P2 <- 2*P2 */
            dup_add_batch2 (x2, z2, x1, z1, t, u, d_2, n);
        }
    }

  *B1done=B1;

  mpresn_unpad (x1);
  mpresn_unpad (z1);

  if (!mpres_invert (u, z1, n)) /* Factor found? */
    {
      mpres_gcd (f, z1, n);
      ret = ECM_FACTOR_FOUND_STEP1;
    }
  mpres_mul (x, x1, u, n);

  mpz_clear (x1);
  mpz_clear (z1);
  mpz_clear (x2);
  mpz_clear (z2);
  mpz_clear (t);
  mpz_clear (u);
  if (batch == 2)
    {
      mpz_clear (d_2);
    }

  return ret;
}
Beispiel #23
0
/* If x^y is exactly representable (with maybe a larger precision than z),
   round it in z and return the (mpc) inexact flag in [0, 10].

   If x^y is not exactly representable, return -1.

   If intermediate computations lead to numbers of more than maxprec bits,
   then abort and return -2 (in that case, to avoid loops, mpc_pow_exact
   should be called again with a larger value of maxprec).

   Assume one of Re(x) or Im(x) is non-zero, and y is non-zero (y is real).
*/
static int
mpc_pow_exact (mpc_ptr z, mpc_srcptr x, mpfr_srcptr y, mpc_rnd_t rnd,
               mp_prec_t maxprec)
{
  mp_exp_t ec, ed, ey, emin, emax;
  mpz_t my, a, b, c, d, u;
  unsigned long int t;
  int ret = -2;

  mpz_init (my);
  mpz_init (a);
  mpz_init (b);
  mpz_init (c);
  mpz_init (d);
  mpz_init (u);

  ey = mpfr_get_z_exp (my, y);
  /* normalize so that my is odd */
  t = mpz_scan1 (my, 0);
  ey += t;
  mpz_tdiv_q_2exp (my, my, t);

  if (mpfr_zero_p (MPC_RE(x)))
    {
      mpz_set_ui (c, 0);
      ec = 0;
    }
  else
    ec = mpfr_get_z_exp (c, MPC_RE(x));
  if (mpfr_zero_p (MPC_IM(x)))
    {
      mpz_set_ui (d, 0);
      ed = ec;
    }
  else
    {
      ed = mpfr_get_z_exp (d, MPC_IM(x));
      if (mpfr_zero_p (MPC_RE(x)))
        ec = ed;
    }
  /* x = c*2^ec + I * d*2^ed */
  /* equalize the exponents of x */
  if (ec < ed)
    {
      mpz_mul_2exp (d, d, ed - ec);
      if (mpz_sizeinbase (d, 2) > maxprec)
        goto end;
      ed = ec;
    }
  else if (ed < ec)
    {
      mpz_mul_2exp (c, c, ec - ed);
      if (mpz_sizeinbase (c, 2) > maxprec)
        goto end;
      ec = ed;
    }
  /* now ec=ed and x = (c + I * d) * 2^ec */

  /* divide by two if possible */
  if (mpz_cmp_ui (c, 0) == 0)
    {
      t = mpz_scan1 (d, 0);
      mpz_tdiv_q_2exp (d, d, t);
      ec += t;
    }
  else if (mpz_cmp_ui (d, 0) == 0)
    {
      t = mpz_scan1 (c, 0);
      mpz_tdiv_q_2exp (c, c, t);
      ec += t;
    }
  else /* neither c nor d is zero */
    {
      unsigned long v;
      t = mpz_scan1 (c, 0);
      v = mpz_scan1 (d, 0);
      if (v < t)
        t = v;
      mpz_tdiv_q_2exp (c, c, t);
      mpz_tdiv_q_2exp (d, d, t);
      ec += t;
    }

  /* now either one of c, d is odd */

  while (ey < 0)
    {
      /* check if x is a square */
      if (ec & 1)
        {
          mpz_mul_2exp (c, c, 1);
          mpz_mul_2exp (d, d, 1);
          ec --;
        }
      /* now ec is even */
      if (mpc_perfect_square_p (a, b, c, d) == 0)
        break;
      mpz_swap (a, c);
      mpz_swap (b, d);
      ec /= 2;
      ey ++;
    }

  if (ey < 0)
    {
      ret = -1; /* not representable */
      goto end;
    }

  /* Now ey >= 0, it thus suffices to check that x^my is representable.
     If my > 0, this is always true. If my < 0, we first try to invert
     (c+I*d)*2^ec.
  */
  if (mpz_cmp_ui (my, 0) < 0)
    {
      /* If my < 0, 1 / (c + I*d) = (c - I*d)/(c^2 + d^2), thus a sufficient
         condition is that c^2 + d^2 is a power of two, assuming |c| <> |d|.
         Assume a prime p <> 2 divides c^2 + d^2,
         then if p does not divide c or d, 1 / (c + I*d) cannot be exact.
         If p divides both c and d, then we can write c = p*c', d = p*d',
         and 1 / (c + I*d) = 1/p * 1/(c' + I*d'). This shows that if 1/(c+I*d)
         is exact, then 1/(c' + I*d') is exact too, and we are back to the
         previous case. In conclusion, a necessary and sufficient condition
         is that c^2 + d^2 is a power of two.
      */
      /* FIXME: we could first compute c^2+d^2 mod a limb for example */
      mpz_mul (a, c, c);
      mpz_addmul (a, d, d);
      t = mpz_scan1 (a, 0);
      if (mpz_sizeinbase (a, 2) != 1 + t) /* a is not a power of two */
        {
          ret = -1; /* not representable */
          goto end;
        }
      /* replace (c,d) by (c/(c^2+d^2), -d/(c^2+d^2)) */
      mpz_neg (d, d);
      ec = -ec - t;
      mpz_neg (my, my);
    }

  /* now ey >= 0 and my >= 0, and we want to compute
     [(c + I * d) * 2^ec] ^ (my * 2^ey).

     We first compute [(c + I * d) * 2^ec]^my, then square ey times. */
  t = mpz_sizeinbase (my, 2) - 1;
  mpz_set (a, c);
  mpz_set (b, d);
  ed = ec;
  /* invariant: (a + I*b) * 2^ed = ((c + I*d) * 2^ec)^trunc(my/2^t) */
  while (t-- > 0)
    {
      unsigned long v, w;
      /* square a + I*b */
      mpz_mul (u, a, b);
      mpz_mul (a, a, a);
      mpz_submul (a, b, b);
      mpz_mul_2exp (b, u, 1);
      ed *= 2;
      if (mpz_tstbit (my, t)) /* multiply by c + I*d */
        {
          mpz_mul (u, a, c);
          mpz_submul (u, b, d); /* ac-bd */
          mpz_mul (b, b, c);
          mpz_addmul (b, a, d); /* bc+ad */
          mpz_swap (a, u);
          ed += ec;
        }
      /* remove powers of two in (a,b) */
      if (mpz_cmp_ui (a, 0) == 0)
        {
          w = mpz_scan1 (b, 0);
          mpz_tdiv_q_2exp (b, b, w);
          ed += w;
        }
      else if (mpz_cmp_ui (b, 0) == 0)
        {
          w = mpz_scan1 (a, 0);
          mpz_tdiv_q_2exp (a, a, w);
          ed += w;
        }
      else
        {
          w = mpz_scan1 (a, 0);
          v = mpz_scan1 (b, 0);
          if (v < w)
            w = v;
          mpz_tdiv_q_2exp (a, a, w);
          mpz_tdiv_q_2exp (b, b, w);
          ed += w;
        }
      if (mpz_sizeinbase (a, 2) > maxprec || mpz_sizeinbase (b, 2) > maxprec)
        goto end;
    }
  /* now a+I*b = (c+I*d)^my */

  while (ey-- > 0)
    {
      unsigned long sa, sb;

      /* square a + I*b */
      mpz_mul (u, a, b);
      mpz_mul (a, a, a);
      mpz_submul (a, b, b);
      mpz_mul_2exp (b, u, 1);
      ed *= 2;

      /* divide by largest 2^n possible, to avoid many loops for e.g.,
         (2+2*I)^16777216 */
      sa = mpz_scan1 (a, 0);
      sb = mpz_scan1 (b, 0);
      sa = (sa <= sb) ? sa : sb;
      mpz_tdiv_q_2exp (a, a, sa);
      mpz_tdiv_q_2exp (b, b, sa);
      ed += sa;

      if (mpz_sizeinbase (a, 2) > maxprec || mpz_sizeinbase (b, 2) > maxprec)
        goto end;
    }

  /* save emin, emax */
  emin = mpfr_get_emin ();
  emax = mpfr_get_emax ();
  mpfr_set_emin (mpfr_get_emin_min ());
  mpfr_set_emax (mpfr_get_emax_max ());
  ret = mpfr_set_z (MPC_RE(z), a, MPC_RND_RE(rnd));
  ret = MPC_INEX(ret, mpfr_set_z (MPC_IM(z), b, MPC_RND_IM(rnd)));
  mpfr_mul_2si (MPC_RE(z), MPC_RE(z), ed, MPC_RND_RE(rnd));
  mpfr_mul_2si (MPC_IM(z), MPC_IM(z), ed, MPC_RND_IM(rnd));
  /* restore emin, emax */
  mpfr_set_emin (emin);
  mpfr_set_emax (emax);

 end:
  mpz_clear (my);
  mpz_clear (a);
  mpz_clear (b);
  mpz_clear (c);
  mpz_clear (d);
  mpz_clear (u);

  return ret;
}
Beispiel #24
0
void
check_random (int argc, char *argv[])
{
  mpz_t x, s0, s1, s2, s3, m;
  mp_size_t xsize;
  int i;
  int reps = 100000;
  int bit0, bit1, bit2, bit3;
  unsigned long int bitindex;
  const char  *s = "";

  if (argc == 2)
    reps = atoi (argv[1]);

  mpz_init (x);
  mpz_init (s0);
  mpz_init (s1);
  mpz_init (s2);
  mpz_init (s3);
  mpz_init (m);

  for (i = 0; i < reps; i++)
    {
      xsize = urandom () % (2 * SIZE) - SIZE;
      mpz_random2 (x, xsize);
      bitindex = urandom () % SIZE;

      mpz_set (s0, x);
      bit0 = mpz_tstbit (x, bitindex);
      mpz_setbit (x, bitindex);
      MPZ_CHECK_FORMAT (x);

      mpz_set (s1, x);
      bit1 = mpz_tstbit (x, bitindex);
      mpz_clrbit (x, bitindex);
      MPZ_CHECK_FORMAT (x);

      mpz_set (s2, x);
      bit2 = mpz_tstbit (x, bitindex);
      mpz_setbit (x, bitindex);
      MPZ_CHECK_FORMAT (x);

      mpz_set (s3, x);
      bit3 = mpz_tstbit (x, bitindex);

#define FAIL(str) do { s = str; goto fail; } while (0)

      if (bit1 != 1)  FAIL ("bit1 != 1");
      if (bit2 != 0)  FAIL ("bit2 != 0");
      if (bit3 != 1)  FAIL ("bit3 != 1");

      if (bit0 == 0)
	{
	  if (mpz_cmp (s0, s1) == 0 || mpz_cmp (s0, s2) != 0 || mpz_cmp (s0, s3) == 0)
	    abort ();
	}
      else
	{
	  if (mpz_cmp (s0, s1) != 0 || mpz_cmp (s0, s2) == 0 || mpz_cmp (s0, s3) != 0)
	    abort ();
	}

      if (mpz_cmp (s1, s2) == 0 || mpz_cmp (s1, s3) != 0)
	abort ();
      if (mpz_cmp (s2, s3) == 0)
	abort ();

      mpz_ui_pow_ui (m, 2L, bitindex);
      MPZ_CHECK_FORMAT (m);
      mpz_ior (x, s2, m);
      MPZ_CHECK_FORMAT (x);
      if (mpz_cmp (x, s3) != 0)
	abort ();

      mpz_com (m, m);
      MPZ_CHECK_FORMAT (m);
      mpz_and (x, s1, m);
      MPZ_CHECK_FORMAT (x);
      if (mpz_cmp (x, s2) != 0)
	abort ();
    }

  mpz_clear (x);
  mpz_clear (s0);
  mpz_clear (s1);
  mpz_clear (s2);
  mpz_clear (s3);
  mpz_clear (m);
  return;


 fail:
  printf ("%s\n", s);
  printf ("bitindex = %lu\n", bitindex);
  printf ("x = "); mpz_out_str (stdout, -16, x); printf (" hex\n");
  exit (1);
}
Beispiel #25
0
	void FixComplexKCM::emulate(TestCase * tc) {

		/* first we are going to format the entries */
		mpz_class reIn = tc->getInputValue("ReIN");
		mpz_class imIn = tc->getInputValue("ImIN");


		/* Sign handling */
		// Msb index counting from one
		bool reInNeg = (
				signedInput &&
				(mpz_tstbit(reIn.get_mpz_t(), input_width - 1) == 1)
			);

		bool imInNeg = (
				signedInput && 
				(mpz_tstbit(imIn.get_mpz_t(), input_width - 1) == 1)
			);

		// 2's complement -> absolute value unsigned representation
		if(reInNeg)
		{
			reIn = (mpz_class(1) << input_width) - reIn;
		}

		if(imInNeg)
		{
			imIn = (mpz_class(1) << input_width) - imIn;
		}

		//Cast to mp floating point number
		mpfr_t reIn_mpfr, imIn_mpfr;
		mpfr_init2(reIn_mpfr, input_width + 1);
		mpfr_init2(imIn_mpfr, input_width + 1);

		//Exact
		mpfr_set_z(reIn_mpfr, reIn.get_mpz_t(), GMP_RNDN); 
		mpfr_set_z(imIn_mpfr, imIn.get_mpz_t(), GMP_RNDN);

		//Scaling : Exact
		mpfr_mul_2si(reIn_mpfr, reIn_mpfr, lsb_in, GMP_RNDN);
		mpfr_mul_2si(imIn_mpfr, imIn_mpfr, lsb_in, GMP_RNDN);

		mpfr_t re_prod, im_prod, crexim_prod, xrecim_prod;
		mpfr_t reOut, imOut;

		mpfr_inits2(
				2 * input_width + 1, 
				re_prod, 
				im_prod, 
				crexim_prod, 
				xrecim_prod, 
				NULL
			);

		mpfr_inits2(5 * max(outputim_width, outputre_width) + 1, reOut, imOut, NULL);

		// c_r * x_r -> re_prod
		mpfr_mul(re_prod, reIn_mpfr, mpfr_constant_re, GMP_RNDN);

		// c_i * x_i -> im_prod
		mpfr_mul(im_prod, imIn_mpfr, mpfr_constant_im, GMP_RNDN);

		// c_r * x_i -> crexim_prod
		mpfr_mul(crexim_prod, mpfr_constant_re, imIn_mpfr, GMP_RNDN);

		// x_r * c_im -> xrecim_prod
		mpfr_mul(xrecim_prod, reIn_mpfr, mpfr_constant_im, GMP_RNDN);

		/* Input sign correction */
		if(reInNeg)
		{
			//Exact
			mpfr_neg(re_prod, re_prod, GMP_RNDN);
			mpfr_neg(xrecim_prod, xrecim_prod, GMP_RNDN);
		}

		if(imInNeg)
		{
			//Exact
			mpfr_neg(im_prod, im_prod, GMP_RNDN);
			mpfr_neg(crexim_prod, crexim_prod, GMP_RNDN);
		}

		mpfr_sub(reOut, re_prod, im_prod, GMP_RNDN);
		mpfr_add(imOut, crexim_prod, xrecim_prod, GMP_RNDN);

		bool reOutNeg = (mpfr_sgn(reOut) < 0);
		bool imOutNeg = (mpfr_sgn(imOut) < 0);

		if(reOutNeg)
		{
			//Exact
			mpfr_abs(reOut, reOut, GMP_RNDN);
		}

		if(imOutNeg)
		{
			//Exact
			mpfr_abs(imOut, imOut, GMP_RNDN);
		}

		//Scale back (Exact)
		mpfr_mul_2si(reOut, reOut, -lsb_out,  GMP_RNDN);
		mpfr_mul_2si(imOut, imOut, -lsb_out, GMP_RNDN);

		//Get bits vector
		mpz_class reUp, reDown, imUp, imDown, carry;

		mpfr_get_z(reUp.get_mpz_t(), reOut, GMP_RNDU);
		mpfr_get_z(reDown.get_mpz_t(), reOut, GMP_RNDD);
		mpfr_get_z(imDown.get_mpz_t(), imOut, GMP_RNDD);
		mpfr_get_z(imUp.get_mpz_t(), imOut, GMP_RNDU);
		carry = 0;

		//If result was negative, compute 2's complement
		if(reOutNeg)
		{
			reUp = (mpz_class(1) << outputre_width) - reUp;
			reDown = (mpz_class(1) << outputre_width) - reDown;
		}

		if(imOutNeg)
		{
			imUp = (mpz_class(1) << outputim_width) - imUp;
			imDown = (mpz_class(1) << outputim_width) - imDown;
		}

		//Handle border cases
		if(imUp > (mpz_class(1) << outputim_width) - 1 )
		{
			imUp = 0;
		}

		if(reUp > (mpz_class(1) << outputre_width) - 1)
		{
			reUp = 0;
		}

		if(imDown > (mpz_class(1) << outputim_width) - 1 )
		{
			imDown = 0;
		}

		if(reDown > (mpz_class(1) << outputre_width) - 1)
		{
			reDown = 0;
		}

		//Add expected results to corresponding outputs
		tc->addExpectedOutput("ReOut", reUp);	
		tc->addExpectedOutput("ReOut", reDown);	
		tc->addExpectedOutput("ImOut", imUp);	
		tc->addExpectedOutput("ImOut", imDown);	

		mpfr_clears(
				reOut,
				imOut, 
				re_prod, 
				im_prod, 
				crexim_prod, 
				xrecim_prod, 
				reIn_mpfr, 
				imIn_mpfr,
				NULL
			);
	}
Beispiel #26
0
void *check_groups(void *thread_id) {
    int limite_inferior, limite_superior;
    bool adversario = false;
    Limites limites_grupo_actual;

    pthread_mutex_lock(&mutex_grupos);
    /* Revisamos el grupo para ver si hay algún adversario.
     * Recordar que una restricción de nuestra implementación es
     * que el adversario compromete la clave inmediatamente, lo que
     * significa que al encontrar un adversario podemos considerar
     * que la clave está comprometida y debemos dividir el grupo. */
    if (grupos.size() == 0) {
        pthread_mutex_unlock(&mutex_grupos);
        pthread_mutex_lock(&mutex_thread_pool);
        /* El thread se encola a sí mismo, indicando que está disponible. */
        thread_pool.push((unsigned long) thread_id);
        pthread_mutex_unlock(&mutex_thread_pool);

        pthread_exit(EXIT_SUCCESS);
    }
    limites_grupo_actual = grupos.front();
    grupos.pop();
    pthread_mutex_unlock(&mutex_grupos);

    limite_inferior = limites_grupo_actual.first;
    limite_superior = limites_grupo_actual.second;
    /* Si el grupo consiste en un solo usuario, significa que hemos
     * logrado identificar al adversario */
    if (limite_inferior == limite_superior) {
        if (mpz_tstbit(usuarios, limite_inferior)) {
            pthread_mutex_lock(&mutex_identificados);
            identificados++;
            pthread_mutex_unlock(&mutex_identificados);
        }
    } else {
        /* Buscamos el adversario en el bitset, entre los rangos
         * limite_inferior y limite_superior. */
        int index = mpz_scan1(usuarios, limite_inferior);
        if (index <= limite_superior && index >= 0) {
            adversario = true;
        }

        /* Adversario encontrado, dividir el grupo en dos subgrupos.
         * Revocamos clave antigua y asignamos dos nuevas */
        if (adversario) {
            int avg_limites = avg(limite_superior, limite_inferior);
            Limites nuevos_limites = std::make_pair(limite_inferior, limite_inferior + avg_limites);

            pthread_mutex_lock(&mutex_grupos);
            grupos.push(nuevos_limites);
            nuevos_limites = std::make_pair(nuevos_limites.second + 1, limite_superior);
            grupos.push(nuevos_limites);
            pthread_mutex_unlock(&mutex_grupos);

            pthread_mutex_lock(&mutex_claves);
            claves += 1;
            pthread_mutex_unlock(&mutex_claves);
        }
    }
    pthread_mutex_lock(&mutex_thread_pool);
    /* El thread se encola a sí mismo, indicando que está disponible. */
    thread_pool.push((unsigned long) thread_id);
    pthread_mutex_unlock(&mutex_thread_pool);

    pthread_exit(EXIT_SUCCESS);
}
/**
   Perform a point multiplication 
   @param k    The scalar to multiply by
   @param G    The base point
   @param R    [out] Destination for kG
   @param modulus  The modulus of the field the ECC curve is in
   @param map      Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
   @return CRYPT_OK on success
*/
int
ecc_mulmod (mpz_t k, ecc_point * G, ecc_point * R, mpz_t a, mpz_t modulus,
                int map)

{
   ecc_point *tG, *M[8];
   int        i, j, err, bitidx;
   int        first, bitbuf, bitcpy, mode;

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

  /* alloc ram for window temps */
  for (i = 0; i < 8; i++) {
      M[i] = ecc_new_point();
      if (M[i] == NULL) {
         for (j = 0; j < i; j++) {
             ecc_del_point(M[j]);
         }

         return -1;
      }
  }

   /* make a copy of G incase R==G */
   tG = ecc_new_point();
   if (tG == NULL)
     { 
       err = -1;
       goto done; 
     }

   /* tG = G  and convert to montgomery */
   mpz_set (tG->x, G->x);
   mpz_set (tG->y, G->y);
   mpz_set (tG->z, G->z);

   /* calc the M tab, which holds kG for k==8..15 */
   /* M[0] == 8G */
   if ((err = ecc_projective_dbl_point (tG, M[0], a, modulus)) != 0)
     goto done;

   if ((err = ecc_projective_dbl_point (M[0], M[0], a, modulus)) != 0)
     goto done;

   if ((err = ecc_projective_dbl_point (M[0], M[0], a, modulus)) != 0)
     goto done;
 
   /* now find (8+k)G for k=1..7 */
   for (j = 9; j < 16; j++) {
     if (ecc_projective_add_point(M[j-9], tG, M[j-8], a, modulus) != 0)
       goto done;
   }

   /* setup sliding window */
   mode   = 0;
   bitidx = mpz_size (k) * GMP_NUMB_BITS - 1;
   bitcpy = bitbuf = 0;
   first  = 1;

   /* perform ops */
   for (;;) {
     /* grab next digit as required */
     if (bitidx == -1) {
       break;
     }

     /* grab the next msb from the ltiplicand */
     i = mpz_tstbit (k, bitidx--);

     /* skip leading zero bits */
     if (mode == 0 && i == 0) {
        continue;
     }

     /* if the bit is zero and mode == 1 then we double */
     if (mode == 1 && i == 0) {
        if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0)
          goto done;
        continue;
     }

     /* else we add it to the window */
     bitbuf |= (i << (WINSIZE - ++bitcpy));
     mode = 2;

     if (bitcpy == WINSIZE) {
       /* if this is the first window we do a simple copy */
       if (first == 1) {
          /* R = kG [k = first window] */
          mpz_set(R->x, M[bitbuf-8]->x);
          mpz_set(R->y, M[bitbuf-8]->y);
          mpz_set(R->z, M[bitbuf-8]->z);
          first = 0;
       } else {
         /* normal window */
         /* ok window is filled so double as required and add  */
         /* double first */
         for (j = 0; j < WINSIZE; j++) {
           if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0)
             goto done;
         }

         /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
         if ((err = ecc_projective_add_point(R, M[bitbuf-8], R, a, modulus)) != 0)
           goto done;
       }
       /* empty window and reset */
       bitcpy = bitbuf = 0;
       mode = 1;
    }
  }

   /* if bits remain then double/add */
   if (mode == 2 && bitcpy > 0) {
     /* double then add */
     for (j = 0; j < bitcpy; j++) {
       /* only double if we have had at least one add first */
       if (first == 0) {
          if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0)
            goto done;
       }

       bitbuf <<= 1;
       if ((bitbuf & (1 << WINSIZE)) != 0) {
         if (first == 1){
            /* first add, so copy */
            mpz_set(R->x, tG->x);
            mpz_set(R->y, tG->y);
            mpz_set(R->z, tG->z);
            first = 0;
         } else {
            /* then add */
            if ((err = ecc_projective_add_point(R, tG, R, a, modulus)) != 0)
              goto done;
         }
       }
     }
   }

   /* map R back from projective space */
   if (map) {
      err = ecc_map(R, modulus);
   } else {
      err = 0;
   }
done:
   ecc_del_point(tG);
   for (i = 0; i < 8; i++) {
       ecc_del_point(M[i]);
   }
   return err;
}
Beispiel #28
0
static void cc_miller_no_denom(element_t res, mpz_t q, element_t P,
    element_ptr Qx, element_ptr Qy, element_t negalpha) {
  mp_bitcnt_t m;
  element_t v;
  element_t Z;
  element_t a, b, c;
  element_t t0;
  element_t e0, e1;
  element_ptr Zx, Zy;
  const element_ptr Px = curve_x_coord(P);
  const element_ptr Py = curve_y_coord(P);

  #define do_term(i, j, k, flag) {                                \
    element_ptr e2;                                               \
    e2 = element_item(e0, i);                                     \
    element_mul(e1, element_item(v, j), Qx);                      \
    if (flag == 1) element_mul(e1, e1, negalpha);                 \
    element_mul(element_x(e1), element_x(e1), a);                 \
    element_mul(element_y(e1), element_y(e1), a);                 \
    element_mul(e2, element_item(v, k), Qy);                      \
    element_mul(element_x(e2), element_x(e2), b);                 \
    element_mul(element_y(e2), element_y(e2), b);                 \
    element_add(e2, e2, e1);                                      \
    if (flag == 2) element_mul(e2, e2, negalpha);                 \
    element_mul(element_x(e1), element_x(element_item(v, i)), c); \
    element_mul(element_y(e1), element_y(element_item(v, i)), c); \
    element_add(e2, e2, e1);                                      \
  }

  // a, b, c lie in Fq
  // Qx, Qy lie in Fq^2
  // Qx is coefficient of x^4
  // Qy is coefficient of x^3
  //
  // computes v *= (a Qx x^4 + b Qy x^3 + c)
  //
  // recall x^6 = -alpha thus
  // x^4 (u0 + u1 x^1 + ... + u5 x^5) =
  // u0 x^4 + u1 x^5
  // - alpha u2 - alpha u3 x - alpha u4 x^2 - alpha u5 x^3
  // and
  // x^4 (u0 + u1 x^1 + ... + u5 x^5) =
  // u0 x^3 + u1 x^4 + u2 x^5
  // - alpha u3 - alpha u4 x - alpha u5 x^2
  #define f_miller_evalfn() { \
    do_term(0, 2, 3, 2);      \
    do_term(1, 3, 4, 2);      \
    do_term(2, 4, 5, 2);      \
    do_term(3, 5, 0, 1);      \
    do_term(4, 0, 1, 0);      \
    do_term(5, 1, 2, 0);      \
    element_set(v, e0);       \
  }
  /*
    element_ptr e1;

    e1 = element_item(e0, 4);

    element_mul(element_x(e1), element_x(Qx), a);
    element_mul(element_y(e1), element_y(Qx), a);

    e1 = element_item(e0, 3);

    element_mul(element_x(e1), element_x(Qy), b);
    element_mul(element_y(e1), element_y(Qy), b);

    element_set(element_x(element_item(e0, 0)), c);

    element_mul(v, v, e0);
   */

  //a = -3 Zx^2 since cc->a is 0 for D = 3
  //b = 2 * Zy
  //c = -(2 Zy^2 + a Zx);
  #define do_tangent() {     \
    element_square(a, Zx);   \
    element_mul_si(a, a, 3); \
    element_neg(a, a);       \
                             \
    element_add(b, Zy, Zy);  \
                             \
    element_mul(t0, b, Zy);  \
    element_mul(c, a, Zx);   \
    element_add(c, c, t0);   \
    element_neg(c, c);       \
                             \
    f_miller_evalfn();       \
  }

  //a = -(B.y - A.y) / (B.x - A.x);
  //b = 1;
  //c = -(A.y + a * A.x);
  //but we'll multiply by B.x - A.x to avoid division
  #define do_line() {       \
    element_sub(b, Px, Zx); \
    element_sub(a, Zy, Py); \
    element_mul(t0, b, Zy); \
    element_mul(c, a, Zx);  \
    element_add(c, c, t0);  \
    element_neg(c, c);      \
                            \
    f_miller_evalfn();      \
  }

  element_init(a, Px->field);
  element_init(b, a->field);
  element_init(c, a->field);
  element_init(t0, a->field);
  element_init(e0, res->field);
  element_init(e1, Qx->field);

  element_init(v, res->field);
  element_init(Z, P->field);

  element_set(Z, P);
  Zx = curve_x_coord(Z);
  Zy = curve_y_coord(Z);

  element_set1(v);
  m = (mp_bitcnt_t)mpz_sizeinbase(q, 2);
  m = (m > 2 ? m - 2 : 0);

  //TODO: sliding NAF
  for(;;) {
    do_tangent();

    if (!m) break;

    element_double(Z, Z);
    if (mpz_tstbit(q, m)) {
      do_line();
      element_add(Z, Z, P);
    }
    m--;
    element_square(v, v);
  }

  element_set(res, v);

  element_clear(v);
  element_clear(Z);
  element_clear(a);
  element_clear(b);
  element_clear(c);
  element_clear(t0);
  element_clear(e0);
  element_clear(e1);
  #undef do_term
  #undef f_miller_evalfn
  #undef do_tangent
  #undef do_line
}
Beispiel #29
0
Datei: dlog.c Projekt: blynn/pbc
// x in Z_r, g, h in some group of order r
// finds x such that g^x = h
void element_dlog_pollard_rho(element_t x, element_t g, element_t h) {
// see Blake, Seroussi and Smart
// only one snark for this implementation
  int i, s = 20;
  field_ptr Zr = x->field, G = g->field;
  element_t asum;
  element_t bsum;
  element_t a[20];
  element_t b[20];
  element_t m[20];
  element_t g0, snark;
  darray_t hole;
  int interval = 5;
  mpz_t counter;
  int found = 0;

  mpz_init(counter);
  element_init(g0, G);
  element_init(snark, G);
  element_init(asum, Zr);
  element_init(bsum, Zr);
  darray_init(hole);
  //set up multipliers
  for (i = 0; i < s; i++) {
    element_init(a[i], Zr);
    element_init(b[i], Zr);
    element_init(m[i], G);
    element_random(a[i]);
    element_random(b[i]);
    element_pow_zn(g0, g, a[i]);
    element_pow_zn(m[i], h, b[i]);
    element_mul(m[i], m[i], g0);
  }

  element_random(asum);
  element_random(bsum);
  element_pow_zn(g0, g, asum);
  element_pow_zn(snark, h, bsum);
  element_mul(snark, snark, g0);

  record(asum, bsum, snark, hole, counter);
  for (;;) {
    int len = element_length_in_bytes(snark);
    unsigned char *buf = pbc_malloc(len);
    unsigned char hash = 0;

    element_to_bytes(buf, snark);
    for (i = 0; i < len; i++) {
      hash += buf[i];
    }
    i = hash % s;
    pbc_free(buf);

    element_mul(snark, snark, m[i]);
    element_add(asum, asum, a[i]);
    element_add(bsum, bsum, b[i]);

    for (i = 0; i < hole->count; i++) {
      snapshot_ptr ss = hole->item[i];
      if (!element_cmp(snark, ss->snark)) {
        element_sub(bsum, bsum, ss->b);
        element_sub(asum, ss->a, asum);
        //answer is x such that x * bsum = asum
        //complications arise if gcd(bsum, r) > 1
        //which can happen if r is not prime
        if (!mpz_probab_prime_p(Zr->order, 10)) {
          mpz_t za, zb, zd, zm;

          mpz_init(za);
          mpz_init(zb);
          mpz_init(zd);
          mpz_init(zm);

          element_to_mpz(za, asum);
          element_to_mpz(zb, bsum);
          mpz_gcd(zd, zb, Zr->order);
          mpz_divexact(zm, Zr->order, zd);
          mpz_divexact(zb, zb, zd);
          //if zd does not divide za there is no solution
          mpz_divexact(za, za, zd);
          mpz_invert(zb, zb, zm);
          mpz_mul(zb, za, zb);
          mpz_mod(zb, zb, zm);
          do {
            element_pow_mpz(g0, g, zb);
            if (!element_cmp(g0, h)) {
              element_set_mpz(x, zb);
              break;
            }
            mpz_add(zb, zb, zm);
            mpz_sub_ui(zd, zd, 1);
          } while (mpz_sgn(zd));
          mpz_clear(zm);
          mpz_clear(za);
          mpz_clear(zb);
          mpz_clear(zd);
        } else {
          element_div(x, asum, bsum);
        }
        found = 1;
        break;
      }
    }
    if (found) break;

    mpz_add_ui(counter, counter, 1);
    if (mpz_tstbit(counter, interval)) {
      record(asum, bsum, snark, hole, counter);
      interval++;
    }
  }

  for (i = 0; i < s; i++) {
    element_clear(a[i]);
    element_clear(b[i]);
    element_clear(m[i]);
  }
  element_clear(g0);
  element_clear(snark);
  for (i = 0; i < hole->count; i++) {
    snapshot_ptr ss = hole->item[i];
    element_clear(ss->a);
    element_clear(ss->b);
    element_clear(ss->snark);
    pbc_free(ss);
  }
  darray_clear(hole);
  element_clear(asum);
  element_clear(bsum);
  mpz_clear(counter);
}
Beispiel #30
0
// Miller's algorithm, assuming we can ignore the denominator. We can do this
// with careful group selection when the embedding degree is even. See thesis.
// This version uses projective coordinates, which don't seem much faster.
static void cc_miller_no_denom_proj(element_t res, mpz_t q, element_t P,
    element_ptr Qx, element_ptr Qy) {
  mp_bitcnt_t m;
  element_t v;
  element_t Z;
  element_t a, b, c;
  element_t t0, t1;
  element_ptr t2 = a, t3 = b, t4 = c;
  element_t e0;
  element_t z, z2;
  element_ptr Zx, Zy;
  const element_ptr curve_a = curve_a_coeff(P);
  const element_ptr Px = curve_x_coord(P);
  const element_ptr Py = curve_y_coord(P);

  #define proj_double() {             \
    /* t0 = 3x^2 + (curve_a) z^4 */   \
    element_square(t0, Zx);           \
    /* element_mul_si(t0, t0, 3); */  \
    element_double(t1, t0);           \
    element_add(t0, t0, t1);          \
    element_square(t1, z2);           \
    element_mul(t1, t1, curve_a);     \
    element_add(t0, t0, t1);          \
                                      \
    /* z_out = 2 y z */               \
    element_mul(z, Zy, z);            \
    /* element_mul_si(z, z, 2); */    \
    element_double(z, z);             \
    element_square(z2, z);            \
                                      \
    /* t1 = 4 x y^2 */                \
    element_square(t2, Zy);           \
    element_mul(t1, Zx, t2);          \
    /* element_mul_si(t1, t1, 4); */  \
    element_double(t1, t1);           \
    element_double(t1, t1);           \
                                      \
    /* x_out = t0^2 - 2 t1 */         \
    /* element_mul_si(t3, t1, 2); */  \
    element_double(t3, t1);           \
    element_square(Zx, t0);           \
    element_sub(Zx, Zx, t3);          \
                                      \
    /* t2 = 8y^4 */                   \
    element_square(t2, t2);           \
    /* element_mul_si(t2, t2, 8); */  \
    element_double(t2, t2);           \
    element_double(t2, t2);           \
    element_double(t2, t2);           \
                                      \
    /* y_out = t0(t1 - x_out) - t2 */ \
    element_sub(t1, t1, Zx);          \
    element_mul(t0, t0, t1);          \
    element_sub(Zy, t0, t2);          \
  }

  #define proj_mixin() {                        \
    /* t2 = Px z^2 */                           \
    element_mul(t2, z2, Px);                    \
                                                \
    /* t3 = Zx - t2 */                          \
    element_sub(t3, Zx, t2);                    \
                                                \
    /* t0 = Py z^3 */                           \
    element_mul(t0, z2, Py);                    \
    element_mul(t0, t0, z);                     \
                                                \
    /* t1 = Zy - t0 */                          \
    element_sub(t1, Zy, t0);                    \
                                                \
    /* e7 = Zx + t2, use t2 to double for e7 */ \
    element_add(t2, Zx, t2);                    \
                                                \
    /* e8 = Zy + t0, use t0 to double for e8 */ \
    element_add(t0, Zy, t0);                    \
                                                \
    /* z = z t3 */                              \
    element_mul(z, z, t3);                      \
    element_square(z2, z);                      \
                                                \
    /* Zx = t1^2 - e7 t3^2 */                   \
    /* t3 now holds t3^3, */                    \
    /* t4 holds e7 t3^2. */                     \
    element_square(t4, t3);                     \
    element_mul(t3, t4, t3);                    \
    element_square(Zx, t1);                     \
    element_mul(t4, t2, t4);                    \
    element_sub(Zx, Zx, t4);                    \
                                                \
    /* t4 = e7 t3^2 - 2 Zx */                   \
    element_sub(t4, t4, Zx);                    \
    element_sub(t4, t4, Zx);                    \
                                                \
    /* Zy = (t4 t1 - e8 t3^3)/2 */              \
    element_mul(t4, t4, t1);                    \
    element_mul(t0, t0, t3);                    \
    element_sub(t4, t4, t0);                    \
    element_halve(Zy, t4);                      \
  }

  #define do_tangent() {                  \
    /* a = -(3x^2 + cca z^4) */           \
    /* b = 2 y z^3 */                     \
    /* c = -(2 y^2 + x a) */              \
    /* a = z^2 a */                       \
    element_square(a, z2);                \
    element_mul(a, a, curve_a);           \
    element_square(b, Zx);                \
    /* element_mul_si(b, b, 3); */        \
    element_double(t0, b);                \
    element_add(b, b, t0);                \
    element_add(a, a, b);                 \
    element_neg(a, a);                    \
                                          \
    element_mul(b, z, z2);                \
    element_mul(b, b, Zy);                \
    element_mul_si(b, b, 2);              \
                                          \
    element_mul(c, Zx, a);                \
    element_mul(a, a, z2);                \
    element_square(t0, Zy);               \
    element_mul_si(t0, t0, 2);            \
    element_add(c, c, t0);                \
    element_neg(c, c);                    \
                                          \
    d_miller_evalfn(e0, a, b, c, Qx, Qy); \
    element_mul(v, v, e0);                \
  }

  #define do_line() {                     \
    /* a = -(Py z^3 - Zy) */              \
    /* b = Px z^3 - Zx z */               \
    /* c = Zx z Py - Zy Px; */            \
                                          \
    element_mul(t0, Zx, z);               \
    element_mul(t1, z2, z);               \
                                          \
    element_mul(a, Py, t1);               \
    element_sub(a, Zy, a);                \
                                          \
    element_mul(b, Px, t1);               \
    element_sub(b, b, t0);                \
                                          \
    element_mul(t0, t0, Py);              \
    element_mul(c, Zy, Px);               \
    element_sub(c, t0, c);                \
                                          \
    d_miller_evalfn(e0, a, b, c, Qx, Qy); \
    element_mul(v, v, e0);                \
  }

  element_init(a, Px->field);
  element_init(b, a->field);
  element_init(c, a->field);
  element_init(t0, a->field);
  element_init(t1, a->field);
  element_init(e0, res->field);
  element_init(z, a->field);
  element_init(z2, a->field);
  element_set1(z);
  element_set1(z2);

  element_init(v, res->field);
  element_init(Z, P->field);

  element_set(Z, P);
  Zx = curve_x_coord(Z);
  Zy = curve_x_coord(Z);

  element_set1(v);
  m = (mp_bitcnt_t)mpz_sizeinbase(q, 2);
  m = (m > 2 ? m - 2 : 0);

  for(;;) {
    do_tangent();
    if (!m) break;
    proj_double();
    if (mpz_tstbit(q, m)) {
      do_line();
      proj_mixin();
    }
    m--;
    element_square(v, v);
  }

  element_set(res, v);

  element_clear(v);
  element_clear(Z);
  element_clear(a);
  element_clear(b);
  element_clear(c);
  element_clear(t0);
  element_clear(t1);
  element_clear(e0);
  element_clear(z);
  element_clear(z2);
  #undef proj_double
  #undef proj_mixin
  #undef do_tangent
  #undef do_line
}