[Gmp-commit] /var/hg/gmp: 2 new changesets

mercurial at gmplib.org mercurial at gmplib.org
Tue Jan 22 21:21:43 CET 2013


details:   /var/hg/gmp/rev/0ae1bdc024cb
changeset: 15337:0ae1bdc024cb
user:      Niels M?ller <nisse at lysator.liu.se>
date:      Tue Jan 22 21:17:19 2013 +0100
description:
mini-gmp: Implemented mpz_cmpabs_d.

details:   /var/hg/gmp/rev/2d7ecf5a6459
changeset: 15338:2d7ecf5a6459
user:      Niels M?ller <nisse at lysator.liu.se>
date:      Tue Jan 22 21:21:39 2013 +0100
description:
mini-gmp: Test mpz_cmp_d and mpz_cmpabs_d.

diffstat:

 ChangeLog                  |   12 +
 mini-gmp/mini-gmp.c        |   48 +++++++
 mini-gmp/mini-gmp.h        |    1 +
 mini-gmp/tests/Makefile    |    2 +-
 mini-gmp/tests/t-cmp_d.c   |  295 +++++++++++++++++++++++++++++++++++++++++++++
 mini-gmp/tests/testutils.h |    5 +
 6 files changed, 362 insertions(+), 1 deletions(-)

diffs (truncated from 416 to 300 lines):

diff -r 7763dbcce0a1 -r 2d7ecf5a6459 ChangeLog
--- a/ChangeLog	Mon Jan 21 21:55:42 2013 +0100
+++ b/ChangeLog	Tue Jan 22 21:21:39 2013 +0100
@@ -1,3 +1,15 @@
+2013-01-22  Niels Möller  <nisse at lysator.liu.se>
+
+	* mini-gmp/tests/testutils.h: Include stdio.h and stdlib.h.
+	(numberof): New define.
+
+	* mini-gmp/tests/t-cmp_d.c: New file, copied from
+	tests/mpz/t-cmp_d.c with minor changes.
+	* mini-gmp/tests/Makefile (CHECK_PROGRAMS): Added t-cmp_d,
+
+	* mini-gmp/mini-gmp.c (mpz_cmpabs_d): New function.
+	* mini-gmp/mini-gmp.h: Declare it.
+
 2013-01-21  Niels Möller  <nisse at lysator.liu.se>
 
 	* mini-gmp/tests/t-str.c (testmain): Test mpz_out_str, using
diff -r 7763dbcce0a1 -r 2d7ecf5a6459 mini-gmp/mini-gmp.c
--- a/mini-gmp/mini-gmp.c	Mon Jan 21 21:55:42 2013 +0100
+++ b/mini-gmp/mini-gmp.c	Tue Jan 22 21:21:39 2013 +0100
@@ -1545,6 +1545,54 @@
 }
 
 int
+mpz_cmpabs_d (const mpz_t x, double d)
+{
+  mp_size_t xn;
+  double B, Bi;
+  mp_size_t i;
+
+  xn = GMP_ABS (x->_mp_size);
+  d = GMP_ABS (d);
+
+  if (xn == 0)
+    return - (d > 0.0);
+  if (d < 1.0)
+    return 1;
+
+  B = 2.0 * (double) GMP_LIMB_HIGHBIT;
+  Bi = 1.0 / B;
+
+  /* Scale d so it can be compared with the top limb. */
+  for (i = 1; i < xn; i++)
+    {
+      d *= Bi;
+      if (d < 1.0)
+	return 1;
+    }
+  if (d >= B)
+    return -1;
+
+  /* Subtract x from d, one limb at a time. */
+  for (i = xn; i-- > 0;)
+    {
+      mp_limb_t f, xl;
+
+      f = (mp_limb_t) d;
+      xl = x->_mp_d[i];
+      if (xl > f)
+	return 1;
+      else if (xl < f)
+	return -1;
+      d = B * (d - f);
+    }
+
+  if (d > 0)
+    return -1;
+  else
+    return 0;  
+}
+
+int
 mpz_cmp_d (const mpz_t x, double d)
 {
   mp_size_t xn = x->_mp_size;
diff -r 7763dbcce0a1 -r 2d7ecf5a6459 mini-gmp/mini-gmp.h
--- a/mini-gmp/mini-gmp.h	Mon Jan 21 21:55:42 2013 +0100
+++ b/mini-gmp/mini-gmp.h	Tue Jan 22 21:21:39 2013 +0100
@@ -108,6 +108,7 @@
 int mpz_cmpabs_ui (const mpz_t, unsigned long);
 int mpz_cmpabs (const mpz_t, const mpz_t);
 int mpz_cmp_d (const mpz_t, double);
+int mpz_cmpabs_d (const mpz_t, double);
 
 void mpz_abs (mpz_t, const mpz_t);
 void mpz_neg (mpz_t, const mpz_t);
diff -r 7763dbcce0a1 -r 2d7ecf5a6459 mini-gmp/tests/Makefile
--- a/mini-gmp/tests/Makefile	Mon Jan 21 21:55:42 2013 +0100
+++ b/mini-gmp/tests/Makefile	Tue Jan 22 21:21:39 2013 +0100
@@ -28,7 +28,7 @@
 LIBS = -lgmp -lm -lmcheck
 
 CHECK_PROGRAMS = t-add t-sub t-mul t-invert t-div t-div_2exp \
-	t-double t-gcd t-lcm t-import t-comb t-signed \
+	t-double t-cmp_d t-gcd t-lcm t-import t-comb t-signed \
 	t-sqrt t-root t-powm t-logops t-bitops t-scan t-str \
 	t-reuse
 
diff -r 7763dbcce0a1 -r 2d7ecf5a6459 mini-gmp/tests/t-cmp_d.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mini-gmp/tests/t-cmp_d.c	Tue Jan 22 21:21:39 2013 +0100
@@ -0,0 +1,295 @@
+/* Test mpz_cmp_d and mpz_cmpabs_d.
+
+Copyright 2001, 2002, 2003, 2005, 2013 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library test suite.
+
+The GNU MP Library test suite is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+The GNU MP Library test suite is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+the GNU MP Library test suite.  If not, see http://www.gnu.org/licenses/.  */
+
+#include <math.h>
+
+#include "testutils.h"
+
+/* FIXME: Not sure if the tests here are exhaustive.  Ought to try to get
+   each possible exit from mpz_cmp_d (and mpz_cmpabs_d) exercised.  */
+
+
+#define SGN(n)  ((n) > 0 ? 1 : (n) < 0 ? -1 : 0)
+
+
+void
+check_one (const char *name, mpz_srcptr x, double y, int cmp, int cmpabs)
+{
+  int   got;
+
+  got = mpz_cmp_d (x, y);
+  if (SGN(got) != cmp)
+    {
+      int i;
+      printf    ("mpz_cmp_d wrong (from %s)\n", name);
+      printf    ("  got  %d\n", got);
+      printf    ("  want %d\n", cmp);
+    fail:
+      printf ("  x=");
+      mpz_out_str (stdout, 10, x);
+      printf    ("\n  y %g\n", y);
+      printf ("  x=0x");
+      mpz_out_str (stdout, -16, x);
+      printf    ("\n  y %g\n", y);
+      printf    ("  y");
+      for (i = 0; i < sizeof(y); i++)
+        printf (" %02X", (unsigned) ((unsigned char *) &y)[i]);
+      printf ("\n");
+      abort ();
+    }
+
+  got = mpz_cmpabs_d (x, y);
+  if (SGN(got) != cmpabs)
+    {
+      printf    ("mpz_cmpabs_d wrong\n");
+      printf    ("  got  %d\n", got);
+      printf    ("  want %d\n", cmpabs);
+      goto fail;
+    }
+}
+
+static void
+mpz_set_str_or_abort (mpz_ptr z, const char *str, int base)
+{
+  if (mpz_set_str (z, str, base) != 0)
+    {
+      fprintf (stderr, "ERROR: mpz_set_str failed\n");
+      fprintf (stderr, "   str  = \"%s\"\n", str);
+      fprintf (stderr, "   base = %d\n", base);
+      abort();
+    }
+}
+
+void
+check_data (void)
+{
+  static const struct {
+    const char  *x;
+    double      y;
+    int         cmp, cmpabs;
+
+  } data[] = {
+
+    {  "0",  0.0,  0,  0 },
+
+    {  "1",  0.0,  1,  1 },
+    { "-1",  0.0, -1,  1 },
+
+    {  "1",  0.5,  1,  1 },
+    { "-1", -0.5, -1,  1 },
+
+    {  "0",  1.0, -1, -1 },
+    {  "0", -1.0,  1, -1 },
+
+    {  "0x1000000000000000000000000000000000000000000000000", 1.0,  1, 1 },
+    { "-0x1000000000000000000000000000000000000000000000000", 1.0, -1, 1 },
+
+    {  "0",  1e100, -1, -1 },
+    {  "0", -1e100,  1, -1 },
+
+    {  "2",  1.5,   1,  1 },
+    {  "2", -1.5,   1,  1 },
+    { "-2",  1.5,  -1,  1 },
+    { "-2", -1.5,  -1,  1 },
+  };
+
+  mpz_t  x;
+  int    i;
+
+  mpz_init (x);
+
+  for (i = 0; i < numberof (data); i++)
+    {
+      mpz_set_str_or_abort (x, data[i].x, 0);
+      check_one ("check_data", x, data[i].y, data[i].cmp, data[i].cmpabs);
+    }
+
+  mpz_clear (x);
+}
+
+
+/* Equality of integers with up to 53 bits */
+void
+check_onebits (void)
+{
+  mpz_t   x, x2;
+  double  y;
+  int     i;
+
+  mpz_init_set_ui (x, 0L);
+  mpz_init (x2);
+
+  for (i = 0; i < 512; i++)
+    {
+      mpz_mul_2exp (x, x, 1);
+      mpz_add_ui (x, x, 1L);
+
+      y = mpz_get_d (x);
+      mpz_set_d (x2, y);
+
+      /* stop if any truncation is occurring */
+      if (mpz_cmp (x, x2) != 0)
+        break;
+
+      check_one ("check_onebits", x, y, 0, 0);
+      check_one ("check_onebits", x, -y, 1, 0);
+      mpz_neg (x, x);
+      check_one ("check_onebits", x, y, -1, 0);
+      check_one ("check_onebits", x, -y, 0, 0);
+      mpz_neg (x, x);
+    }
+
+  mpz_clear (x);
+  mpz_clear (x2);
+}
+
+
+/* With the mpz differing by 1, in a limb position possibly below the double */
+void
+check_low_z_one (void)
+{
+  mpz_t          x;
+  double         y;
+  unsigned long  i;
+
+  mpz_init (x);
+
+  /* FIXME: It'd be better to base this on the float format. */
+#if defined (__vax) || defined (__vax__)
+#define LIM 127			/* vax fp numbers have limited range */
+#else
+#define LIM 512
+#endif
+
+  for (i = 1; i < LIM; i++)
+    {
+      mpz_set_ui (x, 1L);
+      mpz_mul_2exp (x, x, i);
+      y = mpz_get_d (x);
+
+      check_one ("check_low_z_one", x, y,   0, 0);
+      check_one ("check_low_z_one", x, -y,  1, 0);
+      mpz_neg (x, x);
+      check_one ("check_low_z_one", x, y,  -1, 0);
+      check_one ("check_low_z_one", x, -y,  0, 0);
+      mpz_neg (x, x);
+
+      mpz_sub_ui (x, x, 1);
+
+      check_one ("check_low_z_one", x, y,  -1, -1);
+      check_one ("check_low_z_one", x, -y,  1, -1);


More information about the gmp-commit mailing list