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

mercurial at gmplib.org mercurial at gmplib.org
Sun Jul 12 08:20:33 CEST 2026


details:   /var/hg/gmp/rev/c14ab54ef5ca
changeset: 18557:c14ab54ef5ca
user:      Marco Bodrato <bodrato at mail.dm.unipi.it>
date:      Sun Jul 12 08:15:55 2026 +0200
description:
mini-gmp/mini-gmp.[ch]: Add the new function mpz_perfect_square_root

details:   /var/hg/gmp/rev/9597e16aee1b
changeset: 18558:9597e16aee1b
user:      Marco Bodrato <bodrato at mail.dm.unipi.it>
date:      Sun Jul 12 08:16:42 2026 +0200
description:
mini-gmp/tests/t-sqrt.c: Test mpz_perfect_square_root

details:   /var/hg/gmp/rev/cf18512fa8ca
changeset: 18559:cf18512fa8ca
user:      Marco Bodrato <bodrato at mail.dm.unipi.it>
date:      Sun Jul 12 08:17:46 2026 +0200
description:
tests/mpz/t-perfsqr.c: Check the format of return values

details:   /var/hg/gmp/rev/27b7b4d951c0
changeset: 18560:27b7b4d951c0
user:      Marco Bodrato <bodrato at mail.dm.unipi.it>
date:      Sun Jul 12 08:18:36 2026 +0200
description:
mpn/generic/sqrtrem.c (mpn_divappr_q): Return the highest limb instead of writing it

details:   /var/hg/gmp/rev/29913bdd5d7c
changeset: 18561:29913bdd5d7c
user:      Marco Bodrato <bodrato at mail.dm.unipi.it>
date:      Sun Jul 12 08:19:13 2026 +0200
description:
ChangeLog

diffstat:

 ChangeLog               |   7 +++
 mini-gmp/ChangeLog      |   7 +++
 mini-gmp/mini-gmp.c     |  17 +++++++-
 mini-gmp/mini-gmp.h     |   1 +
 mini-gmp/tests/t-sqrt.c |  87 ++++++++++++++++++++++++++++++++++--------------
 mpn/generic/sqrtrem.c   |   6 +-
 tests/mpz/reuse.c       |   3 +-
 tests/mpz/t-perfsqr.c   |   8 ++-
 8 files changed, 100 insertions(+), 36 deletions(-)

diffs (truncated from 302 to 300 lines):

diff -r ac62fde50484 -r 29913bdd5d7c ChangeLog
--- a/ChangeLog	Sat Jul 04 21:35:55 2026 +0200
+++ b/ChangeLog	Sun Jul 12 08:19:13 2026 +0200
@@ -1,3 +1,10 @@
+2026-07-12  Marco Bodrato <marco.bodrato at protonmail.com>
+
+	* tests/mpz/t-perfsqr.c: Check the format of return values.
+
+	* mpn/generic/sqrtrem.c (mpn_divappr_q): Return the highest limb
+	instead of writing it.
+
 2026-07-04 Seth Troisi <sethtroisi at google.com>
 
 	* mpn/generic/perfsqr.c: New function mpn_probab_perfect_square_p.
diff -r ac62fde50484 -r 29913bdd5d7c mini-gmp/ChangeLog
--- a/mini-gmp/ChangeLog	Sat Jul 04 21:35:55 2026 +0200
+++ b/mini-gmp/ChangeLog	Sun Jul 12 08:19:13 2026 +0200
@@ -1,3 +1,10 @@
+2026-07-12  Marco Bodrato <marco.bodrato at protonmail.com>
+
+	* mini-gmp.c (mpz_perfect_square_root): New function.
+	(mpz_perfect_square_p): Use it.
+	* mini-gmp.h: Add declaration.
+	* tests/t-sqrt.c: Test the new function.
+
 2026-06-26  Marco Bodrato <marco.bodrato at protonmail.com>
 
 	* mini-gmp.c (mpz_init_setbit): New function.
diff -r ac62fde50484 -r 29913bdd5d7c mini-gmp/mini-gmp.c
--- a/mini-gmp/mini-gmp.c	Sat Jul 04 21:35:55 2026 +0200
+++ b/mini-gmp/mini-gmp.c	Sun Jul 12 08:19:13 2026 +0200
@@ -3342,12 +3342,23 @@
 }
 
 int
-mpz_perfect_square_p (const mpz_t u)
+mpz_perfect_square_root (mpz_t r, const mpz_t u)
 {
   if (u->_mp_size <= 0)
-    return (u->_mp_size == 0);
+    {
+      int ret = u->_mp_size == 0;
+      if (r != NULL)
+	r->_mp_size = 0;
+      return ret;
+    }
   else
-    return mpz_root (NULL, u, 2);
+    return mpz_root (r, u, 2);
+}
+
+int
+mpz_perfect_square_p (const mpz_t u)
+{
+  return mpz_perfect_square_root (NULL, u);
 }
 
 int
diff -r ac62fde50484 -r 29913bdd5d7c mini-gmp/mini-gmp.h
--- a/mini-gmp/mini-gmp.h	Sat Jul 04 21:35:55 2026 +0200
+++ b/mini-gmp/mini-gmp.h	Sun Jul 12 08:19:13 2026 +0200
@@ -212,6 +212,7 @@
 
 void mpz_sqrtrem (mpz_t, mpz_t, const mpz_t);
 void mpz_sqrt (mpz_t, const mpz_t);
+int mpz_perfect_square_root (mpz_t, const mpz_t);
 int mpz_perfect_square_p (const mpz_t);
 
 void mpz_pow_ui (mpz_t, const mpz_t, unsigned long);
diff -r ac62fde50484 -r 29913bdd5d7c mini-gmp/tests/t-sqrt.c
--- a/mini-gmp/tests/t-sqrt.c	Sat Jul 04 21:35:55 2026 +0200
+++ b/mini-gmp/tests/t-sqrt.c	Sun Jul 12 08:19:13 2026 +0200
@@ -1,6 +1,6 @@
 /*
 
-Copyright 2012, 2014, Free Software Foundation, Inc.
+Copyright 2012, 2014, 2026, Free Software Foundation, Inc.
 
 This file is part of the GNU MP Library test suite.
 
@@ -31,25 +31,24 @@
 sqrtrem_valid_p (const mpz_t u, const mpz_t s, const mpz_t r)
 {
   mpz_t t;
+  int ret;
 
   mpz_init (t);
   mpz_mul (t, s, s);
   mpz_sub (t, u, t);
   if (mpz_sgn (t) < 0 || mpz_cmp (t, r) != 0)
     {
-      mpz_clear (t);
-      return 0;
+      ret = 0;
     }
-  mpz_add_ui (t, s, 1);
-  mpz_mul (t, t, t);
-  if (mpz_cmp (t, u) <= 0)
+  else
     {
-      mpz_clear (t);
-      return 0;
+      mpz_add_ui (t, s, 1);
+      mpz_mul (t, t, t);
+      ret = mpz_cmp (t, u) > 0;
     }
 
   mpz_clear (t);
-  return 1;
+  return ret;
 }
 
 void
@@ -105,6 +104,7 @@
 testmain (int argc, char **argv)
 {
   unsigned i;
+  int res;
   mpz_t u, s, r;
 
   mpz_init (s);
@@ -117,12 +117,26 @@
       abort ();
     }
 
+  /* FIXME: We should also check that r is still a valid mpz_t */
+  if (mpz_perfect_square_root (r, u))
+    {
+      fprintf (stderr, "mpz_perfect_square_root failed on -1.\n");
+      abort ();
+    }
+
   if (!mpz_perfect_square_p (s))
     {
       fprintf (stderr, "mpz_perfect_square_p failed on 0.\n");
       abort ();
     }
 
+  res = mpz_perfect_square_root (r, s);
+  if (!res || mpz_cmp_ui (r, 0) != 0)
+    {
+      fprintf (stderr, "mpz_perfect_square_root failed on 0.\n");
+      abort ();
+    }
+
   for (i = 0; i < COUNT; i++)
     {
       mini_rrandomb (u, MAXBITS - (i & 0xFF));
@@ -153,27 +167,48 @@
 	mpz_sub_ui (u, u, 1);
       }
 
-      if ((mpz_sgn (u) <= 0 || (i & 1)) ?
-	  mpz_perfect_square_p (u) :
-	  mpn_perfect_square_p (mpz_limbs_read (u), mpz_size (u)))
+      if (i & 2)
 	{
-	  fprintf (stderr, "mp%s_perfect_square_p failed on non square:\n",
-		   (mpz_sgn (u) <= 0 || (i & 1)) ? "z" : "n");
-	  dump ("u", u);
-	  abort ();
-	}
+	  if ((mpz_sgn (u) <= 0 || (i & 1)) ?
+	      mpz_perfect_square_p (u) :
+	      mpn_perfect_square_p (mpz_limbs_read (u), mpz_size (u)))
+	    {
+	      fprintf (stderr, "mp%s_perfect_square_p failed on non square:\n",
+		       (mpz_sgn (u) <= 0 || (i & 1)) ? "z" : "n");
+	      dump ("u", u);
+	      abort ();
+	    }
 
-      mpz_mul (u, s, s);
-      if (!((mpz_sgn (u) <= 0 || (i & 1)) ?
-	    mpz_perfect_square_p (u) :
-	    mpn_perfect_square_p (mpz_limbs_read (u), mpz_size (u))))
+	  mpz_mul (u, s, s);
+	  if (!((mpz_sgn (u) <= 0 || (i & 1)) ?
+		mpz_perfect_square_p (u) :
+		mpn_perfect_square_p (mpz_limbs_read (u), mpz_size (u))))
+	    {
+	      fprintf (stderr, "mp%s_perfect_square_p failed on square:\n",
+		       (mpz_sgn (u) <= 0 || (i & 1)) ? "z" : "n");
+	      dump ("u", u);
+	      abort ();
+	    }
+	}
+      else
 	{
-	  fprintf (stderr, "mp%s_perfect_square_p failed on square:\n",
-		   (mpz_sgn (u) <= 0 || (i & 1)) ? "z" : "n");
-	  dump ("u", u);
-	  abort ();
+	  /* FIXME: We should also check that r is still a valid mpz_t */
+	  if (mpz_perfect_square_root (r, u))
+	    {
+	      fprintf (stderr, "mpz_perfect_square_root failed on non square:\n");
+	      dump ("u", u);
+	      abort ();
+	    }
+
+	  mpz_mul (u, s, s);
+	  res = mpz_perfect_square_root (r, u);
+	  if (!res || mpz_cmp (r, s) != 0)
+	    {
+	      fprintf (stderr, "mpz_perfect_square_root failed on square:\n");
+	      dump ("u", u);
+	      abort ();
+	    }
 	}
-
     }
   mpz_clear (u);
   mpz_clear (s);
diff -r ac62fde50484 -r 29913bdd5d7c mpn/generic/sqrtrem.c
--- a/mpn/generic/sqrtrem.c	Sat Jul 04 21:35:55 2026 +0200
+++ b/mpn/generic/sqrtrem.c	Sun Jul 12 08:19:13 2026 +0200
@@ -276,7 +276,7 @@
 }
 
 #if USE_DIVAPPR_Q
-static void
+static mp_limb_t
 mpn_divappr_q (mp_ptr qp, mp_srcptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn, mp_ptr scratch)
 {
   gmp_pi1_t inv;
@@ -300,7 +300,7 @@
       qh = mpn_mu_divappr_q (qp, np, nn, dp, dn, TMP_ALLOC_LIMBS (itch));
       TMP_FREE;
     }
-  qp [nn - dn] = qh;
+  return qh;
 }
 #endif
 
@@ -344,7 +344,7 @@
   qp = tp + n + 1; /* l + 2 */
   TRACE(printf("div(appr)_q(,,%u,,%u) -> %u \n", (unsigned) n+1, (unsigned) h, (unsigned) (n + 1 - h + 1)));
 #if USE_DIVAPPR_Q
-  mpn_divappr_q (qp, tp, n + 1, sp + l, h, scratch);
+  qp [l + 1] = mpn_divappr_q (qp, tp, n + 1, sp + l, h, scratch);
 #else
   mpn_div_q (qp, tp, n + 1, sp + l, h, scratch);
 #endif
diff -r ac62fde50484 -r 29913bdd5d7c tests/mpz/reuse.c
--- a/tests/mpz/reuse.c	Sat Jul 04 21:35:55 2026 +0200
+++ b/tests/mpz/reuse.c	Sun Jul 12 08:19:13 2026 +0200
@@ -2,7 +2,8 @@
 
    Test all relevant functions except:
 	mpz_bin_ui
-	mpz_nextprime
+	mpz_{next,prev}prime
+	mpz_perfect_square_root
 	mpz_mul_si
 	mpz_addmul_ui (should this really allow a+=a*c?)
 
diff -r ac62fde50484 -r 29913bdd5d7c tests/mpz/t-perfsqr.c
--- a/tests/mpz/t-perfsqr.c	Sat Jul 04 21:35:55 2026 +0200
+++ b/tests/mpz/t-perfsqr.c	Sun Jul 12 08:19:13 2026 +0200
@@ -1,6 +1,6 @@
 /* Test mpz_perfect_square_p and mpz_perfect_square_root.
 
-Copyright 2000-2002 Free Software Foundation, Inc.
+Copyright 2000-2002, 2026 Free Software Foundation, Inc.
 
 This file is part of the GNU MP Library test suite.
 
@@ -117,6 +117,7 @@
       printf ("mpz_perfect_square_root -4 not a square\n");
       abort ();
     }
+  MPZ_CHECK_FORMAT (root);
 
   // 0 and 1 are both perfect squares with respective root 0 and 1.
   for (unsigned int m = 0; m < 2; m++)
@@ -191,6 +192,7 @@
           printf    ("   mpz_sqrt                %d\n", want);
           abort ();
         }
+      MPZ_CHECK_FORMAT (rop);
       if (res && mpz_cmp(x, rop) != 0)
         {
           printf    ("mpz_perfect_square_root and mpz_sqrt differ\n");
@@ -204,6 +206,7 @@
       /* Check that same variable as input and output works */
       mpz_set(rop, x2);
       res = mpz_perfect_square_root (rop, rop);
+      MPZ_CHECK_FORMAT (rop);
       if (res != want || (res && mpz_cmp(x, rop) != 0))
         {
           printf    ("mpz_perfect_square_root differ when output == input\n");
@@ -217,8 +220,7 @@
     }
 
   if (reps > 1000 && cnt == 0) {
-    printf("No perfect squares found in %d reps", reps);
-    abort();
+    printf("No perfect squares found in %d reps\n", reps);
   }


More information about the gmp-commit mailing list