예제 #1
0
파일: fmpz.c 프로젝트: hperl/flint
void fmpz_invert(fmpz_t res, fmpz_t x, fmpz_t m)
{
   if (m[0] == 0)
   {
       printf("Error: division by zero!\n");
       abort();
   }

   fmpz_t s0, U, V, temp;
   unsigned long size = fmpz_size(m);
   // U may use fmpz_size(m) + 1 limbs after the sum, and gmp requires +1
   U = fmpz_init(size + 2);
   V = fmpz_init(size + 2);
   s0 = fmpz_init(size + 2);
   temp = fmpz_init(size + 2);

   // U := (x%m) + abs(m)
   // V := abs(m)
   fmpz_abs(V, m);
   fmpz_mod(U, x, V);
   fmpz_add(U, U, V);

   // Compute s0 such that 1 = s0 * x  %  m
   mpn_gcdext(temp+1, s0+1, (long *) s0, U+1, fmpz_size(U), V+1, fmpz_size(V));
   fmpz_mod(res, s0, m);

   fmpz_clear(temp);
   fmpz_clear(s0);
   fmpz_clear(V);
   fmpz_clear(U);
}
예제 #2
0
static int
ref_modinv (mp_limb_t *rp, const mp_limb_t *ap, const mp_limb_t *mp, mp_size_t mn)
{
  mp_limb_t tp[4*(mn+1)];
  mp_limb_t *up = tp;
  mp_limb_t *vp = tp + mn+1;
  mp_limb_t *gp = tp + 2*(mn+1);
  mp_limb_t *sp = tp + 3*(mn+1);
  mp_size_t gn, sn;

  mpn_copyi (up, ap, mn);
  mpn_copyi (vp, mp, mn);
  gn = mpn_gcdext (gp, sp, &sn, up, mn, vp, mn);
  if (gn != 1 || gp[0] != 1)
    return 0;
  
  if (sn < 0)
    mpn_sub (sp, mp, mn, sp, -sn);
  else if (sn < mn)
    /* Zero-pad. */
    mpn_zero (sp + sn, mn - sn);

  mpn_copyi (rp, sp, mn);
  return 1;
}
예제 #3
0
void fp_invn_low(dig_t *c, const dig_t *a) {
	mp_size_t cn;
	align dig_t s[FP_DIGS], t[2 * FP_DIGS], u[FP_DIGS + 1];

#if FP_RDC == MONTY
	dv_zero(t + FP_DIGS, FP_DIGS);
	dv_copy(t, a, FP_DIGS);
	fp_rdcn_low(u, t);
#else
	fp_copy(u, a);
#endif

	dv_copy(s, fp_prime_get(), FP_DIGS);

	mpn_gcdext(t, c, &cn, u, FP_DIGS, s, FP_DIGS);
	if (cn < 0) {
		dv_zero(c - cn, FP_DIGS + cn);
		mpn_sub_n(c, fp_prime_get(), c, FP_DIGS);
	} else {
		dv_zero(c + cn, FP_DIGS - cn);
	}

#if FP_RDC == MONTY
	dv_zero(t, FP_DIGS);
	dv_copy(t + FP_DIGS, c, FP_DIGS);
	mpn_tdiv_qr(u, c, 0, t, 2 * FP_DIGS, fp_prime_get(), FP_DIGS);
#endif
}
예제 #4
0
static int
modinv_gcd (const struct ecc_curve *ecc,
	    mp_limb_t *rp, mp_limb_t *ap, mp_limb_t *tp)
{
  mp_size_t size = ecc->p.size;
  mp_limb_t *up = tp;
  mp_limb_t *vp = tp + size+1;
  mp_limb_t *gp = tp + 2*(size+1);
  mp_limb_t *sp = tp + 3*(size+1);
  mp_size_t gn, sn;

  mpn_copyi (up, ap, size);
  mpn_copyi (vp, ecc->p.m, size);
  gn = mpn_gcdext (gp, sp, &sn, up, size, vp, size);
  if (gn != 1 || gp[0] != 1)
    return 0;
  
  if (sn < 0)
    mpn_sub (sp, ecc->p.m, size, sp, -sn);
  else if (sn < size)
    /* Zero-pad. */
    mpn_zero (sp + sn, size - sn);

  mpn_copyi (rp, sp, size);
  return 1;
}
예제 #5
0
int mpfq_p_127_735_inv(mpfq_p_127_735_dst_field k, mpfq_p_127_735_dst_elt z, mpfq_p_127_735_src_elt x) {
#if 1
  invmod_2(z, x, k->p);
#else
  mp_limb_t s1[2+1], s2[2+1];
  mp_limb_t r1[2+1], r2[2+1];
  mp_size_t r1n, r2n;
  int i;

  add_2(s1, x, k->p);
  mpfq_p_127_735_copy(k, s2, k->p);

  if (cmp_2(s1, s2) == 0) {
    fprintf(stderr, "error in inv_fp_2: division by 0\n");
    exit(1);
  }

  assert (cmp_2(s1, s2) > 0);

  r1n = mpn_gcdext(r1, r2, &r2n, s1, 2, s2, 2);

  // Non invertible element ?
  if ((r1n != 1) || (r1[0] != 1UL)) {
    fprintf(stderr, "warning in inv_fp_2: non invertible element\n");
    if ((r1n <= 1) && (r1[0] == 0UL)) {
      fprintf(stderr, "hum... in fact this is a division by 0\n");
      exit(1);
    } else {
      mpn2mpz(k->factor, r1, r1n);
      return 1;
    }
  }

  // OK. GCD is one. make the result positive and put it in z.
  assert ((r1n == 1) && (r1[0] == 1UL));

  if (r2n < 0) {
    for (i = -r2n; i < 2; ++i)
      r2[i] = 0UL;
    sub_2(r2, k->p, r2);
  } else {
    for (i = r2n; i < 2; ++i)
      r2[i] = 0UL;
  }

  mpfq_p_127_735_copy(k, z, r2);
#endif
}
예제 #6
0
파일: modp.cpp 프로젝트: lance6716/SPDZ-2
void Inv(modp& ans,const modp& x,const Zp_Data& ZpD)
{ 
  mp_limb_t g[MAX_MOD_SZ],xx[MAX_MOD_SZ],yy[MAX_MOD_SZ];
  mp_size_t sz;
  mpn_copyi(xx,x.x,ZpD.t);
  mpn_copyi(yy,ZpD.prA,ZpD.t);
  mpn_gcdext(g,ans.x,&sz,xx,ZpD.t,yy,ZpD.t);
  if (sz<0)
    { mpn_sub(ans.x,ZpD.prA,ZpD.t,ans.x,-sz); 
      sz=-sz;
    }
  else
    { for (int i=sz; i<ZpD.t; i++) { ans.x[i]=0; } }
  if (ZpD.montgomery)
    { ZpD.Mont_Mult(ans.x,ans.x,ZpD.R3); }
}
예제 #7
0
void
mpz_gcdext (mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_srcptr a, mpz_srcptr b)
{
  mp_size_t asize, bsize, usize, vsize;
  mp_srcptr ap, bp;
  mp_ptr up, vp;
  mp_size_t gsize, ssize, tmp_ssize;
  mp_ptr gp, sp, tmp_gp, tmp_sp;
  mpz_srcptr u, v;
  mpz_ptr ss, tt;
  __mpz_struct stmp, gtmp;
  TMP_DECL;

  TMP_MARK;

  /* mpn_gcdext requires that U >= V.  Therefore, we often have to swap U and
     V.  This in turn leads to a lot of complications.  The computed cofactor
     will be the wrong one, so we have to fix that up at the end.  */

  asize = ABS (SIZ (a));
  bsize = ABS (SIZ (b));
  ap = PTR (a);
  bp = PTR (b);
  if (asize > bsize || (asize == bsize && mpn_cmp (ap, bp, asize) > 0))
    {
      usize = asize;
      vsize = bsize;
      up = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB);
      vp = (mp_ptr) TMP_ALLOC ((vsize + 1) * BYTES_PER_MP_LIMB);
      MPN_COPY (up, ap, usize);
      MPN_COPY (vp, bp, vsize);
      u = a;
      v = b;
      ss = s;
      tt = t;
    }
  else
    {
      usize = bsize;
      vsize = asize;
      up = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB);
      vp = (mp_ptr) TMP_ALLOC ((vsize + 1) * BYTES_PER_MP_LIMB);
      MPN_COPY (up, bp, usize);
      MPN_COPY (vp, ap, vsize);
      u = b;
      v = a;
      ss = t;
      tt = s;
    }

  tmp_gp = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB);
  tmp_sp = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB);

  if (vsize == 0)
    {
      tmp_sp[0] = 1;
      tmp_ssize = 1;
      MPN_COPY (tmp_gp, up, usize);
      gsize = usize;
    }
  else
    gsize = mpn_gcdext (tmp_gp, tmp_sp, &tmp_ssize, up, usize, vp, vsize);
  ssize = ABS (tmp_ssize);

  PTR (&gtmp) = tmp_gp;
  SIZ (&gtmp) = gsize;

  PTR (&stmp) = tmp_sp;
  SIZ (&stmp) = (tmp_ssize ^ SIZ (u)) >= 0 ? ssize : -ssize;

  if (tt != NULL)
    {
      if (SIZ (v) == 0)
	SIZ (tt) = 0;
      else
	{
	  mpz_t x;
	  MPZ_TMP_INIT (x, ssize + usize + 1);
	  mpz_mul (x, &stmp, u);
	  mpz_sub (x, &gtmp, x);
	  mpz_tdiv_q (tt, x, v);
	}
    }

  if (ss != NULL)
    {
      if (ALLOC (ss) < ssize)
	_mpz_realloc (ss, ssize);
      sp = PTR (ss);
      MPN_COPY (sp, tmp_sp, ssize);
      SIZ (ss) = SIZ (&stmp);
    }

  if (ALLOC (g) < gsize)
    _mpz_realloc (g, gsize);
  gp = PTR (g);
  MPN_COPY (gp, tmp_gp, gsize);
  SIZ (g) = gsize;

  TMP_FREE;
}
예제 #8
0
void
mpz_gcdext (mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_srcptr a, mpz_srcptr b)
{
  mp_size_t asize, bsize;
  mp_ptr tmp_ap, tmp_bp;
  mp_size_t gsize, ssize, tmp_ssize;
  mp_ptr gp, tmp_gp, tmp_sp;
  TMP_DECL;

  /* mpn_gcdext requires that Usize >= Vsize.  Therefore, we often
     have to swap U and V.  The computed cofactor will be the
     "smallest" one, which is faster to produce.  The wanted one will
     be computed here; this is needed anyway when both are requested.  */

  asize = ABSIZ (a);
  bsize = ABSIZ (b);

  if (asize < bsize)
    {
      MPZ_SRCPTR_SWAP (a, b);
      MP_SIZE_T_SWAP (asize, bsize);
      MPZ_PTR_SWAP (s, t);
    }

  if (bsize == 0)
    {
      /* g = |a|, s = sgn(a), t = 0. */
      ssize = SIZ (a) >= 0 ? (asize != 0) : -1;

      gp = MPZ_REALLOC (g, asize);
      MPN_COPY (gp, PTR (a), asize);
      SIZ (g) = asize;

      if (t != NULL)
	SIZ (t) = 0;
      if (s != NULL)
	{
	  SIZ (s) = ssize;
	  PTR (s)[0] = 1;
	}
      return;
    }

  TMP_MARK;

  TMP_ALLOC_LIMBS_2 (tmp_ap, asize, tmp_bp, bsize);
  MPN_COPY (tmp_ap, PTR (a), asize);
  MPN_COPY (tmp_bp, PTR (b), bsize);

  TMP_ALLOC_LIMBS_2 (tmp_gp, bsize, tmp_sp, bsize + 1);

  gsize = mpn_gcdext (tmp_gp, tmp_sp, &tmp_ssize, tmp_ap, asize, tmp_bp, bsize);

  ssize = ABS (tmp_ssize);
  tmp_ssize = SIZ (a) >= 0 ? tmp_ssize : -tmp_ssize;

  if (t != NULL)
    {
      mpz_t x;
      __mpz_struct gtmp, stmp;

      PTR (&gtmp) = tmp_gp;
      SIZ (&gtmp) = gsize;

      PTR (&stmp) = tmp_sp;
      SIZ (&stmp) = tmp_ssize;

      MPZ_TMP_INIT (x, ssize + asize + 1);
      mpz_mul (x, &stmp, a);
      mpz_sub (x, &gtmp, x);
      mpz_divexact (t, x, b);
    }

  if (s != NULL)
    {
      mp_ptr sp;

      sp = MPZ_REALLOC (s, ssize);
      MPN_COPY (sp, tmp_sp, ssize);
      SIZ (s) = tmp_ssize;
    }

  gp = MPZ_REALLOC (g, gsize);
  MPN_COPY (gp, tmp_gp, gsize);
  SIZ (g) = gsize;

  TMP_FREE;
}