summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2016-10-28 21:51:33 +0200
committerMarc Glisse <marc.glisse@inria.fr>2016-10-28 21:51:33 +0200
commit4225225d5de516221eb771aacf5cc0615da96787 (patch)
tree0675d96fd2620a29c76d0913286b2c2964079428
parentffb534049ff90767cd30e562930d67a6529d1908 (diff)
downloadgmp-4225225d5de516221eb771aacf5cc0615da96787.tar.gz
Optimize 1/q to call mpq_inv.
Also handle (-1)/q and 0/q. We could test for l == 1 at runtime and not just with __builtin_constant_p, it might be worth it, especially for non-gcc compilers.
-rw-r--r--ChangeLog5
-rw-r--r--gmpxx.h29
-rw-r--r--tests/cxx/t-ops.cc10
3 files changed, 42 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index a34424d92..f9e63e783 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2016-10-28 Marc Glisse <marc.glisse@inria.fr>
+
+ * gmpxx.h (__gmp_binary_divides): Let 1/q call mpq_inv.
+ * tests/cxx/t-ops.cc (check_mpq): Test it.
+
2016-08-29 Torbjörn Granlund <tg@gmplib.org>
* All C files: Include just gmp-impl.h, make gmp-impl.h grab gmp.h.
diff --git a/gmpxx.h b/gmpxx.h
index 10b655add..389c0d424 100644
--- a/gmpxx.h
+++ b/gmpxx.h
@@ -689,7 +689,17 @@ struct __gmp_binary_divides
}
}
static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r)
- { __GMPXX_TMPQ_UI; mpq_div (q, temp, r); }
+ {
+ if (__GMPXX_CONSTANT_TRUE(l == 0))
+ mpq_set_ui(q, 0, 1);
+ else if (__GMPXX_CONSTANT_TRUE(l == 1))
+ mpq_inv(q, r);
+ else
+ {
+ __GMPXX_TMPQ_UI;
+ mpq_div (q, temp, r);
+ }
+ }
static void eval(mpq_ptr q, mpq_srcptr r, signed long int l)
{
if (__GMPXX_CONSTANT_TRUE(l >= 0))
@@ -706,7 +716,22 @@ struct __gmp_binary_divides
}
}
static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
- { __GMPXX_TMPQ_SI; mpq_div (q, temp, r); }
+ {
+ if (__GMPXX_CONSTANT_TRUE(l == 0))
+ mpq_set_ui(q, 0, 1);
+ else if (__GMPXX_CONSTANT_TRUE(l == 1))
+ mpq_inv(q, r);
+ else if (__GMPXX_CONSTANT_TRUE(l == -1))
+ {
+ mpq_inv(q, r);
+ mpq_neg(q, q);
+ }
+ else
+ {
+ __GMPXX_TMPQ_SI;
+ mpq_div (q, temp, r);
+ }
+ }
static void eval(mpq_ptr q, mpq_srcptr r, double d)
{ __GMPXX_TMPQ_D; mpq_div (q, r, temp); }
static void eval(mpq_ptr q, double d, mpq_srcptr r)
diff --git a/tests/cxx/t-ops.cc b/tests/cxx/t-ops.cc
index a86da6036..ecc6bd07f 100644
--- a/tests/cxx/t-ops.cc
+++ b/tests/cxx/t-ops.cc
@@ -502,6 +502,16 @@ check_mpq (void)
mpq_class c;
c = a / b; ASSERT_ALWAYS(c == 0.75);
}
+ {
+ mpq_class one = 1;
+ mpq_class x(2, 5);
+ ASSERT_ALWAYS(1 / x == one / x);
+ ASSERT_ALWAYS(1u / x == one / x);
+ x = (-1) / x;
+ ASSERT_ALWAYS(x == -2.5);
+ ASSERT_ALWAYS(0 / x == 0);
+ ASSERT_ALWAYS(0u / x == 0);
+ }
// operator<<
// operator>>