Exemplo n.º 1
0
void
mpn_redc_2 (mp_ptr rp, mp_ptr up, mp_srcptr mp, mp_size_t n, mp_srcptr mip)
{
  mp_limb_t q[2];
  mp_size_t j;
  mp_limb_t upn;
  mp_limb_t cy;

  ASSERT_MPN (up, 2*n);

  if ((n & 1) != 0)
    {
      up[0] = mpn_addmul_1 (up, mp, n, (up[0] * mip[0]) & GMP_NUMB_MASK);
      up++;
    }

  for (j = n - 2; j >= 0; j -= 2)
    {
      umul2low (q[1], q[0], mip[1], mip[0], up[1], up[0]);
      upn = up[n];		/* mpn_addmul_2 overwrites this */
      up[1] = mpn_addmul_2 (up, mp, n, q);
      up[0] = up[n];
      up[n] = upn;
      up += 2;
    }
  cy = mpn_add_n (rp, up, up - n, n);
  if (cy != 0)
    mpn_sub_n (rp, rp, mp, n);
}
Exemplo n.º 2
0
void
mpn_mul_basecase (mp_ptr rp,
		  mp_srcptr up, mp_size_t un,
		  mp_srcptr vp, mp_size_t vn)
{
  ASSERT (un >= vn);
  ASSERT (vn >= 1);
  ASSERT (! MPN_OVERLAP_P (rp, un+vn, up, un));
  ASSERT (! MPN_OVERLAP_P (rp, un+vn, vp, vn));

  /* We first multiply by the low order limb (or depending on optional function
     availability, limbs).  This result can be stored, not added, to rp.  We
     also avoid a loop for zeroing this way.  */

#ifdef HAVE_NATIVE_mpn_mul_2
  if (vn >= 2)
    {
      rp[un + 1] = mpn_mul_2 (rp, up, un, vp);
      rp += 2, vp += 2, vn -= 2;
    }
  else
    {
      rp[un] = mpn_mul_1 (rp, up, un, vp[0]);
      return;
    }
#else
  rp[un] = mpn_mul_1 (rp, up, un, vp[0]);
  rp += 1, vp += 1, vn -= 1;
#endif

  /* Now accumulate the product of up[] and the next higher limb (or depending
     on optional function availability, limbs) from vp[].  */

#define MAX_LEFT MP_SIZE_T_MAX	/* Used to simplify loops into if statements */


#ifdef HAVE_NATIVE_mpn_addmul_6
  while (vn >= 6)
    {
      rp[un + 6 - 1] = mpn_addmul_6 (rp, up, un, vp);
      if (MAX_LEFT == 6)
	return;
      rp += 6, vp += 6, vn -= 6;
      if (MAX_LEFT < 2 * 6)
	break;
    }
#undef MAX_LEFT
#define MAX_LEFT (6 - 1)
#endif

#ifdef HAVE_NATIVE_mpn_addmul_5
  while (vn >= 5)
    {
      rp[un + 5 - 1] = mpn_addmul_5 (rp, up, un, vp);
      if (MAX_LEFT == 5)
	return;
      rp += 5, vp += 5, vn -= 5;
      if (MAX_LEFT < 2 * 5)
	break;
    }
#undef MAX_LEFT
#define MAX_LEFT (5 - 1)
#endif

#ifdef HAVE_NATIVE_mpn_addmul_4
  while (vn >= 4)
    {
      rp[un + 4 - 1] = mpn_addmul_4 (rp, up, un, vp);
      if (MAX_LEFT == 4)
	return;
      rp += 4, vp += 4, vn -= 4;
      if (MAX_LEFT < 2 * 4)
	break;
    }
#undef MAX_LEFT
#define MAX_LEFT (4 - 1)
#endif

#ifdef HAVE_NATIVE_mpn_addmul_3
  while (vn >= 3)
    {
      rp[un + 3 - 1] = mpn_addmul_3 (rp, up, un, vp);
      if (MAX_LEFT == 3)
	return;
      rp += 3, vp += 3, vn -= 3;
      if (MAX_LEFT < 2 * 3)
	break;
    }
#undef MAX_LEFT
#define MAX_LEFT (3 - 1)
#endif

#ifdef HAVE_NATIVE_mpn_addmul_2
  while (vn >= 2)
    {
      rp[un + 2 - 1] = mpn_addmul_2 (rp, up, un, vp);
      if (MAX_LEFT == 2)
	return;
      rp += 2, vp += 2, vn -= 2;
      if (MAX_LEFT < 2 * 2)
	break;
    }
#undef MAX_LEFT
#define MAX_LEFT (2 - 1)
#endif

  while (vn >= 1)
    {
      rp[un] = mpn_addmul_1 (rp, up, un, vp[0]);
      if (MAX_LEFT == 1)
	return;
      rp += 1, vp += 1, vn -= 1;
    }
}
Exemplo n.º 3
0
void
mpn_mul_basecase (mp_ptr rp,
		  mp_srcptr up, mp_size_t un,
		  mp_srcptr vp, mp_size_t vn)
{
  ASSERT (un >= vn);
  ASSERT (vn >= 1);
  ASSERT (! MPN_OVERLAP_P (rp, un+vn, up, un));
  ASSERT (! MPN_OVERLAP_P (rp, un+vn, vp, vn));

  /* We first multiply by the low order limb (or depending on optional function
     availability, limbs).  This result can be stored, not added, to rp.  We
     also avoid a loop for zeroing this way.  */

#if HAVE_NATIVE_mpn_mul_2
  if (vn >= 2)
    {
      rp[un + 1] = mpn_mul_2 (rp, up, un, vp);
      rp += 2, vp += 2, vn -= 2;
    }
  else
    {
      rp[un] = mpn_mul_1 (rp, up, un, vp[0]);
      return;
    }
#else
  rp[un] = mpn_mul_1 (rp, up, un, vp[0]);
  rp += 1, vp += 1, vn -= 1;
#endif

  /* Now accumulate the product of up[] and the next low-order limb (or
     depending on optional function availability, limbs) from vp[0].  */

#define MAX_LEFT MP_SIZE_T_MAX

#if HAVE_NATIVE_mpn_addmul_4
  while (vn >= 4)
    {
      rp[un + 4 - 1] = mpn_addmul_4 (rp, up, un, vp);
      rp += 4, vp += 4, vn -= 4;
    }
#undef MAX_LEFT
#define MAX_LEFT 3
#endif

#if HAVE_NATIVE_mpn_addmul_3
  while (vn >= 3)
    {
      rp[un + 3 - 1] = mpn_addmul_3 (rp, up, un, vp);
      rp += 3, vp += 3, vn -= 3;
      if (MAX_LEFT - 3 <= 3)
	break;
    }
#undef MAX_LEFT
#define MAX_LEFT 2
#endif

#if HAVE_NATIVE_mpn_addmul_2
  while (vn >= 2)
    {
      rp[un + 2 - 1] = mpn_addmul_2 (rp, up, un, vp);
      rp += 2, vp += 2, vn -= 2;
      if (MAX_LEFT - 2 <= 2)
	break;
    }
#undef MAX_LEFT
#define MAX_LEFT 1
#endif

  while (vn >= 1)
    {
      rp[un] = mpn_addmul_1 (rp, up, un, vp[0]);
      rp += 1, vp += 1, vn -= 1;
      if (MAX_LEFT - 1 <= 1)
	break;
    }
}
Exemplo n.º 4
0
/* (rp, 2n) = (xp, n)*(yp, n) / B^n */ 
inline static void
mpn_mulshort_n_basecase(mp_ptr rp, mp_srcptr xp, mp_srcptr yp, mp_size_t n)
{
  mp_size_t i, k;

  ASSERT(n >= 3);  /* this restriction doesn't make a lot of sense in general */
  ASSERT_MPN(xp, n);
  ASSERT_MPN(yp, n);
  ASSERT(!MPN_OVERLAP_P (rp, 2 * n, xp, n));
  ASSERT(!MPN_OVERLAP_P (rp, 2 * n, yp, n));

  k = n - 2; /* so want short product sum_(i + j >= k) x[i]y[j]B^(i + j) */
  i = 0;

  /* Multiply w limbs from y + i to (2 + i + w - 1) limbs from x + (n - 2 - i - w + 1)
     and put it into r + (n - 2 - w + 1), "overflow" (i.e. last) limb into
     r + (n + w - 1) for i between 0 and n - 2.
     i == n - w needs special treatment. */

  /* We first multiply by the low order limb (or depending on optional function
     availability, limbs).  This result can be stored, not added, to rp.  We
     also avoid a loop for zeroing this way.  */

#if HAVE_NATIVE_mpn_mul_2
  rp[n + 1] = mpn_mul_2 (rp + k - 1, xp + k - 1, 2 + 1, yp);
  i += 2;
#else
  rp[n] = mpn_mul_1 (rp + k, xp + k, 2, yp[0]);
  i += 1;
#endif

#if HAVE_NATIVE_mpn_addmul_6
  while (i < n - 6)
    {
      rp[n + i + 6 - 1] = mpn_addmul_6 (rp + k - 6 + 1, xp + k - i - 6 + 1, 2 + i + 6 - 1, yp + i);
      i += 6;
    }
  if (i == n - 6)
    {
      rp[n + n - 1] = mpn_addmul_6 (rp + i, xp, n, yp + i);
      return;
    }
#endif

#if HAVE_NATIVE_mpn_addmul_5
  while (i < n - 5)
    {
      rp[n + i + 5 - 1] = mpn_addmul_5 (rp + k - 5 + 1, xp + k - i - 5 + 1, 2 + i + 5 - 1, yp + i)
      i += 5;
    }
  if (i == n - 5)
    {
      rp[n + n - 1] = mpn_addmul_5 (rp + i, xp, n, yp + i);
      return;
    }
#endif

#if HAVE_NATIVE_mpn_addmul_4
  while (i < n - 4)
    {
      rp[n + i + 4 - 1] = mpn_addmul_4 (rp + k - 4 + 1, xp + k - i - 4 + 1, 2 + i + 4 - 1, yp + i);
      i += 4;
    }
  if (i == n - 4)
    {
      rp[n + n - 1] = mpn_addmul_4 (rp + i, xp, n, yp + i);
      return;
    }
#endif

#if HAVE_NATIVE_mpn_addmul_3
  while (i < n - 3)
    {
      rp[n + i + 3 - 1] = mpn_addmul_3 (rp + k - 3 + 1, xp + k - i - 3 + 1, 2 + i + 3 - 1, yp + i);
      i += 3;
    }
  if (i == n - 3)
    {
      rp[n + n - 1] = mpn_addmul_3 (rp + i, xp, n, yp + i);
      return;
    }
#endif

#if HAVE_NATIVE_mpn_addmul_2
  while (i < n - 2)
    {
      rp[n + i + 2 - 1] = mpn_addmul_2 (rp + k - 2 + 1, xp + k - i - 2 + 1, 2 + i + 2 - 1, yp + i);
      i += 2;
    }
  if (i == n - 2)
    {
      rp[n + n - 1] = mpn_addmul_2 (rp + i, xp, n, yp + i);
      return;
    }
#endif

  while (i < n - 1)
    {
      rp[n + i] = mpn_addmul_1 (rp + k, xp + k - i, 2 + i, yp[i]);
      i += 1;
    }
  rp[n + n - 1] = mpn_addmul_1 (rp + i, xp, n, yp[i]);
  return;
}