[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