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

mercurial at gmplib.org mercurial at gmplib.org
Fri Feb 21 18:32:48 UTC 2014


details:   /var/hg/gmp/rev/cc2a98d41eab
changeset: 16309:cc2a98d41eab
user:      Marco Bodrato <bodrato at mail.dm.unipi.it>
date:      Fri Feb 21 19:28:25 2014 +0100
description:
mini-gmp: New function mpn_sqrtrem.

details:   /var/hg/gmp/rev/5cbbb43c9217
changeset: 16310:5cbbb43c9217
user:      Marco Bodrato <bodrato at mail.dm.unipi.it>
date:      Fri Feb 21 19:30:14 2014 +0100
description:
mini-gmp/tests/t-sqrt.c: Test mpn_sqrtrem.

details:   /var/hg/gmp/rev/45bd52435e58
changeset: 16311:45bd52435e58
user:      Marco Bodrato <bodrato at mail.dm.unipi.it>
date:      Fri Feb 21 19:32:38 2014 +0100
description:
ChangeLog

diffstat:

 ChangeLog               |   6 ++++
 mini-gmp/mini-gmp.c     |  21 ++++++++++++++
 mini-gmp/mini-gmp.h     |   1 +
 mini-gmp/tests/t-sqrt.c |  70 ++++++++++++++++++++++++++++++++++++++++++++----
 4 files changed, 92 insertions(+), 6 deletions(-)

diffs (170 lines):

diff -r 4560d88e082a -r 45bd52435e58 ChangeLog
--- a/ChangeLog	Mon Feb 17 22:13:07 2014 +0100
+++ b/ChangeLog	Fri Feb 21 19:32:38 2014 +0100
@@ -1,3 +1,9 @@
+2014-02-21 Marco Bodrato <bodrato at mail.dm.unipi.it>
+
+	* mini-gmp/mini-gmp.c (mpn_sqrtrem): New function.
+	* mini-gmp/mini-gmp.h: Declare it.
+	* mini-gmp/tests/t-sqrt.c: Test it.
+
 2014-02-17  Niels Möller  <nisse at lysator.liu.se>
 
 	* mpn/generic/div_qr_1.c (mpn_div_qr_1): Revert yesterday's fix.
diff -r 4560d88e082a -r 45bd52435e58 mini-gmp/mini-gmp.c
--- a/mini-gmp/mini-gmp.c	Mon Feb 17 22:13:07 2014 +0100
+++ b/mini-gmp/mini-gmp.c	Fri Feb 21 19:32:38 2014 +0100
@@ -3285,6 +3285,27 @@
   assert (p [n-1] != 0);
   return mpz_root (NULL, mpz_roinit_n (t, p, n), 2);
 }
+
+mp_size_t
+mpn_sqrtrem (mp_ptr sp, mp_ptr rp, mp_srcptr p, mp_size_t n)
+{
+  mpz_t s, r, u;
+  mp_size_t res;
+
+  assert (n > 0);
+  assert (p [n-1] != 0);
+
+  mpz_init (r);
+  mpz_init (s);
+  mpz_rootrem (s, r, mpz_roinit_n (u, p, n), 2);
+  mpn_copyd (sp, s->_mp_d, s->_mp_size);
+  mpz_clear (s);
+  res = r->_mp_size;
+  if (rp)
+    mpn_copyd (rp, r->_mp_d, res);
+  mpz_clear (r);
+  return res;
+}
 

 /* Combinatorics */
 
diff -r 4560d88e082a -r 45bd52435e58 mini-gmp/mini-gmp.h
--- a/mini-gmp/mini-gmp.h	Mon Feb 17 22:13:07 2014 +0100
+++ b/mini-gmp/mini-gmp.h	Fri Feb 21 19:32:38 2014 +0100
@@ -99,6 +99,7 @@
 void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
 void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t);
 int mpn_perfect_square_p (mp_srcptr, mp_size_t);
+mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t);
 
 mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
 mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
diff -r 4560d88e082a -r 45bd52435e58 mini-gmp/tests/t-sqrt.c
--- a/mini-gmp/tests/t-sqrt.c	Mon Feb 17 22:13:07 2014 +0100
+++ b/mini-gmp/tests/t-sqrt.c	Fri Feb 21 19:32:38 2014 +0100
@@ -24,7 +24,7 @@
 #include "testutils.h"
 
 #define MAXBITS 400
-#define COUNT 10000
+#define COUNT 9000
 
 static void
 dump (const char *label, const mpz_t x)
@@ -61,24 +61,71 @@
 }
 
 void
+mpz_mpn_sqrtrem (mpz_t s, mpz_t r, const mpz_t u)
+{
+  mp_limb_t *sp, *rp;
+  mp_size_t un, sn, ret;
+
+  un = mpz_size (u);
+
+  mpz_xor (s, s, u);
+  sn = (un + 1) / 2;
+  sp = mpz_limbs_write (s, sn + 1);
+  sp [sn] = 11;
+
+  if (un & 1)
+    rp = NULL; /* Exploits the fact that r already is correct. */
+  else {
+    mpz_add (r, u, s);
+    rp = mpz_limbs_write (r, un + 1);
+    rp [un] = 19;
+  }
+
+  ret = mpn_sqrtrem (sp, rp, mpz_limbs_read (u), un);
+
+  if (sp [sn] != 11)
+    {
+      fprintf (stderr, "mpn_sqrtrem buffer overrun on sp.\n");
+      abort ();
+    }
+  if (un & 1) {
+    if ((ret != 0) != (mpz_size (r) != 0)) {
+      fprintf (stderr, "mpn_sqrtrem wrong return value with NULL.\n");
+      abort ();
+    }
+  } else {
+    mpz_limbs_finish (r, ret);
+    if (ret != mpz_size (r)) {
+      fprintf (stderr, "mpn_sqrtrem wrong return value.\n");
+      abort ();
+    }
+    if (rp [un] != 19)
+      {
+	fprintf (stderr, "mpn_sqrtrem buffer overrun on rp.\n");
+	abort ();
+      }
+  } 
+  
+  mpz_limbs_finish (s, (un + 1) / 2);
+}
+
+void
 testmain (int argc, char **argv)
 {
   unsigned i;
   mpz_t u, s, r;
 
-  mpz_init (u);
   mpz_init (s);
   mpz_init (r);
 
-  mpz_set_si (u, -1);
+  mpz_init_set_si (u, -1);
   if (mpz_perfect_square_p (u))
     {
       fprintf (stderr, "mpz_perfect_square_p failed on -1.\n");
       abort ();
     }
 
-  mpz_set_ui (u, 0);
-  if (!mpz_perfect_square_p (u))
+  if (!mpz_perfect_square_p (s))
     {
       fprintf (stderr, "mpz_perfect_square_p failed on 0.\n");
       abort ();
@@ -86,7 +133,7 @@
 
   for (i = 0; i < COUNT; i++)
     {
-      mini_rrandomb (u, MAXBITS);
+      mini_rrandomb (u, MAXBITS - (i & 0xFF));
       mpz_sqrtrem (s, r, u);
 
       if (!sqrtrem_valid_p (u, s, r))
@@ -98,6 +145,17 @@
 	  abort ();
 	}
 
+      mpz_mpn_sqrtrem (s, r, u);
+
+      if (!sqrtrem_valid_p (u, s, r))
+	{
+	  fprintf (stderr, "mpn_sqrtrem failed:\n");
+	  dump ("u", u);
+	  dump ("sqrt", s);
+	  dump ("rem", r);
+	  abort ();
+	}
+
       if (mpz_sgn (r) == 0) {
 	mpz_neg (u, u);
 	mpz_sub_ui (u, u, 1);


More information about the gmp-commit mailing list