I've attached an updated diff, thanks for the comments Marco. There doesn't seem to be a way to set s->reps without setting a high precision so I reused SPEED_BLOCK_SIZE from speed_gcd and ran the inner loop that many times
Would folks rather I time 1. s->reps next_primes chained (next_prime(p, p); next_prime(p, p);) 2. s->reps of next_prime on random s->size bit numbers? 1. will be slightly slower (as it will have to search the full gap each time) and more likely for intermediate results to overflow s->size bits (which is seems fine) than 2. Currently it takes about 20 seconds to test -s 16-128, and 15 minutes to test -s 16-1028 with -t 1.04 the resulting graph is much smoother than the old graph. On Sat, Aug 24, 2019 at 8:33 AM Marco Bodrato <bodr...@mail.dm.unipi.it> wrote: > Ciao, > > Il Gio, 22 Agosto 2019 8:48 am, Marco Bodrato ha scritto: > > Il Gio, 22 Agosto 2019 7:24 am, Niels Möller ha scritto: > >> Maybe it would make sense to generalize a bit further, and write a > >> function to find the first prime (if any) in an arithmetic sequence. > >> I.e., find the smallest k >= such that A + kB is prime (if any). A > > ... here too we should decide what to do with negative numbers. > which prime should we return if: > 1) A = -123; B= 42; (I'd suggest A+3*B = +3) > 2) A = -123; B= 30; (I'd suggest A+4*B = -3) > 3) A = -123; B= 26; (I'd suggest A+1*B = -97) > > > I know that my proposal is an incompatible change for the interface... > but > > I'd suggest to extend the range for mpz_nextprime. Can we consider both > > positive and negative primes? > > By the way... our documentation does not mention "positive" primes :-) and > I'm quite sure that there aren't programs using the fact that the current > implementation of nextprime returns 2 for negative numbers... > > Il Gio, 22 Agosto 2019 10:32 am, Niels Möller ha scritto: > > I think that's a bit unusual. We can compare with the corresponding > > functions in pari/gp. These differ from gmp by nextprime(p) == p if p is > > prime. And they don't consider negative numbers to be primes. > > Il Mer, 21 Agosto 2019 10:02 am, Seth Troisi ha scritto: > > Finally for mpz_prevprime(rop, op <= 2) it's not clear what rop should be > > set to, so I use the smallest prime (2). > > Well, in pari/gp there is a function > precprime(x): largest pseudoprime <= x, 0 if x<=1. > > I'm not sure I like that interface... > > My proposal to extend the range of nextprime to negative numbers: > > diff -r 643c931da9bd mpz/nextprime.c > --- a/mpz/nextprime.c Thu Aug 22 15:14:09 2019 +0200 > +++ b/mpz/nextprime.c Sat Aug 24 16:52:21 2019 +0200 > @@ -56,21 +56,24 @@ > mp_size_t pn; > mp_bitcnt_t nbits; > unsigned incr; > + mpz_t tp; > TMP_SDECL; > > /* First handle tiny numbers */ > - if (mpz_cmp_ui (n, 2) < 0) > + if (mpz_cmp_ui (n, 2) < 0 && mpz_cmpabs_ui (n, 4) < 0) > { > mpz_set_ui (p, 2); > + if (mpz_cmpabs_ui (n, 3) == 0) > + mpz_neg (p, p); > return; > } > mpz_add_ui (p, n, 1); > mpz_setbit (p, 0); > > - if (mpz_cmp_ui (p, 7) <= 0) > + if (mpz_cmpabs_ui (p, 7) <= 0) > return; > > - pn = SIZ(p); > + pn = ABSIZ(p); > MPN_SIZEINBASE_2EXP(nbits, PTR(p), pn, 1); > if (nbits / 2 >= NUMBER_OF_PRIMES) > prime_limit = NUMBER_OF_PRIMES - 1; > @@ -88,7 +91,7 @@ > prime = 3; > for (i = 0; i < prime_limit; i++) > { > - moduli[i] = mpz_tdiv_ui (p, prime); > + moduli[i] = mpz_fdiv_ui (p, prime); > prime += primegap[i]; > } > > @@ -115,7 +118,7 @@ > difference = 0; > > /* Miller-Rabin test */ > - if (mpz_millerrabin (p, 25)) > + if (mpz_millerrabin (mpz_roinit_n (tp, PTR (p), ABSIZ (p)), 25)) > goto done; > next:; > incr += 2; > > > After those changes, the _precprime function can be implemented with: > > void > mpz_precprime (mpz_ptr p, mpz_srcptr n) > { > mpz_t tn; > > mpz_nextprime (p, mpz_roinit_n (tn, PTR (n), -SIZ (n))); > mpz_neg (p, p); > } > > > Ĝis, > m > > -- > http://bodrato.it/papers/ > >
diff --git a/tune/common.c b/tune/common.c index 9fefb0d..545abfa 100644 --- a/tune/common.c +++ b/tune/common.c @@ -1722,6 +1722,11 @@ speed_mpn_gcd_1N (struct speed_params *s) SPEED_ROUTINE_MPN_GCD_1N (mpn_gcd_1); } +double +speed_mpz_nextprime (struct speed_params *s) +{ + SPEED_ROUTINE_MPZ_NEXTPRIME (mpz_nextprime); +} double speed_mpz_jacobi (struct speed_params *s) diff --git a/tune/speed.c b/tune/speed.c index 82e9c1a..588b7eb 100644 --- a/tune/speed.c +++ b/tune/speed.c @@ -307,6 +307,9 @@ const struct routine_t { #if 0 { "mpn_gcdext_lehmer", speed_mpn_gcdext_lehmer }, #endif + + { "mpz_nextprime", speed_mpz_nextprime }, + { "mpz_jacobi", speed_mpz_jacobi }, { "mpn_jacobi_base", speed_mpn_jacobi_base }, { "mpn_jacobi_base_1", speed_mpn_jacobi_base_1 }, diff --git a/tune/speed.h b/tune/speed.h index 6ea000b..0272f4e 100644 --- a/tune/speed.h +++ b/tune/speed.h @@ -396,6 +396,7 @@ double speed_mpz_fib_ui (struct speed_params *); double speed_mpz_fib2_ui (struct speed_params *); double speed_mpz_init_clear (struct speed_params *); double speed_mpz_init_realloc_clear (struct speed_params *); +double speed_mpz_nextprime (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 *); @@ -3099,6 +3100,46 @@ int speed_routine_count_zeros_setup (struct speed_params *, mp_ptr, int, int); return t; \ } +/* Calculate nextprime(n) for random n of s->size bits (not limbs). */ +#define SPEED_ROUTINE_MPZ_NEXTPRIME(function) \ + { \ + unsigned i, j; \ + mpz_t wp, n; \ + double t; \ + \ + SPEED_RESTRICT_COND (s->size >= 10); \ + \ + mpz_init (wp); \ + mpz_init_set_n (n, s->xp, s->size); \ + /* limit to s->size bits, as this function is very slow */ \ + mpz_tdiv_r_2exp (n, n, s->size); \ + /* set high bits so operand and result are genaral s->size bits */ \ + mpz_setbit (n, s->size - 1); \ + mpz_clrbit (n, s->size - 2); \ + \ + speed_starttime (); \ + i = s->reps; \ + do \ + { \ + /* nextprime timing is variable, so average over many calls */ \ + j = SPEED_BLOCK_SIZE - 1; \ + /* starts on random, after measures prime to next prime */ \ + function (wp, n); \ + do \ + { \ + function (wp, wp); \ + } \ + while (--j != 0); \ + } \ + while (--i != 0); \ + t = speed_endtime (); \ + \ + mpz_clear (wp); \ + mpz_clear (n); \ + s->time_divisor = SPEED_BLOCK_SIZE; \ + return t; \ + } + #define SPEED_ROUTINE_MPZ_JACOBI(function) \ { \ mpz_t a, b; \
_______________________________________________ gmp-devel mailing list gmp-devel@gmplib.org https://gmplib.org/mailman/listinfo/gmp-devel