I made a few improvements. tested with '--enable-assert' and verified no impact to timing with `./tune/speed -f 1.02 -s 10-260 mpz_prevprime -p100000000 -P time_prevprime` comparing with mpz_nextprime (before and after my change)
On Fri, Mar 27, 2020 at 2:29 AM Seth Troisi <brain...@gmail.com> wrote: > Thanks for the quick review and probing comments. > > On Thu, Mar 26, 2020 at 2:00 PM Marco Bodrato <bodr...@mail.dm.unipi.it> > wrote: > >> 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 >> +@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.". >> > Replaced > >> >> 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))? >> > Yes. changed now. > >> >> + 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); >> > I moved this to the caller side (so that both findnext and findnext_small > consider p) and added some comments > >> >> -void >> -mpz_nextprime (mpz_ptr p, mpz_srcptr n) >> +int >> +findnext (mpz_ptr p, >> >> If the function is not public any more, use static. >> > Done. > >> >> - mpz_setbit (p, 0); >> >> This line can still be here, maybe converted to >> * PTR (p) |= 1; >> > This has been moved to the outer functions. > Maybe I should add a test that p is odd? > Something like ASSERT (PTR(p) & 1 == 0); > > >> + /* 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. >> > Changed back to nbits > 3 and added an ASSERT (SIZ(p) > 0); > >> >> +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? >> > This has been reworked but should never have been included. > >> >> 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? >> > Yes, I was counting by two but I reverted that at some point. > >> >> >> 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}, >> > I did this (using hex form) I threw in some 16*n-1 also > >> >> >> +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? >> > > I modified the tests so that it makes it more clean that it's testing that > it verifies the retval matches > the return of mpz_prob_prime. > > >> Ok, I'm sleepy now. I hope I did not write wrong things. Good night! >> > Given the number of times you are pointing our real issues, I wouldn't be > worried about writing one or two wrong comments :) > >> >> Ĝis, >> m > >
diff -r c5d0fcb06969 doc/gmp.texi --- a/doc/gmp.texi Sat Jul 04 23:15:41 2020 +0200 +++ b/doc/gmp.texi Fri Aug 28 03:44:14 2020 -0700 @@ -3563,8 +3563,19 @@ @deftypefun void mpz_nextprime (mpz_t @var{rop}, const mpz_t @var{op}) @cindex Next prime function Set @var{rop} to the next prime greater than @var{op}. - -This function uses a probabilistic algorithm to identify primes. For +@end deftypefun + +@deftypefun int mpz_prevprime (mpz_t @var{rop}, const mpz_t @var{op}) +@cindex Previous prime function +Set @var{rop} to the greatest prime less than @var{op}. + +If previous prime doesn't exist (i.e. @var{op} < 3), rop is unchanged and +0 is returned. + +Return 1 if @var{rop} is a probably prime, and 2 if @var{rop} is definitely +prime. + +These functions use a probabilistic algorithm to identify primes. For practical purposes it's adequate, the chance of a composite passing will be extremely small. @end deftypefun diff -r c5d0fcb06969 gmp-h.in --- a/gmp-h.in Sat Jul 04 23:15:41 2020 +0200 +++ b/gmp-h.in Fri Aug 28 03:44:14 2020 -0700 @@ -947,6 +947,9 @@ #define mpz_nextprime __gmpz_nextprime __GMP_DECLSPEC void mpz_nextprime (mpz_ptr, mpz_srcptr); +#define mpz_prevprime __gmpz_prevprime +__GMP_DECLSPEC int mpz_prevprime (mpz_ptr, mpz_srcptr); + #define mpz_out_raw __gmpz_out_raw #ifdef _GMP_H_HAVE_FILE __GMP_DECLSPEC size_t mpz_out_raw (FILE *, mpz_srcptr); diff -r c5d0fcb06969 mpz/nextprime.c --- a/mpz/nextprime.c Sat Jul 04 23:15:41 2020 +0200 +++ b/mpz/nextprime.c Fri Aug 28 03:44:14 2020 -0700 @@ -124,14 +124,19 @@ } static unsigned -mpz_nextprime_small (unsigned t) +findnext_small (unsigned t, short diff) { - ASSERT (t > 0); /* Expect t=1 if the operand was smaller.*/ + /* For diff= 2, expect t = 1 if operand was negative. + * For diff=-2, expect t >= 3 + */ + + /* Start from next candidate (2 or odd) */ + t = diff > 0 ? (t + 1) | (t > 1) + : ((t - 2) | 1) + (t == 3); + ASSERT (t >= 2); ASSERT (t < NP_SMALL_LIMIT); - /* Start from next candidate (2 or odd) */ - t = (t + 1) | (t > 1); - for (; ; t += 2) + for (; ; t += diff) { unsigned prime = 3; for (int i = 0; ; prime += primegap_small[i++]) @@ -148,8 +153,10 @@ } } -void -mpz_nextprime (mpz_ptr p, mpz_srcptr n) +static int +findnext (mpz_ptr p, + unsigned long(*nextmod_func)(const mpz_t, unsigned long), + void(*nextseq_func)(mpz_t, const mpz_t, unsigned long)) { char *composite; const unsigned char *primegap; @@ -160,19 +167,14 @@ unsigned odds_in_composite_sieve; TMP_DECL; - /* First handle small numbers */ - if (mpz_cmp_ui (n, NP_SMALL_LIMIT) < 0) - { - ASSERT (NP_SMALL_LIMIT < UINT_MAX); - mpz_set_ui (p, mpz_nextprime_small (SIZ (n) > 0 ? mpz_get_ui (n) : 1)); - return; - } - mpz_add_ui (p, n, 1); - mpz_setbit (p, 0); - TMP_MARK; pn = SIZ(p); MPN_SIZEINBASE_2EXP(nbits, PTR(p), pn, 1); + /* Smaller numbers handled earlier */ + ASSERT (nbits >= 3); + /* p is odd */ + ASSERT ((PTR(p)[0] & 1) == 1); + if (nbits / 2 <= NUMBER_OF_PRIMES) { primegap = primegap_small; @@ -229,12 +231,13 @@ { unsigned long difference; unsigned long incr, prime; + int primetest; memset (composite, 0, odds_in_composite_sieve); prime = 3; for (i = 0; i < prime_limit; i++) { - m = mpz_cdiv_ui(p, prime); + m = nextmod_func(p, prime); /* Only care about odd multiplies of prime. */ if (m & 1) m += prime; @@ -252,20 +255,60 @@ if (composite[incr]) continue; - mpz_add_ui (p, p, difference); + nextseq_func(p, p, difference); difference = 0; /* Miller-Rabin test */ - if (mpz_millerrabin (p, 25)) + primetest = mpz_millerrabin (p, 25); + if (primetest) { TMP_FREE; - return; + return primetest; } } /* Sieve next segment, very rare */ - mpz_add_ui (p, p, difference); + nextseq_func(p, p, difference); + } +} + +void +mpz_nextprime (mpz_ptr p, mpz_srcptr n) +{ + /* First handle small numbers */ + 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; } + + /* First odd greater than n */ + mpz_add_ui (p, n, 1); + mpz_setbit (p, 0); + + findnext(p, mpz_cdiv_ui, mpz_add_ui); +} + +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 (mpz_get_ui (n), -2)); + return 2; + } + + /* First odd less than n */ + mpz_sub_ui (p, n, 2); + mpz_setbit (p, 0); + + return findnext(p, mpz_fdiv_ui, mpz_sub_ui); } #undef LOOP_ON_SIEVE_END diff -r c5d0fcb06969 tests/mpz/Makefile.am --- a/tests/mpz/Makefile.am Sat Jul 04 23:15:41 2020 +0200 +++ b/tests/mpz/Makefile.am Fri Aug 28 03:44:14 2020 -0700 @@ -30,7 +30,8 @@ t-fac_ui t-mfac_uiui t-primorial_ui t-fib_ui t-lucnum_ui t-scan t-fits \ t-divis t-divis_2exp t-cong t-cong_2exp t-sizeinbase t-set_str \ t-aorsmul t-cmp_d t-cmp_si t-hamdist t-oddeven t-popcount t-set_f \ - t-io_raw t-import t-export t-pprime_p t-nextprime t-remove t-limbs + t-io_raw t-import t-export t-pprime_p t-nextprime t-remove t-limbs \ + t-nextprime-tune TESTS = $(check_PROGRAMS) diff -r c5d0fcb06969 tests/mpz/t-nextprime.c --- a/tests/mpz/t-nextprime.c Sat Jul 04 23:15:41 2020 +0200 +++ b/tests/mpz/t-nextprime.c Fri Aug 28 03:44:14 2020 -0700 @@ -33,10 +33,20 @@ } void +refmpz_prevprime (mpz_ptr p, mpz_srcptr t) +{ + if (mpz_cmp_ui(t, 2) <= 0) + return; + + mpz_sub_ui (p, t, 1L); + while (! mpz_probab_prime_p (p, 10)) + mpz_sub_ui (p, p, 1L); +} + +void test_largegap (mpz_t low, const int gap) { mpz_t t, nxt; - mpz_init (t); mpz_init (nxt); @@ -45,45 +55,55 @@ if (mpz_cmp_ui(t, gap) != 0) { - gmp_printf ("prime gap %Zd != %d\n", t, gap); + gmp_printf ("nextprime gap %Zd => %Zd != %d\n", low, nxt, gap); abort (); } + mpz_prevprime(t, nxt); + if (mpz_cmp(t, low) != 0) + { + gmp_printf ("prevprime gap %Zd => %Zd != %d\n", nxt, t, gap); + abort (); + } + + mpz_clear (nxt); mpz_clear (t); - mpz_clear (nxt); } void test_largegaps () { - mpz_t x; + mpz_t n; + + mpz_init (n); - mpz_init (x); + // largest gap with start < 2^32. + mpz_set_str (n, "3842610773", 10); + test_largegap (n, 336); - // This takes ~3 seconds on a fast computer. - // Gap 33008 from P454 = 55261931 * 1063#/210 - 13116 - mpz_primorial_ui (x, 1063); - mpz_mul_ui (x, x, 55261931); - mpz_divexact_ui (x, x, 210); - mpz_sub_ui (x, x, 13116); + // largest gap with start < 2^64. + mpz_set_str (n, "18361375334787046697", 10); + test_largegap (n, 1550); - test_largegap(x, 33008); + // test high merit primegap in the P30 digit range. + mpz_set_str (n, "3001549619028223830552751967", 10); + test_largegap (n, 2184); - mpz_clear (x); - + // test high merit primegap in the P100 range. + mpz_primorial_ui (n, 257); + mpz_mul_ui (n, n, 4280516017UL); + mpz_divexact_ui (n, n, 5610); + mpz_sub_ui (n, n, 2560); + test_largegap (n, 9006); - /* - // This takes ~30 seconds, it test the deep science magic constant in - // nextprime.c but takes too long to be always enabled. - // Gap 66520 from P816 = 1931 * 1933# / 7230 - 30244 - mpz_primorial_ui (x, 1933); - mpz_mul_ui (x, x, 1931); - mpz_divexact_ui (x, x, 7230); - mpz_sub_ui (x, x, 30244); + // test high merit primegap in the P200 range. + mpz_primorial_ui (n, 409); + mpz_mul_ui (n, n, 3483347771UL); + mpz_divexact_ui (n, n, 30); + mpz_sub_ui (n, n, 7016); + test_largegap (n, 15900); - test_largegap(x, 66520); - */ - + mpz_clear (n); } void @@ -112,8 +132,8 @@ if (mpz_cmp (x, y) != 0) { - gmp_printf ("got %Zx\n", x); - gmp_printf ("want %Zx\n", y); + gmp_printf ("got %Zd\n", x); + gmp_printf ("want %Zd\n", y); abort (); } @@ -121,6 +141,45 @@ mpz_clear (x); } +void +run_p (const char *start, int reps, const char *end, short diffs[]) +{ + mpz_t x, y; + int i; + + mpz_init_set_str (x, end, 0); + mpz_init (y); + + // Last rep doesn't share same data with nextprime + for (i = 0; i < reps - 1; i++) + { + mpz_prevprime (y, x); + mpz_sub (x, x, y); + if (diffs != NULL && + (! mpz_fits_sshort_p (x) || diffs[reps - i - 1] != (short) mpz_get_ui (x))) + { + gmp_printf ("diff list discrepancy %Zd, %d vs %d\n", + y, diffs[i], mpz_get_ui (x)); + abort (); + } + mpz_swap (x, y); + } + + // starts aren't always prime, so check that result is less than or equal + mpz_prevprime(x, x); + + mpz_set_str(y, start, 0); + if (mpz_cmp (x, y) > 0) + { + gmp_printf ("got %Zd\n", x); + gmp_printf ("want %Zd\n", y); + } + + mpz_clear (y); + mpz_clear (x); +} + + extern short diff1[]; extern short diff3[]; extern short diff4[]; @@ -128,15 +187,18 @@ extern short diff6[]; void -test_ref(gmp_randstate_ptr rands, int reps) { +test_ref (gmp_randstate_ptr rands, int reps, + void (*func)(mpz_t, const mpz_t), + void(*ref_func)(mpz_t, const mpz_t)) +{ int i; - mpz_t bs, x, next_p, ref_next_p; + mpz_t bs, x, test_p, ref_p; unsigned long size_range; mpz_init (bs); mpz_init (x); - mpz_init (next_p); - mpz_init (ref_next_p); + mpz_init (test_p); + mpz_init (ref_p); for (i = 0; i < reps; i++) { @@ -146,35 +208,59 @@ mpz_urandomb (bs, rands, size_range); mpz_rrandomb (x, rands, mpz_get_ui (bs)); -/* gmp_printf ("%ld: %Zd\n", mpz_sizeinbase (x, 2), x); */ - - mpz_nextprime (next_p, x); - refmpz_nextprime (ref_next_p, x); - if (mpz_cmp (next_p, ref_next_p) != 0) + func (test_p, x); + ref_func (ref_p, x); + if (mpz_cmp (test_p, ref_p) != 0) { - gmp_printf ("Ref mismatch %Zd => %Zd vs %Zd\n", x, ref_next_p, next_p); + gmp_printf ("start %Zd\n", x); + gmp_printf ("got %Zd\n", test_p); + gmp_printf ("want %Zd\n", ref_p); abort (); } } mpz_clear (bs); mpz_clear (x); - mpz_clear (next_p); - mpz_clear (ref_next_p); + mpz_clear (test_p); + mpz_clear (ref_p); } -int -main (int argc, char **argv) +void +test_nextprime(gmp_randstate_ptr rands, int reps) { - gmp_randstate_ptr rands; - int reps = 20; + /* Test mpz_nextprime(n <= 1) returns 2. */ + { + long i; + mpz_t n, nxtp; + mpz_init (n); + mpz_init (nxtp); - tests_start(); + for (i = -10; i <= 1; i++) + { + mpz_set_si(n, i); + mpz_nextprime (nxtp, n); + if ( mpz_cmp_ui (nxtp, 2) != 0 ) + { + gmp_printf ("mpz_nxtprime(%Zd) return %Zd\n", n, nxtp); + abort (); + } + } - rands = RANDS; - TESTS_REPS (reps, argv, argc); + for (i = 0; i <= 1000; i++) + { + mpz_ui_pow_ui(n, 2, i); + mpz_neg(n, n); + mpz_nextprime (nxtp, n); + if ( mpz_cmp_ui (nxtp, 2) != 0 ) + { + gmp_printf ("mpz_prevprime(%Zd) return %Zd\n", n, nxtp); + abort (); + } + } - test_ref(rands, reps); + mpz_clear (n); + mpz_clear (nxtp); + } run ("2", 1000, "0x1ef7", diff1); @@ -192,8 +278,114 @@ run ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80", 50, /* 2^128 - 128 */ "0x10000000000000000000000000000155B", diff6); - // Too slow to include in normal testing. - //test_largegaps (); + test_ref( + rands, reps, + (void (*)(mpz_t, const mpz_t)) mpz_nextprime, + refmpz_nextprime); +} + +void +test_prevprime (gmp_randstate_ptr rands, int reps) +{ + long i; + int retval; + mpz_t n, prvp; + + mpz_init (n); + mpz_init (prvp); + + /* Test mpz_prevprime(n <= 2) returns 0, leaves rop unchanged. */ + { + int temp = -5; + mpz_set_si (prvp, temp); + for (i = -10; i <= 2; i++) + { + mpz_set_si(n, i); + retval = mpz_prevprime (prvp, n); + if ( retval != 0 || mpz_cmp_si (prvp, temp) != 0 ) + { + gmp_printf ("mpz_prevprime(%Zd) return (%d) rop (%Zd)\n", n, retval, prvp); + abort (); + } + } + } + + mpz_set_ui(n, 3); + if ( mpz_prevprime (prvp, n) != 2 || mpz_cmp_ui(prvp, 2) != 0 ) + { + gmp_printf ("mpz_prevprime(%Zd) return (%d) rop (%Zd)\n", n, retval, prvp); + abort (); + } + + /* Test mpz_prevprime(10 <= n < 2^20) expect definitely prime (return 2). */ + { + for (i = 10; i < 0x100000L; i += i/10) + { + mpz_set_ui(n, i); + retval = mpz_prevprime (prvp, n); + if ( retval != 2 || mpz_cmp(prvp, n) >= 0 ) + { + gmp_printf ("mpz_prevprime(%Zd) return (%d) rop (%Zd)\n", n, retval, prvp); + abort (); + } + } + } + + /* Test mpz_prevprime(2^70 <= n <= 2^100). */ + { + for (i = 70; i < 100; i++) + { + mpz_ui_pow_ui(n, 2, i); + retval = mpz_prevprime (prvp, n); + if ( retval == 0 || mpz_cmp(prvp, n) >= 0 ) + { + gmp_printf ("mpz_prevprime(%Zd) return (%d) rop (%Zd)\n", n, retval, prvp); + abort (); + } + } + } + + mpz_clear (n); + mpz_clear (prvp); + + run_p ("2", 1000, "0x1ef7", diff1); + + run_p ("3", 1000 - 1, "0x1ef7", NULL); + + run_p ("0x8a43866f5776ccd5b02186e90d28946aeb0ed914", 50, + "0x8a43866f5776ccd5b02186e90d28946aeb0eeec5", diff3); + + run_p ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C", 50, /* 2^148 - 148 */ + "0x100000000000000000000000000000000010ab", diff4); + + run_p ("0x1c2c26be55317530311facb648ea06b359b969715db83292ab8cf898d8b1b", 50, + "0x1c2c26be55317530311facb648ea06b359b969715db83292ab8cf898da957", diff5); + + run_p ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80", 50, /* 2^128 - 128 */ + "0x10000000000000000000000000000155B", diff6); + + // Cast away int return from mpz_prevprime for test ref. + test_ref( + rands, reps, + (void (*)(mpz_t, const mpz_t)) mpz_prevprime, + refmpz_prevprime); +} + +int +main (int argc, char **argv) +{ + gmp_randstate_ptr rands; + int reps = 20; + + tests_start(); + + rands = RANDS; + TESTS_REPS (reps, argv, argc); + + test_nextprime(rands, reps); + test_prevprime(rands, reps); + + test_largegaps (); tests_end (); return 0; diff -r c5d0fcb06969 tune/common.c --- a/tune/common.c Sat Jul 04 23:15:41 2020 +0200 +++ b/tune/common.c Fri Aug 28 03:44:14 2020 -0700 @@ -1776,6 +1776,18 @@ } double +speed_mpz_prevprime (struct speed_params *s) +{ + SPEED_ROUTINE_MPZ_NEXTPRIME (mpz_prevprime); +} + +double +speed_mpz_prevprime_1 (struct speed_params *s) +{ + SPEED_ROUTINE_MPZ_UNARY_1 (mpz_prevprime); +} + +double speed_mpz_jacobi (struct speed_params *s) { SPEED_ROUTINE_MPZ_JACOBI (mpz_jacobi); diff -r c5d0fcb06969 tune/speed.c --- a/tune/speed.c Sat Jul 04 23:15:41 2020 +0200 +++ b/tune/speed.c Fri Aug 28 03:44:14 2020 -0700 @@ -318,6 +318,8 @@ { "mpz_nextprime", speed_mpz_nextprime }, { "mpz_nextprime_1", speed_mpz_nextprime_1, FLAG_R_OPTIONAL }, + { "mpz_prevprime", speed_mpz_prevprime }, + { "mpz_prevprime_1", speed_mpz_prevprime_1, FLAG_R_OPTIONAL }, { "mpz_jacobi", speed_mpz_jacobi }, { "mpn_jacobi_base", speed_mpn_jacobi_base }, diff -r c5d0fcb06969 tune/speed.h --- a/tune/speed.h Sat Jul 04 23:15:41 2020 +0200 +++ b/tune/speed.h Fri Aug 28 03:44:14 2020 -0700 @@ -409,6 +409,8 @@ double speed_mpz_init_realloc_clear (struct speed_params *); double speed_mpz_nextprime (struct speed_params *); double speed_mpz_nextprime_1 (struct speed_params *); +double speed_mpz_prevprime (struct speed_params *); +double speed_mpz_prevprime_1 (struct speed_params *); double speed_mpz_jacobi (struct speed_params *); double speed_mpz_lucnum_ui (struct speed_params *); double speed_mpz_lucnum2_ui (struct speed_params *);
_______________________________________________ gmp-devel mailing list gmp-devel@gmplib.org https://gmplib.org/mailman/listinfo/gmp-devel