Пример #1
0
int
main (int argc, char **argv)
{
  mp_ptr ap, bp, rp, refp;
  gmp_randstate_ptr rands;
  int test;
  TMP_DECL;
  TMP_MARK;

  tests_start ();
  rands = RANDS;

  ap = TMP_ALLOC_LIMBS (MAX_N);
  bp = TMP_ALLOC_LIMBS (MAX_N);
  rp = TMP_ALLOC_LIMBS (MAX_N + 2);
  refp = TMP_ALLOC_LIMBS (MAX_N + 2);

  for (test = 0; test < COUNT; test++)
    {
      mp_size_t an, bn, rn;
      unsigned size_log;

      size_log = 1 + gmp_urandomm_ui (rands, SIZE_LOG);
      an = 1 + gmp_urandomm_ui(rands, 1L << size_log);

      size_log = 1 + gmp_urandomm_ui (rands, SIZE_LOG);
      bn = 1 + gmp_urandomm_ui(rands, 1L << size_log);

      /* Make sure an >= bn */
      if (an < bn)
	MP_SIZE_T_SWAP (an, bn);

      mpn_random2 (ap, an);
      mpn_random2 (bp, bn);

      refmpn_mulmid (refp, ap, an, bp, bn);
      mpn_mulmid (rp, ap, an, bp, bn);

      rn = an + 3 - bn;
      if (mpn_cmp (refp, rp, rn))
	{
	  printf ("ERROR in test %d, an = %d, bn = %d, rn = %d\n",
		  test, (int) an, (int) bn, (int) rn);
	  printf("a: "); mpn_dump (ap, an);
	  printf("b: "); mpn_dump (bp, bn);
	  printf("r:   "); mpn_dump (rp, rn);
	  printf("ref: "); mpn_dump (refp, rn);

	  abort();
	}
    }
  TMP_FREE;
  tests_end ();
  return 0;
}
Пример #2
0
void
mpq_inv (mpq_ptr dest, mpq_srcptr src)
{
  mp_size_t num_size = SIZ(NUM(src));
  mp_size_t den_size = SIZ(DEN(src));

  if (num_size < 0)
    {
      num_size = -num_size;
      den_size = -den_size;
    }
  else if (UNLIKELY (num_size == 0))
    DIVIDE_BY_ZERO;

  SIZ(DEN(dest)) = num_size;
  SIZ(NUM(dest)) = den_size;

  /* If dest == src we may just swap the numerator and denominator;
     we ensured that the new denominator is positive.  */

  if (dest == src)
    {
      MP_PTR_SWAP (PTR(NUM(dest)), PTR(DEN(dest)));
      MP_SIZE_T_SWAP (ALLOC(NUM(dest)), ALLOC(DEN(dest)));
    }
  else
    {
      mp_ptr dp;

      den_size = ABS (den_size);
      dp = MPZ_NEWALLOC (NUM(dest), den_size);
      MPN_COPY (dp, PTR(DEN(src)), den_size);

      dp = MPZ_NEWALLOC (DEN(dest), num_size);
      MPN_COPY (dp, PTR(NUM(src)), num_size);
    }
}
Пример #3
0
void
mpz_mul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
{
  mp_size_t usize;
  mp_size_t vsize;
  mp_size_t wsize;
  mp_size_t sign_product;
  mp_ptr up, vp;
  mp_ptr wp;
  mp_ptr free_me;
  size_t free_me_size;
  mp_limb_t cy_limb;
  TMP_DECL;

  usize = SIZ (u);
  vsize = SIZ (v);
  sign_product = usize ^ vsize;
  usize = ABS (usize);
  vsize = ABS (vsize);

  if (usize < vsize)
    {
      MPZ_SRCPTR_SWAP (u, v);
      MP_SIZE_T_SWAP (usize, vsize);
    }

  if (vsize == 0)
    {
      SIZ (w) = 0;
      return;
    }

#if HAVE_NATIVE_mpn_mul_2
  if (vsize <= 2)
    {
      wp = MPZ_REALLOC (w, usize+vsize);
      if (vsize == 1)
	cy_limb = mpn_mul_1 (wp, PTR (u), usize, PTR (v)[0]);
      else
	{
	  cy_limb = mpn_mul_2 (wp, PTR (u), usize, PTR (v));
	  usize++;
	}
      wp[usize] = cy_limb;
      usize += (cy_limb != 0);
      SIZ (w) = (sign_product >= 0 ? usize : -usize);
      return;
    }
#else
  if (vsize == 1)
    {
      wp = MPZ_REALLOC (w, usize+1);
      cy_limb = mpn_mul_1 (wp, PTR (u), usize, PTR (v)[0]);
      wp[usize] = cy_limb;
      usize += (cy_limb != 0);
      SIZ (w) = (sign_product >= 0 ? usize : -usize);
      return;
    }
#endif

  TMP_MARK;
  free_me = NULL;
  up = PTR (u);
  vp = PTR (v);
  wp = PTR (w);

  /* Ensure W has space enough to store the result.  */
  wsize = usize + vsize;
  if (ALLOC (w) < wsize)
    {
      if (wp == up || wp == vp)
	{
	  free_me = wp;
	  free_me_size = ALLOC (w);
	}
      else
	(*__gmp_free_func) (wp, (size_t) ALLOC (w) * GMP_LIMB_BYTES);

      ALLOC (w) = wsize;
      wp = __GMP_ALLOCATE_FUNC_LIMBS (wsize);
      PTR (w) = wp;
    }
  else
    {
      /* Make U and V not overlap with W.  */
      if (wp == up)
	{
	  /* W and U are identical.  Allocate temporary space for U.  */
	  up = TMP_ALLOC_LIMBS (usize);
	  /* Is V identical too?  Keep it identical with U.  */
	  if (wp == vp)
	    vp = up;
	  /* Copy to the temporary space.  */
	  MPN_COPY (up, wp, usize);
	}
      else if (wp == vp)
	{
	  /* W and V are identical.  Allocate temporary space for V.  */
	  vp = TMP_ALLOC_LIMBS (vsize);
	  /* Copy to the temporary space.  */
	  MPN_COPY (vp, wp, vsize);
	}
    }

  if (up == vp)
    {
      mpn_sqr (wp, up, usize);
      cy_limb = wp[wsize - 1];
    }
  else
    {
      cy_limb = mpn_mul (wp, up, usize, vp, vsize);
    }

  wsize -= cy_limb == 0;

  SIZ (w) = sign_product < 0 ? -wsize : wsize;
  if (free_me != NULL)
    (*__gmp_free_func) (free_me, free_me_size * GMP_LIMB_BYTES);
  TMP_FREE;
}
Пример #4
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;
}
Пример #5
0
REGPARM_ATTR (1) static void
mpz_aorsmul (mpz_ptr w, mpz_srcptr x, mpz_srcptr y, mp_size_t sub)
{
    mp_size_t  xsize, ysize, tsize, wsize, wsize_signed;
    mp_ptr     wp, tp;
    mp_limb_t  c, high;
    TMP_DECL;

    /* w unaffected if x==0 or y==0 */
    xsize = SIZ(x);
    ysize = SIZ(y);
    if (xsize == 0 || ysize == 0)
        return;

    /* make x the bigger of the two */
    if (ABS(ysize) > ABS(xsize))
    {
        MPZ_SRCPTR_SWAP (x, y);
        MP_SIZE_T_SWAP (xsize, ysize);
    }

    sub ^= ysize;
    ysize = ABS(ysize);

    /* use mpn_addmul_1/mpn_submul_1 if possible */
    if (ysize == 1)
    {
        mpz_aorsmul_1 (w, x, PTR(y)[0], sub);
        return;
    }

    sub ^= xsize;
    xsize = ABS(xsize);

    wsize_signed = SIZ(w);
    sub ^= wsize_signed;
    wsize = ABS(wsize_signed);

    tsize = xsize + ysize;
    wp = MPZ_REALLOC (w, MAX (wsize, tsize) + 1);

    if (wsize_signed == 0)
    {
        /* Nothing to add to, just set w=x*y.  No w==x or w==y overlap here,
        since we know x,y!=0 but w==0.  */
        high = mpn_mul (wp, PTR(x),xsize, PTR(y),ysize);
        tsize -= (high == 0);
        SIZ(w) = (sub >= 0 ? tsize : -tsize);
        return;
    }

    TMP_MARK;
    tp = TMP_ALLOC_LIMBS (tsize);

    high = mpn_mul (tp, PTR(x),xsize, PTR(y),ysize);
    tsize -= (high == 0);
    ASSERT (tp[tsize-1] != 0);
    if (sub >= 0)
    {
        mp_srcptr up    = wp;
        mp_size_t usize = wsize;

        if (usize < tsize)
        {
            up	= tp;
            usize = tsize;
            tp	= wp;
            tsize = wsize;

            wsize = usize;
        }

        c = mpn_add (wp, up,usize, tp,tsize);
        wp[wsize] = c;
        wsize += (c != 0);
    }
    else
    {
        mp_srcptr up    = wp;
        mp_size_t usize = wsize;

        if (mpn_cmp_twosizes_lt (up,usize, tp,tsize))
        {
            up	= tp;
            usize = tsize;
            tp	= wp;
            tsize = wsize;

            wsize = usize;
            wsize_signed = -wsize_signed;
        }

        ASSERT_NOCARRY (mpn_sub (wp, up,usize, tp,tsize));
        wsize = usize;
        MPN_NORMALIZE (wp, wsize);
    }

    SIZ(w) = (wsize_signed >= 0 ? wsize : -wsize);

    TMP_FREE;
}