Esempio n. 1
0
int
mpz_congruent_ui_p (mpz_srcptr a, unsigned long cu, unsigned long du)
{
  mp_srcptr  ap;
  mp_size_t  asize;
  mp_limb_t  c, d, r;

  if (UNLIKELY (du == 0))
    return (mpz_cmp_ui (a, cu) == 0);

  asize = SIZ(a);
  if (asize == 0)
    {
      if (cu < du)
        return cu == 0;
      else
        return (cu % du) == 0;
    }

  /* For nails don't try to be clever if c or d is bigger than a limb, just
     fake up some mpz_t's and go to the main mpz_congruent_p.  */
  if (du > GMP_NUMB_MAX || cu > GMP_NUMB_MAX)
    {
      mp_limb_t  climbs[2], dlimbs[2];
      mpz_t      cz, dz;

      ALLOC(cz) = 2;
      PTR(cz) = climbs;
      ALLOC(dz) = 2;
      PTR(dz) = dlimbs;

      mpz_set_ui (cz, cu);
      mpz_set_ui (dz, du);
      return mpz_congruent_p (a, cz, dz);
    }

  /* NEG_MOD works on limbs, so convert ulong to limb */
  c = cu;
  d = du;

  if (asize < 0)
    {
      asize = -asize;
      NEG_MOD (c, c, d);
    }

  ap = PTR (a);

  if (ABOVE_THRESHOLD (asize, BMOD_1_TO_MOD_1_THRESHOLD))
    {
      r = mpn_mod_1 (ap, asize, d);
      if (c < d)
        return r == c;
      else
        return r == (c % d);
    }

  if ((d & 1) == 0)
    {
      /* Strip low zero bits to get odd d required by modexact.  If
         d==e*2^n then a==c mod d if and only if both a==c mod 2^n
         and a==c mod e.  */

      unsigned  twos;

      if ((ap[0]-c) & LOW_ZEROS_MASK (d))
        return 0;

      count_trailing_zeros (twos, d);
      d >>= twos;
    }
Esempio n. 2
0
int
mpz_congruent_p (mpz_srcptr a, mpz_srcptr c, mpz_srcptr d)
{
  mp_size_t  asize, csize, dsize, sign;
  mp_srcptr  ap, cp, dp;
  mp_ptr     xp;
  mp_limb_t  alow, clow, dlow, dmask, r;
  int        result;
  TMP_DECL;

  dsize = SIZ(d);
  if (UNLIKELY (dsize == 0))
    return (mpz_cmp (a, c) == 0);

  dsize = ABS(dsize);
  dp = PTR(d);

  if (ABSIZ(a) < ABSIZ(c))
    MPZ_SRCPTR_SWAP (a, c);

  asize = SIZ(a);
  csize = SIZ(c);
  sign = (asize ^ csize);

  asize = ABS(asize);
  ap = PTR(a);

  if (csize == 0)
    return mpn_divisible_p (ap, asize, dp, dsize);

  csize = ABS(csize);
  cp = PTR(c);

  alow = ap[0];
  clow = cp[0];
  dlow = dp[0];

  /* Check a==c mod low zero bits of dlow.  This might catch a few cases of
     a!=c quickly, and it helps the csize==1 special cases below.  */
  dmask = LOW_ZEROS_MASK (dlow) & GMP_NUMB_MASK;
  alow = (sign >= 0 ? alow : -alow);
  if (((alow-clow) & dmask) != 0)
    return 0;

  if (csize == 1)
    {
      if (dsize == 1)
	{
	cong_1:
	  if (sign < 0)
	    NEG_MOD (clow, clow, dlow);

	  if (ABOVE_THRESHOLD (asize, BMOD_1_TO_MOD_1_THRESHOLD))
	    {
	      r = mpn_mod_1 (ap, asize, dlow);
	      if (clow < dlow)
		return r == clow;
	      else
		return r == (clow % dlow);
	    }

	  if ((dlow & 1) == 0)
	    {
	      /* Strip low zero bits to get odd d required by modexact.  If
		 d==e*2^n then a==c mod d if and only if both a==c mod e and
		 a==c mod 2^n, the latter having been done above.  */
	      unsigned	twos;
	      count_trailing_zeros (twos, dlow);
	      dlow >>= twos;
	    }

	  r = mpn_modexact_1c_odd (ap, asize, dlow, clow);
	  return r == 0 || r == dlow;
	}