summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--bootstrap.c1
-rw-r--r--mini-gmp/ChangeLog5
-rw-r--r--mini-gmp/mini-gmp.c32
4 files changed, 39 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 6ad52911b..e0f2a398d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2018-05-20 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * bootstrap.c: Define DONT_USE_FLOAT_H before including mini-gmp.
+
2018-05-14 Marco Bodrato <bodrato@mail.dm.unipi.it>
* mpn/generic/dcpi1_bdiv_q.c (mpn_dcpi1_bdiv_q_n): Decl. static.
diff --git a/bootstrap.c b/bootstrap.c
index 999178e01..5ded7f7f8 100644
--- a/bootstrap.c
+++ b/bootstrap.c
@@ -29,6 +29,7 @@ GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
+#define DONT_USE_FLOAT_H 1
#include "mini-gmp/mini-gmp.c"
#define MIN(l,o) ((l) < (o) ? (l) : (o))
diff --git a/mini-gmp/ChangeLog b/mini-gmp/ChangeLog
index c8a8675fa..58b97426e 100644
--- a/mini-gmp/ChangeLog
+++ b/mini-gmp/ChangeLog
@@ -1,3 +1,8 @@
+2018-05-20 Marco Bodrato <bodrato@mail.dm.unipi.it>
+
+ * mini-gmp.c (mpz_get_d): Convert a fixed number of
+ bits (GMP_DBL_MANT_BITS) to avoid rounding.
+
2018-04-26 Marco Bodrato <bodrato@mail.dm.unipi.it>
* mini-mpq.c: New file, mini-implementation of mpq_t.
diff --git a/mini-gmp/mini-gmp.c b/mini-gmp/mini-gmp.c
index 360bfa942..86c6fa190 100644
--- a/mini-gmp/mini-gmp.c
+++ b/mini-gmp/mini-gmp.c
@@ -50,6 +50,10 @@ see https://www.gnu.org/licenses/. */
#include "mini-gmp.h"
+#if !defined(DONT_USE_FLOAT_H)
+#include <float.h>
+#endif
+
/* Macros */
#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
@@ -71,6 +75,12 @@ see https://www.gnu.org/licenses/. */
#define GMP_CMP(a,b) (((a) > (b)) - ((a) < (b)))
+#if defined(DBL_MANT_DIG) && FLT_RADIX == 2
+#define GMP_DBL_MANT_BITS DBL_MANT_DIG
+#else
+#define GMP_DBL_MANT_BITS (53)
+#endif
+
/* Return non-zero if xp,xsize and yp,ysize overlap.
If xp+xsize<=yp there's no overlap, or if yp+ysize<=xp there's no
overlap. If both these are false, there's an overlap. */
@@ -1689,6 +1699,8 @@ mpz_init_set_d (mpz_t r, double x)
double
mpz_get_d (const mpz_t u)
{
+ int m;
+ mp_limb_t l;
mp_size_t un;
double x;
double B = 2.0 * (double) GMP_LIMB_HIGHBIT;
@@ -1698,9 +1710,23 @@ mpz_get_d (const mpz_t u)
if (un == 0)
return 0.0;
- x = u->_mp_d[--un];
- while (un > 0)
- x = B*x + u->_mp_d[--un];
+ l = u->_mp_d[--un];
+ gmp_clz (m, l);
+ m = m + GMP_DBL_MANT_BITS - GMP_LIMB_BITS;
+ if (m < 0)
+ l &= GMP_LIMB_MAX << -m;
+
+ for (x = l; --un >= 0;)
+ {
+ x = B*x;
+ if (m > 0) {
+ l = u->_mp_d[un];
+ m -= GMP_LIMB_BITS;
+ if (m < 0)
+ l &= GMP_LIMB_MAX << -m;
+ x += l;
+ }
+ }
if (u->_mp_size < 0)
x = -x;