[Gmp-commit] /var/hg/gmp: Construct temporary mpq from double on the stack, a...
mercurial at gmplib.org
mercurial at gmplib.org
Sun Feb 17 22:23:30 CET 2013
details: /var/hg/gmp/rev/7081a2d8e439
changeset: 15454:7081a2d8e439
user: Marc Glisse <marc.glisse at inria.fr>
date: Sun Feb 17 22:23:22 2013 +0100
description:
Construct temporary mpq from double on the stack, as is already the case for mpz.
diffstat:
ChangeLog | 7 +++
gmpxx.h | 121 ++++++++++++---------------------------------------
tests/cxx/t-ops2.cc | 10 ++++
3 files changed, 45 insertions(+), 93 deletions(-)
diffs (249 lines):
diff -r 23c4a66dd85c -r 7081a2d8e439 ChangeLog
--- a/ChangeLog Sun Feb 17 21:07:38 2013 +0100
+++ b/ChangeLog Sun Feb 17 22:23:22 2013 +0100
@@ -13,6 +13,13 @@
* tests/cxx/t-ops2.cc: Comment about more tests. Use <math.h> rather
than <cmath> and using namespace. Don't include <iostream>.
+ * gmpxx.h (__GMPXX_BITS_TO_LIMBS, __GMPQ_NUM_DBL_LIMBS,
+ __GMPQ_DEN_DBL_LIMBS, __GMPXX_TMPQ_D): New macros.
+ (__gmp_binary_plus, __gmp_binary_minus, __gmp_binary_multiplies,
+ __gmp_binary_divides, __gmp_binary_equal, __gmp_binary_less,
+ __gmp_cmp_function): Use __GMPXX_TMPQ_D.
+ * tests/cxx/t-ops2.cc: Test __GMPXX_TMPQ_D on DBL_MIN, DBL_MAX.
+
2013-02-16 Marc Glisse <marc.glisse at inria.fr>
* gmpxx.h: Include <algorithm>.
diff -r 23c4a66dd85c -r 7081a2d8e439 gmpxx.h
--- a/gmpxx.h Sun Feb 17 21:07:38 2013 +0100
+++ b/gmpxx.h Sun Feb 17 22:23:22 2013 +0100
@@ -58,15 +58,20 @@
#define __GMPXX_NOEXCEPT
#endif
-// Max allocations for plain types when converted to mpz_t
-#define __GMPZ_DBL_LIMBS (2 + DBL_MAX_EXP / GMP_NUMB_BITS)
-
+// Max allocations for plain types when converted to GMP types
#if GMP_NAIL_BITS != 0 && ! defined _LONG_LONG_LIMB
#define __GMPZ_ULI_LIMBS 2
#else
#define __GMPZ_ULI_LIMBS 1
#endif
+#define __GMPXX_BITS_TO_LIMBS(n) (((n) + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS)
+#define __GMPZ_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MAX_EXP)+1
+#define __GMPQ_NUM_DBL_LIMBS __GMPZ_DBL_LIMBS
+#define __GMPQ_DEN_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MANT_DIG+1-DBL_MIN_EXP)+1
+// The final +1s are a security margin. The current implementation of
+// mpq_set_d seems to need it for the denominator.
+
inline void __mpz_set_ui_safe(mpz_ptr p, unsigned long l)
{
p->_mp_size = (l != 0);
@@ -124,6 +129,14 @@
mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS; \
mpq_denref(temp)->_mp_size = 1; \
mpq_denref(temp)->_mp_d[0] = 1
+#define __GMPXX_TMPQ_D \
+ mpq_t temp; \
+ mp_limb_t limbs[__GMPQ_NUM_DBL_LIMBS + __GMPQ_DEN_DBL_LIMBS]; \
+ mpq_numref(temp)->_mp_d = limbs; \
+ mpq_numref(temp)->_mp_alloc = __GMPQ_NUM_DBL_LIMBS; \
+ mpq_denref(temp)->_mp_d = limbs + __GMPQ_NUM_DBL_LIMBS; \
+ mpq_denref(temp)->_mp_alloc = __GMPQ_DEN_DBL_LIMBS; \
+ mpq_set_d (temp, d)
inline unsigned long __gmpxx_abs_ui (signed long l)
{
@@ -216,13 +229,7 @@
static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
{ eval(q, r, l); }
static void eval(mpq_ptr q, mpq_srcptr r, double d)
- {
- mpq_t temp;
- mpq_init(temp);
- mpq_set_d(temp, d);
- mpq_add(q, r, temp);
- mpq_clear(temp);
- }
+ { __GMPXX_TMPQ_D; mpq_add (q, r, temp); }
static void eval(mpq_ptr q, double d, mpq_srcptr r)
{ eval(q, r, d); }
@@ -346,21 +353,9 @@
static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
{ eval(q, r, l); mpq_neg(q, q); }
static void eval(mpq_ptr q, mpq_srcptr r, double d)
- {
- mpq_t temp;
- mpq_init(temp);
- mpq_set_d(temp, d);
- mpq_sub(q, r, temp);
- mpq_clear(temp);
- }
+ { __GMPXX_TMPQ_D; mpq_sub (q, r, temp); }
static void eval(mpq_ptr q, double d, mpq_srcptr r)
- {
- mpq_t temp;
- mpq_init(temp);
- mpq_set_d(temp, d);
- mpq_sub(q, temp, r);
- mpq_clear(temp);
- }
+ { __GMPXX_TMPQ_D; mpq_sub (q, temp, r); }
static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z)
{
@@ -569,13 +564,7 @@
static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
{ eval(q, r, l); }
static void eval(mpq_ptr q, mpq_srcptr r, double d)
- {
- mpq_t temp;
- mpq_init(temp);
- mpq_set_d(temp, d);
- mpq_mul(q, r, temp);
- mpq_clear(temp);
- }
+ { __GMPXX_TMPQ_D; mpq_mul (q, r, temp); }
static void eval(mpq_ptr q, double d, mpq_srcptr r)
{ eval(q, r, d); }
@@ -718,21 +707,9 @@
static void eval(mpq_ptr q, signed long int l, mpq_srcptr r)
{ __GMPXX_TMPQ_SI; mpq_div (q, temp, r); }
static void eval(mpq_ptr q, mpq_srcptr r, double d)
- {
- mpq_t temp;
- mpq_init(temp);
- mpq_set_d(temp, d);
- mpq_div(q, r, temp);
- mpq_clear(temp);
- }
+ { __GMPXX_TMPQ_D; mpq_div (q, r, temp); }
static void eval(mpq_ptr q, double d, mpq_srcptr r)
- {
- mpq_t temp;
- mpq_init(temp);
- mpq_set_d(temp, d);
- mpq_div(q, temp, r);
- mpq_clear(temp);
- }
+ { __GMPXX_TMPQ_D; mpq_div (q, temp, r); }
static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h)
{ mpf_div(f, g, h); }
@@ -909,19 +886,9 @@
static bool eval(signed long int l, mpq_srcptr q)
{ return eval(q, l); }
static bool eval(mpq_srcptr q, double d)
- {
- bool b;
- mpq_t temp;
- mpq_init(temp);
- mpq_set_d(temp, d);
- b = (mpq_equal(q, temp) != 0);
- mpq_clear(temp);
- return b;
- }
+ { __GMPXX_TMPQ_D; return mpq_equal (q, temp) != 0; }
static bool eval(double d, mpq_srcptr q)
- {
- return eval(q, d);
- }
+ { return eval(q, d); }
static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) == 0; }
@@ -967,25 +934,9 @@
static bool eval(signed long int l, mpq_srcptr q)
{ return mpq_cmp_si(q, l, 1) > 0; }
static bool eval(mpq_srcptr q, double d)
- {
- bool b;
- mpq_t temp;
- mpq_init(temp);
- mpq_set_d(temp, d);
- b = (mpq_cmp(q, temp) < 0);
- mpq_clear(temp);
- return b;
- }
+ { __GMPXX_TMPQ_D; return mpq_cmp (q, temp) < 0; }
static bool eval(double d, mpq_srcptr q)
- {
- bool b;
- mpq_t temp;
- mpq_init(temp);
- mpq_set_d(temp, d);
- b = (mpq_cmp(temp, q) < 0);
- mpq_clear(temp);
- return b;
- }
+ { __GMPXX_TMPQ_D; return mpq_cmp (temp, q) < 0; }
static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) < 0; }
@@ -1133,25 +1084,9 @@
static int eval(signed long int l, mpq_srcptr q)
{ return -mpq_cmp_si(q, l, 1); }
static int eval(mpq_srcptr q, double d)
- {
- int i;
- mpq_t temp;
- mpq_init(temp);
- mpq_set_d(temp, d);
- i = mpq_cmp(q, temp);
- mpq_clear(temp);
- return i;
- }
+ { __GMPXX_TMPQ_D; return mpq_cmp (q, temp); }
static int eval(double d, mpq_srcptr q)
- {
- int i;
- mpq_t temp;
- mpq_init(temp);
- mpq_set_d(temp, d);
- i = mpq_cmp(temp, q);
- mpq_clear(temp);
- return i;
- }
+ { __GMPXX_TMPQ_D; return mpq_cmp (temp, q); }
static int eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g); }
diff -r 23c4a66dd85c -r 7081a2d8e439 tests/cxx/t-ops2.cc
--- a/tests/cxx/t-ops2.cc Sun Feb 17 21:07:38 2013 +0100
+++ b/tests/cxx/t-ops2.cc Sun Feb 17 22:23:22 2013 +0100
@@ -129,6 +129,9 @@
ASSERT_ALWAYS(sgn(mpz_class(0))==0);
ASSERT_ALWAYS(sgn(mpz_class(9))==1);
ASSERT_ALWAYS(sgn(mpz_class(-17))==-1);
+ ASSERT_ALWAYS(mpz_class(1)+DBL_MAX>2);
+ ASSERT_ALWAYS(mpz_class(1)+DBL_MIN<2);
+ ASSERT_ALWAYS(mpz_class(1)+std::numeric_limits<double>::denorm_min()<2);
}
template<class T>
@@ -175,6 +178,11 @@
ASSERT_ALWAYS(sgn(T(0))==0);
ASSERT_ALWAYS(sgn(T(9))==1);
ASSERT_ALWAYS(sgn(T(-17))==-1);
+ ASSERT_ALWAYS(T(1)+DBL_MAX>2);
+ ASSERT_ALWAYS(T(1)+DBL_MIN>1);
+ ASSERT_ALWAYS(T(1)+DBL_MIN<1.001);
+ ASSERT_ALWAYS(T(1)+std::numeric_limits<double>::denorm_min()>1);
+ ASSERT_ALWAYS(T(1)+std::numeric_limits<double>::denorm_min()<1.001);
}
void checkf (){
@@ -236,6 +244,8 @@
{
tests_start();
+ // Enough precision for 1 + denorm_min
+ mpf_set_default_prec(DBL_MANT_DIG-DBL_MIN_EXP+42);
checkz();
checkqf<mpq_class>();
checkqf<mpf_class>();
More information about the gmp-commit
mailing list