Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

J Primes Enumeration

Tags:

j

sieve

J will answer the n-th prime via p:n.

If I ask for the 100 millionth prime I get an almost instant answer. I cannot imagine J is sieving for that prime that quickly, but neither looking it up in a table as that table would be around 1GB in size.

There are equations giving approximations to the number of primes to a bound, but they are only approximations.

How is J finding the answer so quickly ?

like image 300
user1202733 Avatar asked Apr 14 '15 22:04

user1202733


1 Answers

J uses a table to start, then calculates

NOTE! This is speculation, based on benchmarks (shown below).

If you want to quickly try for yourself, try the following:

p:1e8   NB. near-instant
p:1e8-1 NB. noticeable pause

The low points on the graph are where J looks up the prime in a table. After that, J is calculating the value from a particular starting point so it doesn't have to calculate the entire thing. So some lucky primes will be constant time (simple table lookup) but generally there's first a table lookup, and then a calculation. But happily, it calculates starting from the previous table lookup instead of calculating the entire value.

Benchmarks

I did some benchmarking to see how p: performs on my machine (iMac i5, 16G RAM). I'm using J803. The results are interesting. I'm guessing the sawtooth pattern in the time plots (visible on the 'up to 2e5' plot) is lookup table related, while the overall log-ish shape (visible on the 'up to 1e7' plot) is CPU related.

NB. my test script
ts=:3 : 0
  a=.y
  while. a do.
  c=.timespacex 'p:(1e4*a)'  NB. 1000 times a
  a=.<:a
  b=.c;b
  end.
  }:b
)

a =: ts 200

require'plot'
plot >0{each a  NB. time
plot >1{each a  NB. space

(p: up to 2e5)

time

time

space

space

(p: up to 1e7)

time

bigtime

space

bigspace

During these runs one core was hovering around 100%: cpu

Also, the voc page states:

Currently, arguments larger than 2^31 are tested to be prime according to a probabilistic algorithm (Miller-Rabin).

And in addition to a prime lookup table as @Mauris points out, v2.c contains this function:

static F1(jtdetmr){A z;B*zv;I d,h,i,n,wn,*wv;
 RZ(w=vi(w));
 wn=AN(w); wv=AV(w);
 GA(z,B01,wn,AR(w),AS(w)); zv=BAV(z);
 for(i=0;i<wn;++i){
  n=*wv++;
  if(1>=n||!(1&n)||0==n%3||0==n%5){*zv++=0; continue;}
  h=0; d=n-1; while(!(1&d)){++h; d>>=1;}
  if     (n< 9080191)*zv++=spspd(31,n,d,h)&&spspd(73,n,d,h);
  else if(n<94906266)*zv++=spspd(2 ,n,d,h)&&spspd( 7,n,d,h)&&spspd(61,n,d,h);
  else               *zv++=spspx(2 ,n,d,h)&&spspx( 7,n,d,h)&&spspx(61,n,d,h);
 }
 RE(0); R z;
}    /* deterministic Miller-Rabin */ 
like image 51
Alex Shroyer Avatar answered Oct 17 '22 04:10

Alex Shroyer