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; }
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; }