[project @ 1998-06-05 14:38:07 by simonm]
authorsimonm <unknown>
Fri, 5 Jun 1998 14:38:08 +0000 (14:38 +0000)
committersimonm <unknown>
Fri, 5 Jun 1998 14:38:08 +0000 (14:38 +0000)
Initial revision

18 files changed:
ghc/rts/gmp/mpz/tests/Makefile.in [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/configure.in [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/convert.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/dive.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/io-binary.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/io.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/logic.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/reuse.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/t-fdiv.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/t-fdiv_ui.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/t-gcd.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/t-gcd2.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/t-mul.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/t-powm.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/t-powm_ui.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/t-sqrtrem.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/t-tdiv.c [new file with mode: 0644]
ghc/rts/gmp/mpz/tests/t-tdiv_ui.c [new file with mode: 0644]

diff --git a/ghc/rts/gmp/mpz/tests/Makefile.in b/ghc/rts/gmp/mpz/tests/Makefile.in
new file mode 100644 (file)
index 0000000..5a0cf59
--- /dev/null
@@ -0,0 +1,126 @@
+# Makefile for mpz/tests for GNU MP
+
+srcdir = .
+
+CC = gcc
+
+TEST_LIBS = ../../libgmp.a
+INCLUDES = -I../../mpn -I$(srcdir)/../..
+CFLAGS = -g -O
+
+.c.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $<
+
+TEST_SRCS = t-mul.c t-tdiv.c t-tdiv_ui.c t-fdiv.c t-fdiv_ui.c t-gcd.c \
+ t-gcd2.c dive.c t-sqrtrem.c convert.c io.c logic.c t-powm.c t-powm_ui.c \
+  reuse.c
+TEST_OBJS = t-mul.o t-tdiv.o t-tdiv_ui.o t-fdiv.o t-fdiv_ui.o t-gcd.o \
+ t-gcd2.o dive.o t-sqrtrem.o convert.o io.o logic.o t-powm.o t-powm_ui.o \
+ reuse.o
+TESTS = t-mul t-tdiv t-tdiv_ui t-fdiv t-fdiv_ui t-gcd t-gcd2 \
+ dive t-sqrtrem convert io logic t-powm t-powm_ui reuse
+
+check: Makefile st-mul st-tdiv st-tdiv_ui st-fdiv st-fdiv_ui st-gcd st-gcd2 st-dive \
+  st-sqrtrem st-convert st-io st-logic st-powm st-powm_ui st-reuse
+       @echo "The tests passed."
+
+st-mul: t-mul
+       ./t-mul
+       touch $@
+st-tdiv: t-tdiv
+       ./t-tdiv
+       touch $@
+st-tdiv_ui: t-tdiv_ui
+       ./t-tdiv_ui
+       touch $@
+st-fdiv: t-fdiv
+       ./t-fdiv
+       touch $@
+st-fdiv_ui: t-fdiv_ui
+       ./t-fdiv_ui
+       touch $@
+st-gcd: t-gcd
+       ./t-gcd
+       touch $@
+st-gcd2: t-gcd2
+       ./t-gcd2
+       touch $@
+st-dive: dive
+       ./dive
+       touch $@
+st-sqrtrem: t-sqrtrem
+       ./t-sqrtrem
+       touch $@
+st-convert: convert
+       ./convert
+       touch $@
+st-io: io
+       ./io
+       touch $@
+st-logic: logic
+       ./logic
+       touch $@
+st-powm: t-powm
+       ./t-powm
+       touch $@
+st-powm_ui: t-powm_ui
+       ./t-powm_ui
+       touch $@
+st-reuse: reuse
+       ./reuse
+       touch $@
+
+t-mul: t-mul.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-tdiv: t-tdiv.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-tdiv_ui: t-tdiv_ui.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-fdiv: t-fdiv.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-fdiv_ui: t-fdiv_ui.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-gcd: t-gcd.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-gcd2: t-gcd2.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+dive: dive.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-sqrtrem: t-sqrtrem.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+convert: convert.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+io: io.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+logic: logic.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-powm: t-powm.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+t-powm_ui: t-powm_ui.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+reuse: reuse.o $(TEST_LIBS)
+       $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS)
+
+t-mul.o: $(srcdir)/t-mul.c
+t-tdiv.o: $(srcdir)/t-tdiv.c
+t-tdiv_ui.o: $(srcdir)/t-tdiv_ui.c
+t-fdiv.o: $(srcdir)/t-fdiv.c
+t-fdiv_ui.o: $(srcdir)/t-fdiv_ui.c
+t-gcd.o: $(srcdir)/t-gcd.c
+t-gcd2.o: $(srcdir)/t-gcd2.c
+dive.o: $(srcdir)/dive.c
+t-sqrtrem.o: $(srcdir)/t-sqrtrem.c
+convert.o: $(srcdir)/convert.c
+io.o: $(srcdir)/io.c
+logic.o: $(srcdir)/logic.c
+t-powm.o: $(srcdir)/t-powm.c
+t-powm_ui.o: $(srcdir)/t-powm_ui.c
+reuse.o: $(srcdir)/reuse.c
+
+clean mostlyclean:
+       rm -f *.o st-* $(TESTS)
+distclean maintainer-clean: clean
+       rm -f Makefile config.status
+
+Makefile: $(srcdir)/Makefile.in
+       $(SHELL) ./config.status
diff --git a/ghc/rts/gmp/mpz/tests/configure.in b/ghc/rts/gmp/mpz/tests/configure.in
new file mode 100644 (file)
index 0000000..dacc177
--- /dev/null
@@ -0,0 +1,11 @@
+# This file is a shell script that supplies the information necessary
+# to tailor a template configure script into the configure script
+# appropriate for this directory.  For more information, check any
+# existing configure script.
+
+srctrigger=t-mul.c
+srcname="gmp/mpz/tests"
+
+# per-host:
+
+# per-target:
diff --git a/ghc/rts/gmp/mpz/tests/convert.c b/ghc/rts/gmp/mpz/tests/convert.c
new file mode 100644 (file)
index 0000000..1d82370
--- /dev/null
@@ -0,0 +1,80 @@
+/* Test conversion using mpz_get_str and mpz_set_str.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 32
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  MP_INT op1, op2;
+  mp_size_t size;
+  int i;
+  int reps = 100000;
+  char *str;
+  int base;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (&op1);
+  mpz_init (&op2);
+
+  for (i = 0; i < reps; i++)
+    {
+      size = urandom () % SIZE - SIZE/2;
+
+      mpz_random2 (&op1, size);
+      base = urandom () % 36 + 1;
+      if (base == 1)
+       base = 0;
+
+      str = mpz_get_str ((char *) 0, base, &op1);
+      mpz_set_str (&op2, str, base);
+      free (str);
+
+      if (mpz_cmp (&op1, &op2))
+       {
+         fprintf (stderr, "ERROR\n");
+         fprintf (stderr, "op1  = "); debug_mp (&op1, -16);
+         fprintf (stderr, "base = %d\n", base);
+         abort ();
+       }
+    }
+
+  exit (0);
+}
+
+void
+debug_mp (x, base)
+     MP_INT *x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/dive.c b/ghc/rts/gmp/mpz/tests/dive.c
new file mode 100644 (file)
index 0000000..8d3516d
--- /dev/null
@@ -0,0 +1,87 @@
+/* Test mpz_mul, mpz_divexact.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 32
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t op1, op2;
+  mpz_t prod, quot;
+  mp_size_t size;
+  int i;
+  int reps = 100000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (op1);
+  mpz_init (op2);
+  mpz_init (prod);
+  mpz_init (quot);
+
+  for (i = 0; i < reps; i++)
+    {
+      size = urandom () % SIZE - SIZE/2;
+      mpz_random2 (op1, size);
+
+      do
+       {
+         size = urandom () % SIZE - SIZE/2;
+         mpz_random2 (op2, size);
+       }
+      while (mpz_cmp_ui (op2, 0) == 0);
+
+      mpz_mul (prod, op1, op2);
+
+      mpz_divexact (quot, prod, op2);
+      if (mpz_cmp (quot, op1) != 0)
+       dump_abort (quot, op1);
+    }
+
+  exit (0);
+}
+
+dump_abort (op1, op2)
+     mpz_t op1, op2;
+{
+  fprintf (stderr, "ERROR\n");
+  fprintf (stderr, "ref = "); debug_mp (op1, -16);
+  fprintf (stderr, "wrong = "); debug_mp (op2, -16);
+  abort();
+}
+
+void
+debug_mp (x, base)
+     mpz_t x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/io-binary.c b/ghc/rts/gmp/mpz/tests/io-binary.c
new file mode 100644 (file)
index 0000000..c28f2a5
--- /dev/null
@@ -0,0 +1,76 @@
+/* Test mpz_inp_binary and mpz_out_binary.
+
+   We write and read back some test strings, and both compare
+   the numerical result, and make sure the pattern on file is
+   what we expect.  The latter is important for compatibility
+   between machines with different word sizes.  */
+
+#include <stdio.h>
+#include "gmp.h"
+
+FILE *file;
+
+test (str, binary_len, binary_str)
+     char *str;
+     int binary_len;
+     char *binary_str;
+{
+  mpz_t x, y;
+  int n_written;
+  char buf[100];
+
+  mpz_init_set_str (x, str, 0);
+  mpz_init (y);
+
+  fseek (file, 0, SEEK_SET);
+  mpz_out_binary (file, x);
+  n_written = ftell (file);
+  if (n_written != binary_len)
+    abort ();
+
+  fseek (file, 0, SEEK_SET);
+  mpz_inp_binary (y, file);
+  if (n_written != ftell (file))
+    abort ();
+  if (mpz_cmp (x, y) != 0)
+    abort ();
+
+  fseek (file, 0, SEEK_SET);
+  fread (buf, n_written, 1, file);
+  if (memcmp (buf, binary_str, binary_len) != 0)
+    abort ();
+
+  mpz_clear (x);
+}
+
+main ()
+{
+  file = fopen ("xtmpfile", "w+");
+
+  test ("0", 4,
+       "\000\000\000\000");
+
+  test ("1", 5,
+       "\000\000\000\001\001");
+  test ("0x123", 6,
+       "\000\000\000\002\001\043");
+  test ("0xdeadbeef", 8,
+       "\000\000\000\004\336\255\276\357");
+  test ("0xbabefaced", 9,
+       "\000\000\000\005\013\253\357\254\355");
+  test ("0x123456789facade0", 12,
+       "\000\000\000\010\022\064\126\170\237\254\255\340");
+
+  test ("-1", 5,
+       "\377\377\377\377\001");
+  test ("-0x123", 6,
+       "\377\377\377\376\001\043");
+  test ("-0xdeadbeef", 8,
+       "\377\377\377\374\336\255\276\357");
+  test ("-0xbabefaced", 9,
+       "\377\377\377\373\013\253\357\254\355");
+  test ("-0x123456789facade0", 12,
+       "\377\377\377\370\022\064\126\170\237\254\255\340");
+
+  exit (0);
+}
diff --git a/ghc/rts/gmp/mpz/tests/io.c b/ghc/rts/gmp/mpz/tests/io.c
new file mode 100644 (file)
index 0000000..3dfa9a5
--- /dev/null
@@ -0,0 +1,86 @@
+/* Test conversion and I/O using mpz_out_str and mpz_inp_str.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  MP_INT op1, op2;
+  mp_size_t size;
+  int i;
+  int reps = 10000;
+  FILE *fsin, *fsout;
+  int fd[2];
+  int base;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (&op1);
+  mpz_init (&op2);
+
+  pipe (fd);
+  fsin = fdopen (fd[0], "r");
+  fsout = fdopen (fd[1], "w");
+
+  for (i = 0; i < reps; i++)
+    {
+      size = urandom () % SIZE - SIZE/2;
+
+      mpz_random2 (&op1, size);
+      base = urandom () % 36 + 1;
+      if (base == 1)
+       base = 0;
+
+      mpz_out_str (fsout, base, &op1);
+      putc (' ', fsout);
+      fflush (fsout);
+      mpz_inp_str (&op2, fsin, base);
+
+      if (mpz_cmp (&op1, &op2))
+       {
+         fprintf (stderr, "ERROR\n");
+         fprintf (stderr, "op1  = "); debug_mp (&op1, -16);
+         fprintf (stderr, "base = %d\n", base);
+         abort ();
+       }
+    }
+
+  exit (0);
+}
+
+void
+debug_mp (x, base)
+     MP_INT *x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/logic.c b/ghc/rts/gmp/mpz/tests/logic.c
new file mode 100644 (file)
index 0000000..41a8cac
--- /dev/null
@@ -0,0 +1,103 @@
+/* Test mpz_com, mpz_and, and mpz_ior.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t x, y, r1, r2;
+  mpz_t t1, t2, t3, t4;
+  mp_size_t xsize, ysize;
+  int i;
+  int reps = 100000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (x);
+  mpz_init (y);
+  mpz_init (r1);
+  mpz_init (r2);
+  mpz_init (t1);
+  mpz_init (t2);
+  mpz_init (t3);
+  mpz_init (t4);
+
+  for (i = 0; i < reps; i++)
+    {
+      xsize = urandom () % SIZE - SIZE/2;
+      mpz_random2 (x, xsize);
+
+      ysize = urandom () % SIZE - SIZE/2;
+      mpz_random2 (y, ysize);
+
+      mpz_com (r1, x);
+      mpz_com (r1, r1);
+      if (mpz_cmp (r1, x) != 0)
+       dump_abort ();
+
+      mpz_com (r1, y);
+      mpz_com (r2, r1);
+      if (mpz_cmp (r2, y) != 0)
+       dump_abort ();
+
+      mpz_com (t1, x);
+      mpz_com (t2, y);
+      mpz_and (t3, t1, t2);
+      mpz_com (r1, t3);
+      mpz_ior (r2, x, y);
+      if (mpz_cmp (r1, r2) != 0)
+       dump_abort ();
+
+      mpz_com (t1, x);
+      mpz_com (t2, y);
+      mpz_ior (t3, t1, t2);
+      mpz_com (r1, t3);
+      mpz_and (r2, x, y);
+      if (mpz_cmp (r1, r2) != 0)
+       dump_abort ();
+    }
+
+  exit (0);
+}
+
+dump_abort ()
+{
+  abort();
+}
+
+void
+debug_mp (x, base)
+     MP_INT *x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/reuse.c b/ghc/rts/gmp/mpz/tests/reuse.c
new file mode 100644 (file)
index 0000000..52fc5a5
--- /dev/null
@@ -0,0 +1,135 @@
+/* Test that routines allow reusing a source variable as destination.  */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+#if __STDC__
+typedef void (*dss_func) (mpz_ptr, mpz_srcptr, mpz_srcptr);
+#else
+typedef void (*dss_func) ();
+#endif
+
+dss_func dss_funcs[] =
+{
+  mpz_add, mpz_and, mpz_cdiv_q, mpz_cdiv_r, mpz_fdiv_q, mpz_fdiv_r,
+  mpz_gcd, mpz_ior, mpz_mul, mpz_sub, mpz_tdiv_q, mpz_tdiv_r
+};
+
+char *dss_func_names[] =
+{
+  "mpz_add", "mpz_and", "mpz_cdiv_q", "mpz_cdiv_r", "mpz_fdiv_q", "mpz_fdiv_r",
+  "mpz_gcd", "mpz_ior", "mpz_mul", "mpz_sub", "mpz_tdiv_q", "mpz_tdiv_r"
+};
+
+char dss_func_division[] = {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1};
+
+#if 0
+mpz_divexact /* requires special operands */
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int i;
+  int pass, reps = 10000;
+  mpz_t in1, in2, out1;
+  mpz_t res1, res2, res3;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (in1);
+  mpz_init (in2);
+  mpz_init (out1);
+  mpz_init (res1);
+  mpz_init (res2);
+  mpz_init (res3);
+
+  for (pass = 1; pass <= reps; pass++)
+    {
+      mpz_random (in1, urandom () % SIZE - SIZE/2);
+      mpz_random (in2, urandom () % SIZE - SIZE/2);
+
+      for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++)
+       {
+         if (dss_func_division[i] && mpz_cmp_ui (in2, 0) == 0)
+           continue;
+
+         (dss_funcs[i]) (res1, in1, in2);
+
+         mpz_set (out1, in1);
+         (dss_funcs[i]) (out1, out1, in2);
+         mpz_set (res2, out1);
+
+         mpz_set (out1, in2);
+         (dss_funcs[i]) (out1, in1, out1);
+         mpz_set (res3, out1);
+
+         if (mpz_cmp (res1, res2) != 0)
+           dump_abort (dss_func_names[i], in1, in2);
+         if (mpz_cmp (res1, res3) != 0)
+           dump_abort (dss_func_names[i], in1, in2);
+       }
+    }
+
+  exit (0);
+}
+
+dump_abort (name, in1, in2)
+     char *name;
+     mpz_t in1, in2;
+{
+  printf ("failure in %s (", name);
+  mpz_out_str (stdout, -16, in1);
+  printf (" ");
+  mpz_out_str (stdout, -16, in2);
+  printf (")\n");
+  abort ();
+}
+
+#if 0
+void mpz_add_ui                _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_div_2exp      _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_mod_2exp      _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_mul_2exp      _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_mul_ui                _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_pow_ui                _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_sub_ui                _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_tdiv_q_ui     _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+void mpz_tdiv_r_ui     _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+
+void mpz_abs           _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_com           _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_sqrt          _PROTO ((mpz_ptr, mpz_srcptr));
+void mpz_neg           _PROTO ((mpz_ptr, mpz_srcptr));
+
+void mpz_tdiv_qr_ui    _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
+
+void mpz_powm_ui       _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr));
+
+void mpz_gcdext                _PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+
+void mpz_cdiv_qr       _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_fdiv_qr       _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+void mpz_tdiv_qr       _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr));
+
+void mpz_powm          _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr));
+
+void mpz_sqrtrem       _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr));
+
+unsigned long int mpz_cdiv_qr_ui       _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_fdiv_qr_ui       _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int));
+
+unsigned long int mpz_cdiv_q_ui        _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_cdiv_r_ui        _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_fdiv_q_ui        _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_fdiv_r_ui        _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+unsigned long int mpz_gcd_ui   _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int));
+#endif
diff --git a/ghc/rts/gmp/mpz/tests/t-fdiv.c b/ghc/rts/gmp/mpz/tests/t-fdiv.c
new file mode 100644 (file)
index 0000000..9de22d7
--- /dev/null
@@ -0,0 +1,118 @@
+/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_fdiv_qr, mpz_fdiv_q,
+   mpz_fdiv_r, mpz_mul.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t dividend, divisor;
+  mpz_t quotient, remainder;
+  mpz_t quotient2, remainder2;
+  mpz_t temp;
+  mp_size_t dividend_size, divisor_size;
+  int i;
+  int reps = 100000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (dividend);
+  mpz_init (divisor);
+  mpz_init (quotient);
+  mpz_init (remainder);
+  mpz_init (quotient2);
+  mpz_init (remainder2);
+  mpz_init (temp);
+
+  for (i = 0; i < reps; i++)
+    {
+      dividend_size = urandom () % SIZE - SIZE/2;
+      mpz_random2 (dividend, dividend_size);
+
+      divisor_size = urandom () % SIZE - SIZE/2;
+      mpz_random2 (divisor, divisor_size);
+      if (mpz_cmp_ui (divisor, 0) == 0)
+       continue;
+
+      mpz_fdiv_qr (quotient, remainder, dividend, divisor);
+      mpz_fdiv_q (quotient2, dividend, divisor);
+      mpz_fdiv_r (remainder2, dividend, divisor);
+
+      /* First determine that the quotients and remainders computed
+        with different functions are equal.  */
+      if (mpz_cmp (quotient, quotient2) != 0)
+       dump_abort (dividend, divisor);
+      if (mpz_cmp (remainder, remainder2) != 0)
+       dump_abort (dividend, divisor);
+
+      /* Check if the sign of the quotient is correct.  */
+      if (mpz_cmp_ui (quotient, 0) != 0)
+       if ((mpz_cmp_ui (quotient, 0) < 0)
+           != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0))
+       dump_abort (dividend, divisor);
+
+      /* Check if the remainder has the same sign as the divisor
+        (quotient rounded towards minus infinity).  */
+      if (mpz_cmp_ui (remainder, 0) != 0)
+       if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (divisor, 0) < 0))
+         dump_abort (dividend, divisor);
+
+      mpz_mul (temp, quotient, divisor);
+      mpz_add (temp, temp, remainder);
+      if (mpz_cmp (temp, dividend) != 0)
+       dump_abort (dividend, divisor);
+
+      mpz_abs (temp, divisor);
+      mpz_abs (remainder, remainder);
+      if (mpz_cmp (remainder, temp) >= 0)
+       dump_abort (dividend, divisor);
+    }
+
+  exit (0);
+}
+
+dump_abort (dividend, divisor)
+     mpz_t dividend, divisor;
+{
+  fprintf (stderr, "ERROR\n");
+  fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+  fprintf (stderr, "divisor  = "); debug_mp (divisor, -16);
+  abort();
+}
+
+void
+debug_mp (x, base)
+     mpz_t x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/t-fdiv_ui.c b/ghc/rts/gmp/mpz/tests/t-fdiv_ui.c
new file mode 100644 (file)
index 0000000..74ba9fc
--- /dev/null
@@ -0,0 +1,117 @@
+/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_fdiv_qr_ui, mpz_fdiv_q_ui,
+   mpz_fdiv_r_ui, mpz_mul, mpz_mul_ui.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t dividend;
+  mpz_t quotient, remainder;
+  mpz_t quotient2, remainder2;
+  mpz_t temp;
+  mp_size_t dividend_size;
+  mp_limb_t divisor;
+  int i;
+  int reps = 100000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (dividend);
+  mpz_init (quotient);
+  mpz_init (remainder);
+  mpz_init (quotient2);
+  mpz_init (remainder2);
+  mpz_init (temp);
+
+  for (i = 0; i < reps; i++)
+    {
+      dividend_size = urandom () % SIZE - SIZE/2;
+      mpz_random2 (dividend, dividend_size);
+
+      divisor = urandom ();
+      if (divisor == 0)
+       continue;
+
+      mpz_fdiv_qr_ui (quotient, remainder, dividend, divisor);
+      mpz_fdiv_q_ui (quotient2, dividend, divisor);
+      mpz_fdiv_r_ui (remainder2, dividend, divisor);
+
+      /* First determine that the quotients and remainders computed
+        with different functions are equal.  */
+      if (mpz_cmp (quotient, quotient2) != 0)
+       dump_abort (dividend, divisor);
+      if (mpz_cmp (remainder, remainder2) != 0)
+       dump_abort (dividend, divisor);
+
+      /* Check if the sign of the quotient is correct.  */
+      if (mpz_cmp_ui (quotient, 0) != 0)
+       if ((mpz_cmp_ui (quotient, 0) < 0)
+           != (mpz_cmp_ui (dividend, 0) < 0))
+       dump_abort (dividend, divisor);
+
+      /* Check if the remainder has the same sign as the divisor
+        (quotient rounded towards minus infinity).  */
+      if (mpz_cmp_ui (remainder, 0) != 0)
+       if (mpz_cmp_ui (remainder, 0) < 0)
+         dump_abort (dividend, divisor);
+
+      mpz_mul_ui (temp, quotient, divisor);
+      mpz_add (temp, temp, remainder);
+      if (mpz_cmp (temp, dividend) != 0)
+       dump_abort (dividend, divisor);
+
+      mpz_abs (remainder, remainder);
+      if (mpz_cmp_ui (remainder, divisor) >= 0)
+       dump_abort (dividend, divisor);
+    }
+
+  exit (0);
+}
+
+dump_abort (dividend, divisor)
+     mpz_t dividend;
+     mp_limb_t divisor;
+{
+  fprintf (stderr, "ERROR\n");
+  fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+  fprintf (stderr, "divisor  = %lX\n", divisor);
+  abort();
+}
+
+void
+debug_mp (x, base)
+     mpz_t x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/t-gcd.c b/ghc/rts/gmp/mpz/tests/t-gcd.c
new file mode 100644 (file)
index 0000000..d9a7884
--- /dev/null
@@ -0,0 +1,132 @@
+/* Test mpz_gcd, mpz_gcdext, mpz_mul, mpz_tdiv_r, mpz_add, mpz_cmp,
+   mpz_cmp_ui, mpz_init_set, mpz_set, mpz_clear.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void mpz_refgcd (), debug_mp ();
+
+#ifndef SIZE
+#define SIZE 256 /* really needs to be this large to exercise corner cases! */
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t op1, op2;
+  mpz_t refgcd, gcd, s, t;
+  mpz_t temp1, temp2;
+  mp_size_t op1_size, op2_size;
+  int i;
+  int reps = 1000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (op1);
+  mpz_init (op2);
+  mpz_init (refgcd);
+  mpz_init (gcd);
+  mpz_init (temp1);
+  mpz_init (temp2);
+  mpz_init (s);
+  mpz_init (t);
+
+  for (i = 0; i < reps; i++)
+    {
+      op1_size = urandom () % SIZE - SIZE/2;
+      op2_size = urandom () % SIZE - SIZE/2;
+
+      mpz_random2 (op1, op1_size);
+      mpz_random2 (op2, op2_size);
+
+      mpz_refgcd (refgcd, op1, op2);
+
+      mpz_gcd (gcd, op1, op2);
+      if (mpz_cmp (refgcd, gcd))
+       dump_abort (op1, op2);
+
+      mpz_gcdext (gcd, s, t, op1, op2);
+      if (mpz_cmp (refgcd, gcd))
+       dump_abort (op1, op2);
+
+      mpz_mul (temp1, s, op1);
+      mpz_mul (temp2, t, op2);
+      mpz_add (gcd, temp1, temp2);
+      if (mpz_cmp (refgcd, gcd))
+       dump_abort (op1, op2);
+    }
+
+  exit (0);
+}
+
+void
+mpz_refgcd (g, x, y)
+     mpz_t g;
+     mpz_t x, y;
+{
+  mpz_t xx, yy;
+
+  mpz_init (xx);
+  mpz_init (yy);
+
+  mpz_abs (xx, x);
+  mpz_abs (yy, y);
+
+  for (;;)
+    {
+      if (mpz_cmp_ui (yy, 0) == 0)
+       {
+         mpz_set (g, xx);
+         break;
+       }
+      mpz_tdiv_r (xx, xx, yy);
+      if (mpz_cmp_ui (xx, 0) == 0)
+       {
+         mpz_set (g, yy);
+         break;
+       }
+      mpz_tdiv_r (yy, yy, xx);
+    }
+
+  mpz_clear (xx);
+  mpz_clear (yy);
+}
+
+dump_abort (op1, op2)
+     mpz_t op1, op2;
+{
+  fprintf (stderr, "ERROR\n");
+  fprintf (stderr, "op1 = "); debug_mp (op1, -16);
+  fprintf (stderr, "op2 = "); debug_mp (op2, -16);
+  abort();
+}
+
+void
+debug_mp (x, base)
+     mpz_t x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/t-gcd2.c b/ghc/rts/gmp/mpz/tests/t-gcd2.c
new file mode 100644 (file)
index 0000000..b7ad67c
--- /dev/null
@@ -0,0 +1,137 @@
+/* Test mpz_gcd, mpz_gcdext, mpz_mul, mpz_tdiv_r, mpz_add, mpz_cmp,
+   mpz_cmp_ui, mpz_init_set, mpz_set, mpz_clear.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void mpz_refgcd (), debug_mp ();
+
+#ifndef SIZE
+#define SIZE 128
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t op1, op2, x;
+  mpz_t refgcd, gcd, s, t;
+  mpz_t temp1, temp2;
+  mp_size_t op1_size, op2_size, x_size;
+  int i;
+  int reps = 1000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (op1);
+  mpz_init (op2);
+  mpz_init (x);
+  mpz_init (refgcd);
+  mpz_init (gcd);
+  mpz_init (temp1);
+  mpz_init (temp2);
+  mpz_init (s);
+  mpz_init (t);
+
+  for (i = 0; i < reps; i++)
+    {
+      op1_size = urandom () % SIZE - SIZE/2;
+      op2_size = urandom () % SIZE - SIZE/2;
+      x_size = urandom () % SIZE/2;
+
+      mpz_random2 (op1, op1_size);
+      mpz_random2 (op2, op2_size);
+      mpz_random2 (x, x_size);
+      mpz_mul (op1, op1, x);
+      mpz_mul (op2, op2, x);
+
+      mpz_refgcd (refgcd, op1, op2);
+
+      mpz_gcd (gcd, op1, op2);
+      if (mpz_cmp (refgcd, gcd))
+       dump_abort (op1, op2);
+
+      mpz_gcdext (gcd, s, t, op1, op2);
+      if (mpz_cmp (refgcd, gcd))
+       dump_abort (op1, op2);
+
+      mpz_mul (temp1, s, op1);
+      mpz_mul (temp2, t, op2);
+      mpz_add (gcd, temp1, temp2);
+      if (mpz_cmp (refgcd, gcd))
+       dump_abort (op1, op2);
+    }
+
+  exit (0);
+}
+
+void
+mpz_refgcd (g, x, y)
+     mpz_t g;
+     mpz_t x, y;
+{
+  mpz_t xx, yy;
+
+  mpz_init (xx);
+  mpz_init (yy);
+
+  mpz_abs (xx, x);
+  mpz_abs (yy, y);
+
+  for (;;)
+    {
+      if (mpz_cmp_ui (yy, 0) == 0)
+       {
+         mpz_set (g, xx);
+         break;
+       }
+      mpz_tdiv_r (xx, xx, yy);
+      if (mpz_cmp_ui (xx, 0) == 0)
+       {
+         mpz_set (g, yy);
+         break;
+       }
+      mpz_tdiv_r (yy, yy, xx);
+    }
+
+  mpz_clear (xx);
+  mpz_clear (yy);
+}
+
+dump_abort (op1, op2)
+     mpz_t op1, op2;
+{
+  fprintf (stderr, "ERROR\n");
+  fprintf (stderr, "op1 = "); debug_mp (op1, -16);
+  fprintf (stderr, "op2 = "); debug_mp (op2, -16);
+  abort();
+}
+
+void
+debug_mp (x, base)
+     mpz_t x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/t-mul.c b/ghc/rts/gmp/mpz/tests/t-mul.c
new file mode 100644 (file)
index 0000000..b200cd7
--- /dev/null
@@ -0,0 +1,261 @@
+/* Test mpz_add, mpz_cmp, mpz_cmp_ui, mpz_divmod, mpz_mul.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+#include "urandom.h"
+
+void debug_mp ();
+mp_size_t _mpn_mul_classic ();
+void mpz_refmul ();
+
+#ifndef SIZE
+#define SIZE 128
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t multiplier, multiplicand;
+  mpz_t product, ref_product;
+  mpz_t quotient, remainder;
+  mp_size_t multiplier_size, multiplicand_size;
+  int i;
+  int reps = 10000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (multiplier);
+  mpz_init (multiplicand);
+  mpz_init (product);
+  mpz_init (ref_product);
+  mpz_init (quotient);
+  mpz_init (remainder);
+
+  for (i = 0; i < reps; i++)
+    {
+      multiplier_size = urandom () % SIZE - SIZE/2;
+      multiplicand_size = urandom () % SIZE - SIZE/2;
+
+      mpz_random2 (multiplier, multiplier_size);
+      mpz_random2 (multiplicand, multiplicand_size);
+
+      mpz_mul (product, multiplier, multiplicand);
+      mpz_refmul (ref_product, multiplier, multiplicand);
+      if (mpz_cmp_ui (multiplicand, 0) != 0)
+       mpz_divmod (quotient, remainder, product, multiplicand);
+
+      if (mpz_cmp (product, ref_product))
+       dump_abort (multiplier, multiplicand);
+
+      if (mpz_cmp_ui (multiplicand, 0) != 0)
+      if (mpz_cmp_ui (remainder, 0) || mpz_cmp (quotient, multiplier))
+       dump_abort (multiplier, multiplicand);
+    }
+
+  exit (0);
+}
+
+void
+mpz_refmul (w, u, v)
+     mpz_t w;
+     const mpz_t u;
+     const mpz_t v;
+{
+  mp_size_t usize = u->_mp_size;
+  mp_size_t vsize = v->_mp_size;
+  mp_size_t wsize;
+  mp_size_t sign_product;
+  mp_ptr up, vp;
+  mp_ptr wp;
+  mp_ptr free_me = NULL;
+  size_t free_me_size;
+  TMP_DECL (marker);
+
+  TMP_MARK (marker);
+  sign_product = usize ^ vsize;
+  usize = ABS (usize);
+  vsize = ABS (vsize);
+
+  if (usize < vsize)
+    {
+      /* Swap U and V.  */
+      {const __mpz_struct *t = u; u = v; v = t;}
+      {mp_size_t t = usize; usize = vsize; vsize = t;}
+    }
+
+  up = u->_mp_d;
+  vp = v->_mp_d;
+  wp = w->_mp_d;
+
+  /* Ensure W has space enough to store the result.  */
+  wsize = usize + vsize;
+  if (w->_mp_alloc < wsize)
+    {
+      if (wp == up || wp == vp)
+       {
+         free_me = wp;
+         free_me_size = w->_mp_alloc;
+       }
+      else
+       (*_mp_free_func) (wp, w->_mp_alloc * BYTES_PER_MP_LIMB);
+
+      w->_mp_alloc = wsize;
+      wp = (mp_ptr) (*_mp_allocate_func) (wsize * BYTES_PER_MP_LIMB);
+      w->_mp_d = wp;
+    }
+  else
+    {
+      /* Make U and V not overlap with W.  */
+      if (wp == up)
+       {
+         /* W and U are identical.  Allocate temporary space for U.  */
+         up = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB);
+         /* Is V identical too?  Keep it identical with U.  */
+         if (wp == vp)
+           vp = up;
+         /* Copy to the temporary space.  */
+         MPN_COPY (up, wp, usize);
+       }
+      else if (wp == vp)
+       {
+         /* W and V are identical.  Allocate temporary space for V.  */
+         vp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB);
+         /* Copy to the temporary space.  */
+         MPN_COPY (vp, wp, vsize);
+       }
+    }
+
+  wsize = _mpn_mul_classic (wp, up, usize, vp, vsize);
+  w->_mp_size = sign_product < 0 ? -wsize : wsize;
+  if (free_me != NULL)
+    (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB);
+
+  TMP_FREE (marker);
+}
+
+mp_size_t
+_mpn_mul_classic (prodp, up, usize, vp, vsize)
+     mp_ptr prodp;
+     mp_srcptr up;
+     mp_size_t usize;
+     mp_srcptr vp;
+     mp_size_t vsize;
+{
+  mp_size_t i, j;
+  mp_limb_t prod_low, prod_high;
+  mp_limb_t cy_dig;
+  mp_limb_t v_limb, c;
+
+  if (vsize == 0)
+    return 0;
+
+  /* Offset UP and PRODP so that the inner loop can be faster.  */
+  up += usize;
+  prodp += usize;
+
+  /* Multiply by the first limb in V separately, as the result can
+     be stored (not added) to PROD.  We also avoid a loop for zeroing.  */
+  v_limb = vp[0];
+  cy_dig = 0;
+  j = -usize;
+  do
+    {
+      umul_ppmm (prod_high, prod_low, up[j], v_limb);
+      add_ssaaaa (cy_dig, prodp[j], prod_high, prod_low, 0, cy_dig);
+      j++;
+    }
+  while (j < 0);
+
+  prodp[j] = cy_dig;
+  prodp++;
+
+  /* For each iteration in the outer loop, multiply one limb from
+     U with one limb from V, and add it to PROD.  */
+  for (i = 1; i < vsize; i++)
+    {
+      v_limb = vp[i];
+      cy_dig = 0;
+      j = -usize;
+
+      /* Inner loops.  Simulate the carry flag by jumping between
+        these loops.  The first is used when there was no carry
+        in the previois iteration; the second when there was carry.  */
+
+      do
+       {
+         umul_ppmm (prod_high, prod_low, up[j], v_limb);
+         add_ssaaaa (cy_dig, prod_low, prod_high, prod_low, 0, cy_dig);
+         c = prodp[j];
+         prod_low += c;
+         prodp[j] = prod_low;
+         if (prod_low < c)
+           goto cy_loop;
+       ncy_loop:
+         j++;
+       }
+      while (j < 0);
+
+      prodp[j] = cy_dig;
+      prodp++;
+      continue;
+
+      do
+       {
+         umul_ppmm (prod_high, prod_low, up[j], v_limb);
+         add_ssaaaa (cy_dig, prod_low, prod_high, prod_low, 0, cy_dig);
+         c = prodp[j];
+         prod_low += c + 1;
+         prodp[j] = prod_low;
+         if (prod_low > c)
+           goto ncy_loop;
+       cy_loop:
+         j++;
+       }
+      while (j < 0);
+
+      cy_dig += 1;
+      prodp[j] = cy_dig;
+      prodp++;
+    }
+
+  return usize + vsize - (cy_dig == 0);
+}
+
+dump_abort (multiplier, multiplicand)
+     mpz_t multiplier, multiplicand;
+{
+  fprintf (stderr, "ERROR\n");
+  fprintf (stderr, "multiplier = "); debug_mp (multiplier, -16);
+  fprintf (stderr, "multiplicand  = "); debug_mp (multiplicand, -16);
+  abort();
+}
+
+void
+debug_mp (x, base)
+     mpz_t x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/t-powm.c b/ghc/rts/gmp/mpz/tests/t-powm.c
new file mode 100644 (file)
index 0000000..02d7ca5
--- /dev/null
@@ -0,0 +1,125 @@
+/* Test mpz_powm, mpz_mul. mpz_mod, mpz_mod_ui, mpz_div_ui.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 8
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t base, exp, mod;
+  mpz_t r1, r2, t1, exp2, base2;
+  mp_size_t base_size, exp_size, mod_size;
+  int i;
+  int reps = 10000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (base);
+  mpz_init (exp);
+  mpz_init (mod);
+  mpz_init (r1);
+  mpz_init (r2);
+  mpz_init (t1);
+  mpz_init (exp2);
+  mpz_init (base2);
+
+  for (i = 0; i < reps; i++)
+    {
+      base_size = urandom () % SIZE - SIZE/2;
+      mpz_random2 (base, base_size);
+
+      exp_size = urandom () % SIZE;
+      mpz_random2 (exp, exp_size);
+
+      mod_size = urandom () % SIZE /* - SIZE/2 */;
+      mpz_random2 (mod, mod_size);
+      if (mpz_cmp_ui (mod, 0) == 0)
+       continue;
+
+      /* This is mathematically undefined.  */
+      if (mpz_cmp_ui (base, 0) == 0 && mpz_cmp_ui (exp, 0) == 0)
+       continue;
+
+#if 0
+      putc ('\n', stderr);
+      debug_mp (base, -16);
+      debug_mp (exp, -16);
+      debug_mp (mod, -16);
+#endif
+
+      mpz_powm (r1, base, exp, mod);
+
+      mpz_set_ui (r2, 1);
+      mpz_set (base2, base);
+      mpz_set (exp2, exp);
+
+      mpz_mod (r2, r2, mod);   /* needed when exp==0 and mod==1 */
+      while (mpz_cmp_ui (exp2, 0) != 0)
+       {
+         mpz_mod_ui (t1, exp2, 2);
+         if (mpz_cmp_ui (t1, 0) != 0)
+           {
+             mpz_mul (r2, r2, base2);
+             mpz_mod (r2, r2, mod);
+           }
+         mpz_mul (base2, base2, base2);
+         mpz_mod (base2, base2, mod);
+         mpz_div_ui (exp2, exp2, 2);
+       }
+
+#if 0
+      debug_mp (r1, -16);
+      debug_mp (r2, -16);
+#endif
+
+      if (mpz_cmp (r1, r2) != 0)
+       abort ();
+    }
+
+  exit (0);
+}
+
+dump_abort (dividend, divisor)
+     MP_INT *dividend, *divisor;
+{
+  fprintf (stderr, "ERROR\n");
+  fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+  fprintf (stderr, "divisor  = "); debug_mp (divisor, -16);
+  abort();
+}
+
+void
+debug_mp (x, base)
+     MP_INT *x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/t-powm_ui.c b/ghc/rts/gmp/mpz/tests/t-powm_ui.c
new file mode 100644 (file)
index 0000000..b88fa98
--- /dev/null
@@ -0,0 +1,120 @@
+/* Test mpz_powm_ui, mpz_mul. mpz_mod, mpz_mod_ui, mpz_div_ui.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 8
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t base, mod;
+  mpz_t r1, r2, base2;
+  mp_size_t base_size, mod_size;
+  mp_limb_t exp, exp2;
+  int i;
+  int reps = 10000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (base);
+  mpz_init (mod);
+  mpz_init (r1);
+  mpz_init (r2);
+  mpz_init (base2);
+
+  for (i = 0; i < reps; i++)
+    {
+      base_size = urandom () % SIZE /* - SIZE/2 */;
+      mpz_random2 (base, base_size);
+
+      mpn_random2 (&exp, 1);
+
+      mod_size = urandom () % SIZE /* - SIZE/2 */;
+      mpz_random2 (mod, mod_size);
+      if (mpz_cmp_ui (mod, 0) == 0)
+       continue;
+
+      /* This is mathematically undefined.  */
+      if (mpz_cmp_ui (base, 0) == 0 && exp == 0)
+       continue;
+
+#if 0
+      putc ('\n', stderr);
+      debug_mp (base, -16);
+      debug_mp (mod, -16);
+#endif
+
+      mpz_powm_ui (r1, base, (unsigned long int) exp, mod);
+
+      mpz_set_ui (r2, 1);
+      mpz_set (base2, base);
+      exp2 = exp;
+
+      mpz_mod (r2, r2, mod);   /* needed when exp==0 and mod==1 */
+      while (exp2 != 0)
+       {
+         if (exp2 % 2 != 0)
+           {
+             mpz_mul (r2, r2, base2);
+             mpz_mod (r2, r2, mod);
+           }
+         mpz_mul (base2, base2, base2);
+         mpz_mod (base2, base2, mod);
+         exp2 = exp2 / 2;
+       }
+
+#if 0
+      debug_mp (r1, -16);
+      debug_mp (r2, -16);
+#endif
+
+      if (mpz_cmp (r1, r2) != 0)
+       abort ();
+    }
+
+  exit (0);
+}
+
+dump_abort (dividend, divisor)
+     MP_INT *dividend, *divisor;
+{
+  fprintf (stderr, "ERROR\n");
+  fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+  fprintf (stderr, "divisor  = "); debug_mp (divisor, -16);
+  abort();
+}
+
+void
+debug_mp (x, base)
+     MP_INT *x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/t-sqrtrem.c b/ghc/rts/gmp/mpz/tests/t-sqrtrem.c
new file mode 100644 (file)
index 0000000..f5fcd09
--- /dev/null
@@ -0,0 +1,98 @@
+/* Test mpz_add, mpz_add_ui, mpz_cmp, mpz_cmp, mpz_mul, mpz_sqrtrem.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t x2;
+  mpz_t x, rem;
+  mpz_t temp, temp2;
+  mp_size_t x2_size;
+  int i;
+  int reps = 100000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (x2);
+  mpz_init (x);
+  mpz_init (rem);
+  mpz_init (temp);
+  mpz_init (temp2);
+
+  for (i = 0; i < reps; i++)
+    {
+      x2_size = urandom () % SIZE;
+
+      mpz_random2 (x2, x2_size);
+
+      mpz_sqrtrem (x, rem, x2);
+      mpz_mul (temp, x, x);
+
+      /* Is square of result > argument?  */
+      if (mpz_cmp (temp, x2) > 0)
+       dump_abort (x2, x, rem);
+
+      mpz_add_ui (temp2, x, 1);
+      mpz_mul (temp2, temp2, temp2);
+
+      /* Is square of (result + 1) <= argument?  */
+      if (mpz_cmp (temp2, x2) <= 0)
+       dump_abort (x2, x, rem);
+
+      mpz_add (temp2, temp, rem);
+
+      /* Is the remainder wrong?  */
+      if (mpz_cmp (x2, temp2) != 0)
+       dump_abort (x2, x, rem);
+    }
+
+  exit (0);
+}
+
+dump_abort (x2, x, rem)
+     mpz_t x2, x, rem;
+{
+  fprintf (stderr, "ERROR\n");
+  fprintf (stderr, "x2        = "); debug_mp (x2, -16);
+  fprintf (stderr, "x         = "); debug_mp (x, -16);
+  fprintf (stderr, "remainder = "); debug_mp (rem, -16);
+  abort();
+}
+
+void
+debug_mp (x, base)
+     mpz_t x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/t-tdiv.c b/ghc/rts/gmp/mpz/tests/t-tdiv.c
new file mode 100644 (file)
index 0000000..d646ed8
--- /dev/null
@@ -0,0 +1,118 @@
+/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_tdiv_qr, mpz_tdiv_q,
+   mpz_tdiv_r, mpz_mul.
+
+Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t dividend, divisor;
+  mpz_t quotient, remainder;
+  mpz_t quotient2, remainder2;
+  mpz_t temp;
+  mp_size_t dividend_size, divisor_size;
+  int i;
+  int reps = 100000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (dividend);
+  mpz_init (divisor);
+  mpz_init (quotient);
+  mpz_init (remainder);
+  mpz_init (quotient2);
+  mpz_init (remainder2);
+  mpz_init (temp);
+
+  for (i = 0; i < reps; i++)
+    {
+      dividend_size = urandom () % SIZE - SIZE/2;
+      mpz_random2 (dividend, dividend_size);
+
+      divisor_size = urandom () % SIZE - SIZE/2;
+      mpz_random2 (divisor, divisor_size);
+      if (mpz_cmp_ui (divisor, 0) == 0)
+       continue;
+
+      mpz_tdiv_qr (quotient, remainder, dividend, divisor);
+      mpz_tdiv_q (quotient2, dividend, divisor);
+      mpz_tdiv_r (remainder2, dividend, divisor);
+
+      /* First determine that the quotients and remainders computed
+        with different functions are equal.  */
+      if (mpz_cmp (quotient, quotient2) != 0)
+       dump_abort (dividend, divisor);
+      if (mpz_cmp (remainder, remainder2) != 0)
+       dump_abort (dividend, divisor);
+
+      /* Check if the sign of the quotient is correct.  */
+      if (mpz_cmp_ui (quotient, 0) != 0)
+       if ((mpz_cmp_ui (quotient, 0) < 0)
+           != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0))
+       dump_abort (dividend, divisor);
+
+      /* Check if the remainder has the same sign as the dividend
+        (quotient rounded towards 0).  */
+      if (mpz_cmp_ui (remainder, 0) != 0)
+       if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0))
+         dump_abort (dividend, divisor);
+
+      mpz_mul (temp, quotient, divisor);
+      mpz_add (temp, temp, remainder);
+      if (mpz_cmp (temp, dividend) != 0)
+       dump_abort (dividend, divisor);
+
+      mpz_abs (temp, divisor);
+      mpz_abs (remainder, remainder);
+      if (mpz_cmp (remainder, temp) >= 0)
+       dump_abort (dividend, divisor);
+    }
+
+  exit (0);
+}
+
+dump_abort (dividend, divisor)
+     mpz_t dividend, divisor;
+{
+  fprintf (stderr, "ERROR\n");
+  fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+  fprintf (stderr, "divisor  = "); debug_mp (divisor, -16);
+  abort();
+}
+
+void
+debug_mp (x, base)
+     mpz_t x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}
diff --git a/ghc/rts/gmp/mpz/tests/t-tdiv_ui.c b/ghc/rts/gmp/mpz/tests/t-tdiv_ui.c
new file mode 100644 (file)
index 0000000..8d73b11
--- /dev/null
@@ -0,0 +1,117 @@
+/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_tdiv_qr_ui, mpz_tdiv_q_ui,
+   mpz_tdiv_r_ui, mpz_mul_ui.
+
+Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "urandom.h"
+
+void debug_mp ();
+
+#ifndef SIZE
+#define SIZE 16
+#endif
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  mpz_t dividend;
+  mpz_t quotient, remainder;
+  mpz_t quotient2, remainder2;
+  mpz_t temp;
+  mp_size_t dividend_size;
+  mp_limb_t divisor;
+  int i;
+  int reps = 100000;
+
+  if (argc == 2)
+     reps = atoi (argv[1]);
+
+  mpz_init (dividend);
+  mpz_init (quotient);
+  mpz_init (remainder);
+  mpz_init (quotient2);
+  mpz_init (remainder2);
+  mpz_init (temp);
+
+  for (i = 0; i < reps; i++)
+    {
+      dividend_size = urandom () % SIZE - SIZE/2;
+      mpz_random2 (dividend, dividend_size);
+
+      divisor = urandom ();
+      if (divisor == 0)
+       continue;
+
+      mpz_tdiv_qr_ui (quotient, remainder, dividend, divisor);
+      mpz_tdiv_q_ui (quotient2, dividend, divisor);
+      mpz_tdiv_r_ui (remainder2, dividend, divisor);
+
+      /* First determine that the quotients and remainders computed
+        with different functions are equal.  */
+      if (mpz_cmp (quotient, quotient2) != 0)
+       dump_abort (dividend, divisor);
+      if (mpz_cmp (remainder, remainder2) != 0)
+       dump_abort (dividend, divisor);
+
+      /* Check if the sign of the quotient is correct.  */
+      if (mpz_cmp_ui (quotient, 0) != 0)
+       if ((mpz_cmp_ui (quotient, 0) < 0)
+           != (mpz_cmp_ui (dividend, 0) < 0))
+       dump_abort (dividend, divisor);
+
+      /* Check if the remainder has the same sign as the dividend
+        (quotient rounded towards 0).  */
+      if (mpz_cmp_ui (remainder, 0) != 0)
+       if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0))
+         dump_abort (dividend, divisor);
+
+      mpz_mul_ui (temp, quotient, divisor);
+      mpz_add (temp, temp, remainder);
+      if (mpz_cmp (temp, dividend) != 0)
+       dump_abort (dividend, divisor);
+
+      mpz_abs (remainder, remainder);
+      if (mpz_cmp_ui (remainder, divisor) >= 0)
+       dump_abort (dividend, divisor);
+    }
+
+  exit (0);
+}
+
+dump_abort (dividend, divisor)
+     mpz_t dividend;
+     mp_limb_t divisor;
+{
+  fprintf (stderr, "ERROR\n");
+  fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
+  fprintf (stderr, "divisor  = %lX\n", divisor);
+  abort();
+}
+
+void
+debug_mp (x, base)
+     mpz_t x;
+{
+  mpz_out_str (stderr, base, x); fputc ('\n', stderr);
+}