mpz_prevprime

Marco Bodrato bodrato at mail.dm.unipi.it
Thu Mar 26 21:00:26 UTC 2020


Ciao,

Il 2020-03-25 02:25 Seth Troisi ha scritto:
> I'm back with a new mpz_prevprime patch

diff -r 805304ca965a doc/gmp.texi
+ at deftypefun int mpz_prevprime (mpz_t @var{rop}, const mpz_t @var{op})

+If previous prime doesn't exist (e.g. @var{op} < 3), rop is unchanged 
and
+0 is returned.

I suggest "i.e." instead of "e.g.".

diff -r 805304ca965a mpz/nextprime.c
+findnext_small (unsigned t, short diff)
[...]
+  ASSERT (t > 0 || (diff < 0 && t > 2));

This is equivalent to (t > 0). Do you mean (t > 2 || (diff > 0 && t > 
0))?

+  t = diff > 0 ? ((t + 1) | (t > 1)) :
+                 ((t == 3) ? 2 : ((t - 2) | 1));

Maybe move this to the caller side? Or partially, leaving here just
   ASSERT (t >= 2);
   t |= (t != 2);

-void
-mpz_nextprime (mpz_ptr p, mpz_srcptr n)
+int
+findnext (mpz_ptr p,

If the function is not public any more, use static.

-  mpz_setbit (p, 0);

This line can still be here, maybe converted to
* PTR (p) |= 1;

+  /* smaller numbers handled earlier*/
+  ASSERT (nbits >= 15);

Not needed. Maybe ASSERT (nbits > 3), because we don't want to handle 
very small numbers with this code.

+int
+mpz_prevprime (mpz_ptr p, mpz_srcptr n)
+{
+  /* First handle tiny numbers */
+  if (mpz_cmp_ui (n, 2) <= 0)
+    return 0;
+
+  if (mpz_cmp_ui (n, NP_SMALL_LIMIT) < 0)
+    {
+      ASSERT (NP_SMALL_LIMIT < UINT_MAX);
+      mpz_set_ui (p, findnext_small (SIZ (n) > 0 ? mpz_get_ui (n) : 1, 
-2));
+      return 2;
+    }

The line "if (mpz_cmp_ui (n, 2) <= 0)" already handle the case (SIZ (n) 
<= 0), checking if (SIZ (n) > 0) is a nonsense
Anyway... assume that code is used: what happens if findnext_small(1,-2) 
is called?

diff -r 805304ca965a tests/mpz/t-nextprime.c
[...]
+refmpz_prevprime (mpz_ptr p, mpz_srcptr t)
[...]
+  if (mpz_cmp_ui(t, 3) <= 0)

The loop after that branch handles also that case, don't it?


  test_largegaps ()
  {
[...]
+  mpz_set_ui (n, 3842610773);
[...]
+  mpz_set_ui (n, 18361375334787046697UL);

Those lines can fail at compile time... if 3842610773 does not fit in an 
int and 18361375334787046697 not in an unsigned long. E.g. when 
sizeof(int)==4.
Use _set_str.

+  mpz_mul_ui (n, n, 4280516017);
[...]
+  mpz_mul_ui (n, n, 3483347771);

...

> I also added large negative tests for mpz_nextprime

To be honest... I do not like this (undocumented) detail of the current 
behaviour of _nextprime. I personally do not like the idea to enforce it 
with a test...

> and we can enable test_largegaps now that the default gap is smaller

Yes, we should.
I would also check many gaps around 2^{16n}, to check if everything 
works correctly when the search crosses the limb boundaries.
Maybe structuring the test with a table {"number(base16?)", gap}, i.e.
with (also) something like:
{"65521", 16},
{"4294967291", 20},
{"281474976710597", 80},
{"18446744073709551557", 72},
{"1208925819614629174706111", 78},
{"79228162514264337593543950319", 78},
{"5192296858534827628530496329220021", 100},
{"340282366920938463463374607431768211297", 210},


+void
+test_prevprime (gmp_randstate_ptr rands, int reps)
[...]
+  /* Test mpz_prevprime(3 <= n < 2^45) returns 2. */
[...]
+  /* Test mpz_prevprime(n > 2^70) returns 1. */
[...]
+        if ( retval != 1 )
[...]

I do not understand. A test-function should fail if a function behaviour 
does not agree with the documented interface, or it can fail for some 
other kind of regression that we want to avoid...
Your test will warn us against possible improvements! What if the future 
primality testing functions will return 2 on some large primes?

Ok, I'm sleepy now. I hope I did not write wrong things. Good night!

Ĝis,
m


More information about the gmp-devel mailing list