Exemple #1
0
/* Put in {rootp, ceil(un/k)} the kth root of {up, un}, rounded toward zero.
   If remp <> NULL, put in {remp, un} the remainder.
   Return the size (in limbs) of the remainder if remp <> NULL,
	  or a non-zero value iff the remainder is non-zero when remp = NULL.
   Assumes:
   (a) up[un-1] is not zero
   (b) rootp has at least space for ceil(un/k) limbs
   (c) remp has at least space for un limbs (in case remp <> NULL)
   (d) the operands do not overlap.

   The auxiliary memory usage is 3*un+2 if remp = NULL,
   and 2*un+2 if remp <> NULL.  FIXME: This is an incorrect comment.
*/
mp_size_t
mpn_rootrem (mp_ptr rootp, mp_ptr remp,
	     mp_srcptr up, mp_size_t un, mp_limb_t k)
{
  mp_size_t m;
  ASSERT (un > 0);
  ASSERT (up[un - 1] != 0);
  ASSERT (k > 1);

  m = (un - 1) / k;		/* ceil(un/k) - 1 */
  if (remp == NULL && m > 2)
    /* Pad {up,un} with k zero limbs.  This will produce an approximate root
       with one more limb, allowing us to compute the exact integral result. */
    {
      mp_ptr sp, wp;
      mp_size_t rn, sn, wn;
      TMP_DECL;
      TMP_MARK;
      wn = un + k;
      wp = TMP_ALLOC_LIMBS (wn); /* will contain the padded input */
      sn = m + 2; /* ceil(un/k) + 1 */
      sp = TMP_ALLOC_LIMBS (sn); /* approximate root of padded input */
      MPN_COPY (wp + k, up, un);
      MPN_ZERO (wp, k);
      rn = mpn_rootrem_internal (sp, NULL, wp, wn, k, 1);
      /* The approximate root S = {sp,sn} is either the correct root of
	 {sp,sn}, or 1 too large.  Thus unless the least significant limb of
	 S is 0 or 1, we can deduce the root of {up,un} is S truncated by one
	 limb.  (In case sp[0]=1, we can deduce the root, but not decide
	 whether it is exact or not.) */
      MPN_COPY (rootp, sp + 1, sn - 1);
      TMP_FREE;
      return rn;
    }
  else
    {
      return mpn_rootrem_internal (rootp, remp, up, un, k, 0);
    }
}
Exemple #2
0
/* Put in {rootp, ceil(un/k)} the kth root of {up, un}, rounded toward zero.
   If remp <> NULL, put in {remp, un} the remainder.
   Return the size (in limbs) of the remainder if remp <> NULL,
	  or a non-zero value iff the remainder is non-zero when remp = NULL.
   Assumes:
   (a) up[un-1] is not zero
   (b) rootp has at least space for ceil(un/k) limbs
   (c) remp has at least space for un limbs (in case remp <> NULL)
   (d) the operands do not overlap.

   The auxiliary memory usage is 3*un+2 if remp = NULL,
   and 2*un+2 if remp <> NULL.  FIXME: This is an incorrect comment.
*/
mp_size_t
mpn_rootrem (mp_ptr rootp, mp_ptr remp,
	     mp_srcptr up, mp_size_t un, mp_limb_t k)
{
  ASSERT (un > 0);
  ASSERT (up[un - 1] != 0);
  ASSERT (k > 1);

  if ((remp == NULL) && (un / k > 2))
    /* call mpn_rootrem recursively, padding {up,un} with k zero limbs,
       which will produce an approximate root with one more limb,
       so that in most cases we can conclude. */
    {
      mp_ptr sp, wp;
      mp_size_t rn, sn, wn;
      TMP_DECL;
      TMP_MARK;
      wn = un + k;
      wp = TMP_ALLOC_LIMBS (wn); /* will contain the padded input */
      sn = (un - 1) / k + 2; /* ceil(un/k) + 1 */
      sp = TMP_ALLOC_LIMBS (sn); /* approximate root of padded input */
      MPN_COPY (wp + k, up, un);
      MPN_ZERO (wp, k);
      rn = mpn_rootrem_internal (sp, NULL, wp, wn, k, 1);
      /* the approximate root S = {sp,sn} is either the correct root of
	 {sp,sn}, or one too large. Thus unless the least significant limb
	 of S is 0 or 1, we can deduce the root of {up,un} is S truncated by
	 one limb. (In case sp[0]=1, we can deduce the root, but not decide
	 whether it is exact or not.) */
      MPN_COPY (rootp, sp + 1, sn - 1);
      TMP_FREE;
      return rn;
    }
  else /* remp <> NULL */
    {
      return mpn_rootrem_internal (rootp, remp, up, un, k, 0);
    }
}