[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