int mpn_divisible_p (mp_srcptr ap, mp_size_t asize, mp_srcptr dp, mp_size_t dsize) { mp_limb_t alow, dlow, dmask; mp_ptr qp, rp; mp_size_t i; TMP_DECL; ASSERT (asize >= 0); ASSERT (asize == 0 || ap[asize-1] != 0); ASSERT (dsize >= 1); ASSERT (dp[dsize-1] != 0); ASSERT_MPN (ap, asize); ASSERT_MPN (dp, dsize); /* When a<d only a==0 is divisible. Notice this test covers all cases of asize==0. */ if (asize < dsize) return (asize == 0); /* Strip low zero limbs from d, requiring a==0 on those. */ for (;;) { alow = *ap; dlow = *dp; if (dlow != 0) break; if (alow != 0) return 0; /* a has fewer low zero limbs than d, so not divisible */ /* a!=0 and d!=0 so won't get to size==0 */ asize--; ASSERT (asize >= 1); dsize--; ASSERT (dsize >= 1); ap++; dp++; } /* a must have at least as many low zero bits as d */ dmask = LOW_ZEROS_MASK (dlow); if ((alow & dmask) != 0) return 0; if (dsize == 1) { if (BELOW_THRESHOLD (asize, MODEXACT_1_ODD_THRESHOLD)) return mpn_mod_1 (ap, asize, dlow) == 0; if ((dlow & 1) == 0) { unsigned twos; count_trailing_zeros (twos, dlow); dlow >>= twos; } return mpn_modexact_1_odd (ap, asize, dlow) == 0; }
int mpz_divisible_ui_p (mpz_srcptr a, unsigned long d) { mp_size_t asize; mp_ptr ap; unsigned twos; asize = SIZ(a); if (UNLIKELY (d == 0)) return (asize == 0); if (asize == 0) /* 0 divisible by any d */ return 1; /* For nails don't try to be clever if d is bigger than a limb, just fake up an mpz_t and go to the main mpz_divisible_p. */ if (d > GMP_NUMB_MAX) { mp_limb_t dlimbs[2]; mpz_t dz; ALLOC(dz) = 2; PTR(dz) = dlimbs; mpz_set_ui (dz, d); return mpz_divisible_p (a, dz); } ap = PTR(a); asize = ABS(asize); /* ignore sign of a */ if (ABOVE_THRESHOLD (asize, BMOD_1_TO_MOD_1_THRESHOLD)) return mpn_mod_1 (ap, asize, (mp_limb_t) d) == 0; if (! (d & 1)) { /* Strip low zero bits to get odd d required by modexact. If d==e*2^n and a is divisible by 2^n and by e, then it's divisible by d. */ if ((ap[0] & LOW_ZEROS_MASK (d)) != 0) return 0; count_trailing_zeros (twos, (mp_limb_t) d); d >>= twos; } return mpn_modexact_1_odd (ap, asize, (mp_limb_t) d) == 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; }
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; }