summaryrefslogtreecommitdiff
path: root/mpz/divegcd.c
diff options
context:
space:
mode:
authorTorbjorn Granlund <tege@gmplib.org>2011-03-01 19:14:49 +0100
committerTorbjorn Granlund <tege@gmplib.org>2011-03-01 19:14:49 +0100
commit4a13a2fcdb18ec51a4ba871b6c29173df22e6eef (patch)
treebb1bf38662524416581ba2f8a9d25e743ecda0f5 /mpz/divegcd.c
parent5667f05683ef0faa033de1dd2aa2af42584c2f45 (diff)
downloadgmp-4a13a2fcdb18ec51a4ba871b6c29173df22e6eef.tar.gz
Rewrite, as per Marc Glisse's suggestion.
Diffstat (limited to 'mpz/divegcd.c')
-rw-r--r--mpz/divegcd.c100
1 files changed, 46 insertions, 54 deletions
diff --git a/mpz/divegcd.c b/mpz/divegcd.c
index 49257aec2..c67e76972 100644
--- a/mpz/divegcd.c
+++ b/mpz/divegcd.c
@@ -49,62 +49,77 @@ static void
mpz_divexact_by3 (mpz_ptr q, mpz_srcptr a)
{
mp_size_t size = SIZ(a);
- if (size == 0)
- {
- SIZ(q) = 0;
- return;
- }
- else
- {
- mp_size_t abs_size = ABS(size);
- mp_ptr qp;
+ mp_size_t abs_size = ABS(size);
+ mp_ptr qp;
- MPZ_REALLOC (q, abs_size);
+ MPZ_REALLOC (q, abs_size);
- qp = PTR(q);
- mpn_bdiv_dbm1 (qp, PTR(a), abs_size, GMP_NUMB_MASK / 3);
+ qp = PTR(q);
+ mpn_bdiv_dbm1 (qp, PTR(a), abs_size, GMP_NUMB_MASK / 3);
- abs_size -= (qp[abs_size-1] == 0);
- SIZ(q) = (size>0 ? abs_size : -abs_size);
- }
+ abs_size -= (qp[abs_size-1] == 0);
+ SIZ(q) = (size>0 ? abs_size : -abs_size);
}
#endif
+
#if GMP_NUMB_BITS % 4 == 0
static void
mpz_divexact_by5 (mpz_ptr q, mpz_srcptr a)
{
mp_size_t size = SIZ(a);
- if (size == 0)
- {
- SIZ(q) = 0;
- return;
- }
- else
- {
- mp_size_t abs_size = ABS(size);
- mp_ptr qp;
+ mp_size_t abs_size = ABS(size);
+ mp_ptr qp;
- MPZ_REALLOC (q, abs_size);
+ MPZ_REALLOC (q, abs_size);
- qp = PTR(q);
- mpn_bdiv_dbm1 (qp, PTR(a), abs_size, GMP_NUMB_MASK / 5);
+ qp = PTR(q);
+ mpn_bdiv_dbm1 (qp, PTR(a), abs_size, GMP_NUMB_MASK / 5);
- abs_size -= (qp[abs_size-1] == 0);
- SIZ(q) = (size>0 ? abs_size : -abs_size);
- }
+ abs_size -= (qp[abs_size-1] == 0);
+ SIZ(q) = (size>0 ? abs_size : -abs_size);
}
#endif
+static void
+mpz_divexact_limb (mpz_ptr q, mpz_srcptr a, mp_limb_t d)
+{
+ mp_size_t size = SIZ(a);
+ mp_size_t abs_size = ABS(size);
+ mp_ptr qp;
+
+ MPZ_REALLOC (q, abs_size);
+
+ qp = PTR(q);
+ mpn_divexact_1 (qp, PTR(a), abs_size, d);
+
+ abs_size -= (qp[abs_size-1] == 0);
+ SIZ(q) = (size>0 ? abs_size : -abs_size);
+}
+
void
mpz_divexact_gcd (mpz_ptr q, mpz_srcptr a, mpz_srcptr d)
{
ASSERT (mpz_sgn (d) > 0);
+ if (SIZ(a) == 0)
+ {
+ SIZ(q) = 0;
+ return;
+ }
+
if (SIZ(d) == 1)
{
mp_limb_t dl = PTR(d)[0];
int twos;
+ if ((dl & 1) == 0)
+ {
+ count_trailing_zeros (twos, dl);
+ dl >>= twos;
+ mpz_tdiv_q_2exp (q, a, twos);
+ a = q;
+ }
+
if (dl == 1)
{
if (q != a)
@@ -126,30 +141,7 @@ mpz_divexact_gcd (mpz_ptr q, mpz_srcptr a, mpz_srcptr d)
}
#endif
- count_trailing_zeros (twos, dl);
- dl >>= twos;
- mpz_tdiv_q_2exp (q, a, twos);
-
- if (dl == 1)
- {
- return;
- }
-#if GMP_NUMB_BITS % 2 == 0
- if (dl == 3)
- {
- mpz_divexact_by3 (q, q);
- return;
- }
-#endif
-#if GMP_NUMB_BITS % 4 == 0
- if (dl == 5)
- {
- mpz_divexact_by5 (q, q);
- return;
- }
-#endif
-
- mpz_divexact_ui (q, q, dl);
+ mpz_divexact_limb (q, a, dl);
return;
}