view v2.c @ 0:e0bbaa717f41 draft default tip

lol J
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Mon, 25 Nov 2013 11:56:30 -0500
parents
children
line wrap: on
line source

/* Copyright 1990-2011, Jsoftware Inc.  All rights reserved. */
/* License in license.txt.                                   */
/*                                                                         */
/* Verbs: Primes and Factoring                                             */

#include "j.h"


#define MM   25000L     /* interval size to look for primes        */
#define PMAX 105097564L /* upper limit of p: ; (_1+2^31) = p: PMAX */
#define PT   500000L    /* interval size in ptt                    */

static A p4792=0;       /* p: i.4792                               */

static I ptt[]={
    7368791L,   15485867L,   23879539L,   32452867L,   41161751L,
   49979693L,   58886033L,   67867979L,   76918277L,   86028157L,
   95189093L,  104395303L,  113648413L,  122949829L,  132276713L,
  141650963L,  151048973L,  160481219L,  169941223L,  179424691L, /*  10e6 */
  188943817L,  198491329L,  208055047L,  217645199L,  227254213L,
  236887699L,  246534487L,  256203221L,  265892021L,  275604547L,
  285335587L,  295075153L,  304836293L,  314606891L,  324407131L,
  334214467L,  344032391L,  353868019L,  363720403L,  373587911L, /*  20e6 */
  383446691L,  393342743L,  403245719L,  413158523L,  423087253L,
  433024253L,  442967117L,  452930477L,  462900953L,  472882049L,
  482873137L,  492876863L,  502895647L,  512927377L,  522960533L,
  533000401L,  543052501L,  553105253L,  563178743L,  573259433L, /*  30e6 */
  583345003L,  593441861L,  603538541L,  613651369L,  623781269L,
  633910111L,  644047709L,  654188429L,  664338817L,  674506111L,
  684681301L,  694847539L,  705031199L,  715225741L,  725420411L,
  735632797L,  745843009L,  756065179L,  766301759L,  776531419L, /*  40e6 */
  786760649L,  797003437L,  807247109L,  817504253L,  827772511L,
  838041647L,  848321921L,  858599509L,  868891399L,  879190841L,
  889495223L,  899809363L,  910112683L,  920419823L,  930754037L,
  941083987L,  951421147L,  961748941L,  972092467L,  982451707L, /*  50e6 */
  992801861L, 1003162837L, 1013526181L, 1023893887L, 1034271001L,
 1044645419L, 1055040229L, 1065433427L, 1075824283L, 1086218501L,
 1096621151L, 1107029839L, 1117444369L, 1127870683L, 1138305547L,
 1148739817L, 1159168537L, 1169604841L, 1180041943L, 1190494771L, /*  60e6 */
 1200949609L, 1211405387L, 1221863261L, 1232332813L, 1242809783L,
 1253270833L, 1263751141L, 1274224999L, 1284710771L, 1295202523L,
 1305698249L, 1316196209L, 1326697579L, 1337195527L, 1347701867L,
 1358208613L, 1368724913L, 1379256029L, 1389786323L, 1400305369L, /*  70e6 */
 1410844907L, 1421376533L, 1431916091L, 1442469313L, 1453010737L,
 1463555011L, 1474118929L, 1484670179L, 1495213271L, 1505776963L,
 1516351777L, 1526922017L, 1537493917L, 1548074371L, 1558655507L,
 1569250363L, 1579833509L, 1590425983L, 1601020433L, 1611623887L, /*  80e6 */
 1622223991L, 1632828059L, 1643429663L, 1654054511L, 1664674819L,
 1675293223L, 1685912299L, 1696528907L, 1707155683L, 1717783153L,
 1728417367L, 1739062387L, 1749701927L, 1760341447L, 1770989611L,
 1781636627L, 1792287229L, 1802933621L, 1813593029L, 1824261419L, /*  90e6 */
 1834925117L, 1845587717L, 1856264467L, 1866941123L, 1877619461L,
 1888303063L, 1898979371L, 1909662913L, 1920354661L, 1931045239L,
 1941743653L, 1952429177L, 1963130473L, 1973828669L, 1984525423L,
 1995230821L, 2005933283L, 2016634099L, 2027354369L, 2038074751L, /* 100e6 */
 2048795527L, 2059519673L, 2070248617L, 2080975187L, 2091702673L,
 2102429887L, 2113154951L, 2123895979L, 2134651583L, 2145390539L,
};   /* p: PT*1+i.210 */

static I ptn=sizeof(ptt)/SZI;

static I jtsup(J jt,I n,I*wv){I c,d,j,k;
 c=0; DO(n, j=wv[i]; ASSERT(0<=j,EVDOMAIN); if(c<j)c=j;); 
 ASSERT(c<=PMAX,EVLIMIT);
 j=1; k=0; DO(128, if(c<=j)break; j+=j; ++k;); d=c*k; 
 R k&&c>d?IMAX:MAX(d,135L);
}    /* (_1+2^31) <. 135 >. (*>.@(2&^.)) >./ w */

static void sieve(I n,I m,B*b,B*u){I i,j,q;
 static B t[]={
  0,1,0,0,0, 0,0,1,0,0, 0,1,0,1,0, 0,0,1,0,1, 0,0,0,1,0, 0,0,0,0,1,
  0,1,0,0,0, 0,0,1,0,0, 0,1,0,1,0, 0,0,1,0,1, 0,0,0,1,0, 0,0,0,0,1};
 mvc(m,b,30L,t+n%30); if(!n)b[1]=0; q=1+(I)sqrt(n+(D)m);
 if(n)for(i=7;i<q;i+=2){if(u[i]){j=n%i; j=j?i-j:0; while(j<m){b[j]=0; j+=i;}}}
 else for(i=7;i<q;i+=2){if(b[i]){j=i+i;            while(j<m){b[j]=0; j+=i;}}}
}    /* sieve b for n+i.m, but if 0=n then b=. 0 (2 3 5)}b */

static F1(jtprime1){A d,t,y,z;B*b,*u;I c,*dv,e,i,j,k,m,n,p,q,*wv,x,*zv;
 RZ(w);
 k=0; n=AN(w); wv=AV(w); RE(m=sup(n,wv)); jt->rank=0; JBREAK0;
 GA(z,INT,n,AR(w),AS(w)); zv= AV(z);
 RZ(d=grade1(ravel(w)));  dv= AV(d);
 if(p4792){I*u=AV(p4792); c=AN(p4792); while(n>k&&c>(x=wv[dv[k]]))zv[dv[k++]]=u[x];}
 else{
  while(n>k&&0==wv[dv[k]])zv[dv[k++]]=2;
  while(n>k&&1==wv[dv[k]])zv[dv[k++]]=3;
  while(n>k&&2==wv[dv[k]])zv[dv[k++]]=5;
 }
 if(n==k)R z; 
 j=3; p=0; e=PT; q=1+(I)sqrt((D)m); x=wv[dv[k]]; 
 GA(t,B01,q,1,0);         u=BAV(t); sieve(0L,q,u,u); 
 GA(y,B01,MIN(m,MM),1,0); b=BAV(y); 
 for(;0<=p&&p<m;p+=q){
  if(x>=e){c=x/PT; e=PT*(1+c); c=MIN(c,ptn); if(j<c*PT){j=c*PT; p=ptt[c-1];}}
  JBREAK0; q=MIN(MM,m-p); sieve(p,q,b,u); c=j+q/3;
  if(x>c)for(i=1-p%2;i<q;i+=2)j+=b[i];
  else   for(i=1-p%2;i<q;i+=2)
   if(b[i]){while(j==x){zv[dv[k++]]=i+p; if(n==k)R z; x=wv[dv[k]];} ++j;}
 }
 while(n>k)zv[dv[k++]]=p; R z;
}

static I rem(D x,I d){R (I)floor(x-d*floor(x/(D)d));}

static void sieved(D n,I m,B*b){I c,d,e,i,q,r,*u,*v;
 static B t[]={
  0,1,0,0,0, 0,0,1,0,0, 0,1,0,1,0, 0,0,1,0,1, 0,0,0,1,0, 0,0,0,0,1,
  0,1,0,0,0, 0,0,1,0,0, 0,1,0,1,0, 0,0,1,0,1, 0,0,0,1,0, 0,0,0,0,1};
 static I dt[]={1,7,11,13,17,19,23,29};
 c=2*3*5; v=dt+sizeof(dt)/SZI; q=1+(I)sqrt(n+(D)m);
 mvc(m,b,30L,t+rem(n,30L));
 for(i=c;i<q;i+=c){
  u=dt;
  while(u<v){
   d=i+*u++; r=rem(n,d); e=r?d-r:0;
   while(d<m){b[e]=0; e+=d;}
 }}
}    /* sieve b for n+i.m; n>0; u is mask for primes */

static F1(jtprime1d){A d,z;D*wv,x,*zv;I*dv,k,n;
 RZ(w);
 n=AN(w); wv=DAV(w);
 GA(z,FL,n,AR(w),AS(w)); zv=DAV(z);
 RZ(d=grade1(ravel(w))); dv=AV(d);
 k=0; while(n>k&&(D)PMAX>=wv[dv[k]])++k;
 if(k){A y;I*yv;
  RZ(y=prime1(cvt(INT,from(take(sc(k),d),ravel(w))))); yv=AV(y);
  DO(k, zv[dv[i]]=(D)*yv++;);
 }
 if(k==n)R z;
 DO(n-k, x=wv[dv[i]]; ASSERT(0<=x&&x!=inf,EVDOMAIN););
 ASSERT(0,EVLIMIT);
}

F1(jtprime){PROLOG;A z;B b=1;I n,p,q,t;
 RZ(w);
 if(!p4792){RZ(p4792=prime1(IX(4792L))); ACX(p4792);}
 n=AN(w); t=AT(w);
 if(!(t&INT))RZ(w=pcvt(INT,w));
 if(INT&AT(w)){
  irange(n,AV(w),&p,&q);
  if(0<q&&PMAX>=p+q-1){b=0; RZ(z=prime1(w));}
 }
 if(b)RZ(z=prime1d(FL&AT(w)?w:cvt(FL,w)));
 if(t&XNUM+RAT)RZ(z=cvt(XNUM,z));
 EPILOG(z);
}    /* p:"r w */

static I jtsuq(J jt,I n,I*wv){I c=24; DO(n, c=MAX(c,wv[i]););  R c==0x7fffffff?c:1+c;}
     /* 1+24>.>./w */

F1(jtplt){PROLOG;A d,t,y,z;B*b,*u,xt;I c,*dv,e,i,j,k,m,n,p,q,*wv,x,*zv;
 RZ(w);
 xt=1&&AT(w)&XNUM+RAT;
 if(!(INT&AT(w)))RZ(w=vi(ceil1(w))); wv=AV(w); JBREAK0;
 j=3; k=p=c=0; e=*ptt; n=AN(w); 
 RE(m=suq(n,wv)); ASSERT(m<=0x7fffffff,EVLIMIT); q=1+(I)sqrt((D)m); 
 GA(t,B01,q,1,0);         u =BAV(t); sieve(0L,q,u,u);
 GA(y,B01,MIN(m,MM),1,0); b =BAV(y); 
 GA(z,INT,n,AR(w),AS(w)); zv= AV(z);
 RZ(d=grade1(ravel(w)));  dv= AV(d);
 while(n>k&&2>=wv[dv[k]])zv[dv[k++]]=0; 
 while(n>k&&3>=wv[dv[k]])zv[dv[k++]]=1; 
 while(n>k&&5>=wv[dv[k]])zv[dv[k++]]=2; 
 if(n==k)EPILOG(z); x=wv[dv[k]]; 
 for(;0<=p&&p<m;p+=q){
  if(x>=e){
   while(ptn>c&&x>=ptt[c])++c; 
   if(j<c*PT){p=ptt[c-1]; e=c<ptn?ptt[c]:IMAX; j=c*PT;}
  }
  JBREAK0; q=MIN(MM,m-p); sieve(p,q,b,u);
  if(x>p+q)
   for(i=1-p%2;i<q;i+=2)j+=b[i];
  else     
   for(i=1-p%2;i<q;i+=2)if(b[i]){
    while(x<=p+i){zv[dv[k++]]=j; if(n==k){i=q; break;} x=wv[dv[k]];}
    ++j;
 }}
 while(n>k)zv[dv[k++]]=j; 
 if(xt)RZ(z=cvt(XNUM,z));
 EPILOG(z);
}    /* p:^:_1 w, the number of primes less than w */


static B jtxprimeq(J,I,X);
static F1(jtxprimetest);

static B pmsk[]={0,0,1,1,0,1,0,1,0,0, 0,1,0,1,0,0,0,1,0,1, 0,0,0,1,0,0,0,0,0,1, 0,1};
     /* indicates which i<32 is prime */

static F1(jtiprimetest){A z;B*b;I d,j,n,*pv,q,*v,wn,*wv;
 RZ(w);
 wn=AN(w); wv=AV(w); pv=AV(p4792);
#if SY_64
 DO(wn, if(2147483647L<wv[i])R xprimetest(cvt(XNUM,w)););
#endif
 GA(z,B01,wn,AR(w),AS(w)); b=BAV(z);
 for(j=0;j<wn;++j){
  n=*wv++; v=pv;
  if(32>n)b[j]=pmsk[MAX(0,n)];
  else{b[j]=1; DO(AN(p4792), d=*v++; q=n/d; if(n==q*d){b[j]=0; break;}else if(q<d)break;);}
 }
 R z;
}

static F1(jtxprimetest){A z;B*b,rat;I d,j,q,n,old,*pv,*v,wn,wt,*yv;X r,*wv,x,xmaxint,y;
 RZ(w);
 wn=AN(w); wt=AT(w); wv=XAV(w); pv=AV(p4792); 
 rat=1&&wt&RAT; RZ(xmaxint=xc(2147483647L)); RZ(y=xc(-1L)); yv=AV(y);
 GA(z,B01,wn,AR(w),AS(w)); b=BAV(z);
 for(j=0;j<wn;++j){
  x=*wv++; d=*(AV(x)+AN(x)-1); b[j]=1; v=pv;
  if(rat&&xcompare(xone,*wv++)){b[j]=0; continue;}
  ASSERT(d!=XPINF&&d!=XNINF,EVDOMAIN);
  if(0>=d)b[j]=0;
  else if(1==xcompare(x,xmaxint)){
   old=jt->tbase+jt->ttop;
   DO(100, *yv=*v++; RZ(r=xrem(y,x)); if(!*AV(r)){b[j]=0; break;});
   if(b[j])RE(b[j]=xprimeq(100L,x));
   tpop(old);
  }else{
   n=xint(x); v=pv;
   if(32>n)b[j]=pmsk[MAX(0,n)];
   else DO(AN(p4792), d=*v++; q=n/d; if(n==q*d){b[j]=0; break;}else if(q<d)break;);
 }}
 R z;
}    /* prime test for extended integers or rationals */

static F1(jtprimetest){A x;D oct;I t;
 RZ(w);
 t=AT(w);
 if(!AN(w)||t&B01)R reshape(shape(w),zero);
 switch(t){
  default:             ASSERT(0,EVDOMAIN);
  case INT:            R iprimetest(w);
  case RAT: case XNUM: R xprimetest(w);
  case FL:  case CMPX:
   oct=jt->ct; jt->ct=jt->fuzz; x=eq(t&FL?w:conjug(w),floor1(w)); jt->ct=oct;
   R xprimetest(cvt(XNUM,tymes(w,x))); 
}}   /* primality test */


static F1(jtnextprime){A b,fs,x,y;B*bv;I k,n,*xv,*yv;X*wv;
 RZ(w);
 n=AN(w);
 if(!n||B01&AT(w))R reshape(shape(w),num[2]);
 ASSERT(NUMERIC&AT(w),EVDOMAIN);
 RZ(fs=eval("2&+^:(0&p:)^:_"));
 GA(x,INT,n,AR(w),AS(w)); xv=AV(x);
 if(INT&AT(w)){B b=1;I*wv=AV(w);
  DO(n, k=*wv++; if(k==IMAX){b=0; break;}else *xv++=2>k?2:k+1+(k%2););
  if(b)R rank1ex(x,fs,0L,VAV(fs)->f1);
  RZ(w=cvt(XNUM,w));
 }
 if(AT(w)&FL+RAT)RZ(w=cvt(XNUM,floor1(       w )));
 if(AT(w)&CMPX  )RZ(w=cvt(XNUM,floor1(cvt(FL,w))));
 GA(b,B01,n,AR(w),AS(w)); bv=BAV(b); wv=XAV(w);
 DO(n, y=*wv++; yv=AV(y); *bv++=0<yv[AN(y)-1]; *xv++=*yv%2?2:1;);
 R rank1ex(tymes(b,plus(w,x)),fs,0L,VAV(fs)->f1);
}

static F1(jtprevprime){A fs,x,y;I k,m,n,*xv,*yv;X*wv;
 RZ(w);
 n=AN(w);
 ASSERT(!n||NUMERIC&AT(w)&&!(B01&AT(w)),EVDOMAIN);
 RZ(fs=eval("_2&+^:(0&p:)^:_"));
 GA(x,INT,n,AR(w),AS(w)); xv=AV(x);
 if(INT&AT(w)){I*wv=AV(w);
  DO(n, k=*wv++; ASSERT(2<k,EVDOMAIN); *xv++=3==k?2:k-(1+k%2););
  R rank1ex(x,fs,0L,VAV(fs)->f1);
 }
 if(AT(w)&FL+RAT)RZ(w=cvt(XNUM,ceil1(       w )));
 if(AT(w)&CMPX  )RZ(w=cvt(XNUM,ceil1(cvt(FL,w))));
 wv=XAV(w);
 DO(n, y=*wv++; yv=AV(y); m=AN(y); k=*yv; ASSERT(0<yv[m-1]&&(1<m||2<k),EVDOMAIN); *xv++=1==m&&3==k?1:1+k%2;);
 R rank1ex(minus(w,x),fs,0L,VAV(fs)->f1);
}

static F1(jttotient){A b,x,z;B*bv,p=0;I k,n,t;
 RZ(w);
 n=AN(w); t=AT(w);
 if(t&B01)R ca(w);
 GA(b,B01,n,AR(w),AS(w)); bv=BAV(b);
 if(t&INT){I*wv=AV(w),*xv;
  GA(x,INT,n,AR(w),AS(w)); xv=AV(x);
  DO(n, k=*wv++; ASSERT(0<=k,EVDOMAIN); if(k){*bv++=1; *xv++=k;}else{*bv++=0; *xv++=1; p=1;};);
 }else{X*xv,y;
  RZ(x=cvt(XNUM,w)); xv=XAV(x);
  DO(n, y=xv[i]; k=*(AV(y)+AN(y)-1); ASSERT(0<=k,EVDOMAIN); if(k)*bv++=1; else{*bv++=0; xv[i]=xone; p=1;});
 }
 z=cvt(AT(x),df1(x,eval("(- ~:)&.q:"))); 
 R p?tymes(b,z):z;
}

/*
MillerRabin=: 100&$: : (4 : 0) " 0
 if. 0=2|y do. 2=y return. end.
 if. 74>y do. y e. i.&.(p:^:_1) 74 return. end.
 e=. huo y-1
 for_a. x witnesses y do. if. (+./c=y-1) +: 1={:c=. a y&|@^ e do. 0 return. end. end.
 1
)
*/

static B jtspspd(J jt,I b,I n,I d,I h){D a,n1,nn,x;
 if(b==n)R 1;
 a=1; x=(D)b; nn=(D)n; n1=(D)n-1;
 while(d){if(1&d)a=fmod(a*x,nn); x=fmod(x*x,nn); d>>=1;}
 if(a==1||a==n1)R 1;
 DO(h-1, a=fmod(a*a,nn); if(a==n1)R 1;);
 R 0;
}

static B jtspspx(J jt,I b,I n,I d,I h){I ai,n1;X a,ox,xn;
 if(b==n)R 1;
 n1=n-1;
 ox=jt->xmod; jt->xmod=cvt(XNUM,sc(n)); a=xpow(xc(b),xc(d)); jt->xmod=ox;
 ai=xint(a);
 if(ai==1||ai==n1)R 1;
 xn=xc(n);
 DO(h-1, a=xrem(xn,xtymes(a,a)); if(xint(a)==n1)R 1;);
 R 0;
}

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 */ 

F2(jtpco2){A z;B*b;I k;
 RZ(a&&w);
 if(!p4792){RZ(p4792=prime1(IX(4792L))); ACX(p4792);}
 RE(k=i0(a));
 switch(k){
  default: ASSERT(0,EVDOMAIN);
  case -4: R prevprime(w);
  case -1: R plt(w);
  case  0: RZ(z=primetest(w)); b=BAV(z); DO(AN(z), *b=!*b; ++b;); R z;
  case  1: R primetest(w);
  case  2: R qco2(scf(infm),w);
  case  3: R factor(w);
  case  4: R nextprime(w);
  case  5: R totient(w);
  case  6: R detmr(w);
}}   /* a p: w */

static A jtqco2x(J jt,I m,A w){A y;I c,*dv,i,*pv,*yv;X d,q,r,x;
 if(!p4792){RZ(p4792=prime1(IX(4792L))); ACX(p4792);}
 if(!(XNUM&AT(w)))RZ(w=cvt(XNUM,w));
 x=*XAV(w); pv=AV(p4792); RZ(d=xc(2L)); dv=AV(d);
 GA(y,INT,m,1,0); yv=AV(y); memset(yv,C0,m*SZI);
 for(i=0;i<m;++i){
  c=0; *dv=pv[i];
  while(1){RZ(xdivrem(x,d,&q,&r)); if(*AV(r))break; ++c; x=q;}
  yv[i]=c; if(1==AN(x)&&1==*AV(x))break;
 }
 R cvt(XNUM,y);
}    /* m q: w where 0<:m and p: m is one xdigit and w is a single extended integer */

F2(jtqco2){A q,y,z;B b,bb,xt;I c,j,k,m,*qv,wn,wr,*yv,*zv;
 RZ(a&&w);
 wn=AN(w); wr=AR(w); b=all1(lt(a,zero)); xt=1&&AT(w)&XNUM+RAT;
 if(AR(a)||wr&&(b||xt))R rank2ex(a,w,0L,0L,0L,jtqco2);
 if(!b&&xt){RE(m=i0(vib(a))); if(0<=m&&m<1229)R qco2x(m,w);}  /* 1229=p:^:_1 XBASE */
 RZ(q=factor(w)); qv=AV(q);
 if(b)RZ(a=negate(a));
 bb=equ(a,ainf);
 if(b&bb){ /* __ q: w */
  RZ(y=ne(q,curtail(over(zero,q))));
  R lamin2(repeat(y,q),df1(y,cut(ds(CPOUND),one)));
 }
 RZ(y=vi(plt(q))); yv=AV(y);
 k=-1; DO(AN(y), if(k<yv[i])k=yv[i];); ++k;
 if(bb)m=k; else RE(m=i0(a));
 if(b){
  q=repeat(ge(y,sc(k-m)),q);
  R lamin2(nub(q),df2(q,q,sldot(ds(CPOUND))));
 }else{
  GA(z,INT,wn*m,1+wr,AS(w)); *(AS(z)+wr)=m; zv=AV(z);
  memset(zv,C0,AN(z)*SZI);
  j=0; c=*(AS(q)+wr); DO(wn, DO(c, if(qv[j]&&m>yv[j])++zv[yv[j]]; ++j;); zv+=m;);
  R AT(w)&XNUM+RAT?cvt(XNUM,z):z;
}}   /* a q: w for array w */

static F1(jtxfactor);

F1(jtfactor){PROLOG;A y,z;I c,d,i,k,m,n,q,*u,*v,wn,*wv,*zv;
 RZ(w);
 if(!p4792){RZ(p4792=prime1(IX(4792L))); ACX(p4792);}
 if(AT(w)&XNUM+RAT)R xfactor(w);
 if(AT(w)&FL+CMPX){
  RZ(y=pcvt(INT,w)); 
  if(INT&AT(y))w=y; 
  else{RZ(y=pcvt(XNUM,xco1(w))); ASSERT(XNUM&AT(y),EVDOMAIN); R pcvt(INT,xfactor(y));}
 }
 RZ(w=vi(w));
 wn=AN(w); wv=AV(w);
 n=0; DO(wn, k=wv[i]; ASSERT(0<k,EVDOMAIN); n=MAX(n,k););
#if SY_64
 if(n>2147483647)R cvt(INT,xfactor(w));
#endif
 u=AV(p4792); c=8*SZI-2;
 GA(z,INT,c*wn,1+AR(w),AS(w)); *(AS(z)+AR(w))=c; v=zv=AV(z);
 for(i=m=0;i<wn;++i){
  n=*wv++;
  DO(AN(p4792), d=u[i]; q=n/d; while(n==q*d){*v++=d; n=q; q/=d;} if(q<d)break;);
  if(1<n)*v++=n;
  d=v-zv; m=MAX(m,d); zv+=c; while(v<zv)*v++=0; 
 }
 EPILOG(c==m?z:taker(m,z));
}    /* q:"r w */


/*
 http://ww2.lafayette.edu/~reiterc/j/vector/factor_ecj.html
 Elliptic curve arithmetic and factorization.
 factor_ecj.ijs
 Cliff Reiter
 June 2003

 Elliptic curves are E=.a,b where (y^2)=(x^3)+(a*x)+b
 Moduli are n where n-:0 corresponds to rational arithmetic
*/

static B jtsmallprimes(J jt,I n,X x,A*zs,X*zx){A s;I i,m,old,*pv,*sv,*v;X d,q,r;
 ASSERT(n<=1229&&n<=AN(p4792),EVLIMIT);
 pv=AV(p4792); m=(I)(3.322*XBASEN*AN(x)); 
 GA(s,INT,m,1,0); v=sv=AV(s);
 old=jt->tbase+jt->ttop;
 for(i=0;i<n;++i){
  RZ(d=xc(pv[i])); 
  RZ(xdivrem(x,d,&q,&r));   /* d must have only one "digit" */
  while(!xcompare(r,xzero)){*v++=pv[i]; x=q; RZ(xdivrem(q,d,&q,&r));} 
  if(-1==xcompare(q,d))break;
  gc(x,old);
 }
 if(1>xcompare(x,xc(99460729L))&&!(1==AN(x)&&1==XDIG(x))){*v++=xint(x); x=xone;}
 AN(s)=*AS(s)=v-sv;
 RZ(*zs=cvt(XNUM,s)); *zx=x;
 R 1;
}    /* remove small prime factors */

/* if 0=n xprimeq y, then y is certainly composite; and                    */
/* if 1=n xprimeq y, then y is prime with a probability of error of 0.25^n */

static B jtxprimeq(J jt,I n,X y){A h,om=jt->xmod;B b;I*dv,i,k,old,*pv;X d,m,t,x,y1;
 ASSERT(n<=AN(p4792),EVLIMIT);
 pv=AV(p4792);
 GA(h,XNUM,1,0,0); *XAV(h)=y; jt->xmod=h; 
 k=0; RZ(t=xc(2L)); RZ(m=y1=xminus(y,xone)); 
 while(0==*AV(m)%2){++k; RZ(m=xdiv(m,t,XMFLR));}
 GA(d,INT,1,1,0); dv=AV(d);
 old=jt->tbase+jt->ttop;
 for(i=0;i<n;++i){
  *dv=pv[i]; RZ(x=xpow(d,m)); b=1==AN(x)&&1==*AV(x);
  DO(k*!b, if(!xcompare(x,y1)){b=1; break;} RZ(x=xrem(y,xsq(x))););
  tpop(old);
  if(!b)break;
 }
 jt->xmod=om; R b;
}    /* y assumed to be not in n{.p4792 */

static XF1(jtpollard_p_1){A om=jt->xmod;D p,m;I e,i,n,old,*pv;X c,g,z=xone;
 n=MIN(1229,AN(p4792)); pv=AV(p4792); m=log((D)pv[n-1]);
 RZ(c=xc(2L));
 RZ(jt->xmod=scx(w));
 old=jt->tbase+jt->ttop;
 for(i=0;i<n;++i){
  p=(D)pv[i]; e=(I)pow(p,jfloor(m/log(p)));
  RZ(c=xpow(c,sc(e)));
  RZ(g=xgcd(w,xminus(c,xone)));
  if(!equ(g,xone)&&!equ(g,w)){z=g; break;}
  gc(c,old);
 }
 jt->xmod=om; 
 R z;
}

static XF1(jtpollard_rho){I i,n,old=jt->tbase+jt->ttop;X g,y1,y2;
 n=10000;
 RZ(y1=y2=xc(2L));
 for(i=0;i<n;++i){
  RZ(y1=xrem(w,xplus(xone,xsq(y1))));
  RZ(y2=xrem(w,xplus(xone,xsq(xplus(xone,xsq(y2))))));
  RZ(g=xgcd(w,xrem(w,xminus(y2,y1))));
  if(!equ(g,xone)&&!equ(g,w))R g;
  gc3(y1,y2,0L,old);
 }
 R xone;
}

static B jtranec(J jt,X w,X*zg,X*za,X*zb,X*zx,X*zy){A mm,t;I*tv;X a,aa,b,bb,g,x,y;
 g=w; RZ(mm=reshape(sc(3L),sc(IMAX)));
 while(!xcompare(g,w)){
  RZ(t=roll(mm)); tv=AV(t); 
  RZ(x=xc(tv[0])); 
  RZ(y=xc(tv[1])); 
  RZ(a=xc(tv[2]));
  RZ(b=xrem(w,xminus(xsq(y),xtymes(x,xplus(a,xsq(x))))));
  RZ(aa=xtymes(xc( 4L),xtymes(a,xsq(a))));
  RZ(bb=xtymes(xc(27L),         xsq(b) ));
  RZ(g=xgcd(w,xplus(aa,bb)));
 }
 *zg=g; *za=a; *zb=b; *zx=x; *zy=y;
 R 1;
}    /* random elliptic curve */

static A jtdb1b2(J jt,I n,X w){A t,z;D c,d,lg,n1=(D)n-1,p,r;I m,s[2],*v,*zv;
 s[0]=n; s[1]=2; GA(z,INT,2*n,2,s); zv=v=AV(z);
 RZ(t=cvt(FL,scx(w))); d=*DAV(t); 
 lg=log(d); c=log(sqrt(d)); r=exp(sqrt(0.5)+sqrt(c*log(c)))/lg;
 DO(n, c=lg*pow(r,i/n1); p=c*log(c); if(p>=2147483647)break; *v++=(I)jfloor(c); *v++=(I)p;);
 m=(v-zv)/2; ASSERT(m,EVLIMIT);
 *AS(z)=m; AN(z)=2*m;
 R z;
}

static B jtecd(J jt,X n,X a,X b,X*q,X*z){I old=jt->tbase+jt->ttop;X m,s,x2,y2,yy,z2;
 if(0==xcompare(q[1],xzero)||0==xcompare(q[2],xzero)){z[0]=xzero; z[1]=xone; z[2]=xzero;}
 else{
  RZ(m=xplus(xtymes(xc(3L),xsq(q[0])),xtymes(a,xsq(xsq(q[2])))));
  RZ(yy=xsq(q[1]));
  RZ(s=xtymes(xc(4L),xtymes(q[0],yy)));
  RZ(x2=xplus(xsq(m),xtymes(xc(-2L),s)));
  RZ(y2=xplus(xtymes(m,xminus(s,x2)),xtymes(xc(-8L),xsq(yy))));
  RZ(z2=xtymes(xc(2L),xtymes(q[1],q[2])));
  RZ(z[0]=xrem(n,x2)); RZ(z[1]=xrem(n,y2)); RZ(z[2]=xrem(n,z2));
 }
 gc3(z[0],z[1],z[2],old);
 R 1;
}    /* elliptic curve double point (mod proj coord) */

static B jteca(J jt,X n,X a,X b,X*p,X*q,X*z){I old=jt->tbase+jt->ttop;
 if     (0==xcompare(p[2],xzero)){z[0]=q[0]; z[1]=q[1]; z[2]=q[2];}
 else if(0==xcompare(q[2],xzero)){z[0]=p[0]; z[1]=p[1]; z[2]=p[2];}
 else{X m,r,s1,s2,t,t1,t2,u1,u2,w,w2,x3,y3,z12,z22,z3;
  RZ(u1=xtymes(q[0],z12=xsq(p[2]))); RZ(s1=xtymes(q[1],xtymes(p[2],z12)));
  RZ(u2=xtymes(p[0],z22=xsq(q[2]))); RZ(s2=xtymes(p[1],xtymes(q[2],z22)));
  RZ(w=xminus(u1,u2));
  if(0==xcompare(w,xzero))RZ(ecd(n,a,b,p,z))
  else{
   RZ(r=xminus(s1,s2));
   RZ(t=xplus(u1,u2));
   RZ(m=xplus(s1,s2));
   RZ(w2=xsq(w));
   RZ(x3=xminus(xsq(r),xtymes(t,w2)));
   RZ(t1=xtymes(r,xplus(xtymes(xc(-2L),x3),xtymes(t,w2))));
   RZ(t2=xtymes(m,xtymes(w,w2)));
   RZ(y3=xdiv(xminus(t1,t2),xc(2L),XMFLR));
   RZ(z3=xtymes(p[2],xtymes(q[2],w)));
   RZ(z[0]=xrem(n,x3)); RZ(z[1]=xrem(n,y3)); RZ(z[2]=xrem(n,z3));
 }}
 gc3(z[0],z[1],z[2],old);
 R 1;
}    /* elliptic curve add (mod proj coord) */

#if SY_64
#define BIT0 0x8000000000000000
#else
#define BIT0 0x80000000
#endif

static B jtecm(J jt,X n,X a,X b,I m,X*p,X*z){I old=jt->tbase+jt->ttop;
 if(0==m){z[0]=xzero; z[1]=xone; z[2]=xzero;}
 else{I k;UI c,d;X pm[3],q[3];
  q[0]=p[0]; q[1]=p[1]; q[2]=p[2]; 
  pm[0]=p[0]; RZ(pm[1]=xminus(xzero,p[1])); pm[2]=p[2]; 
  c=(3*m)>>1; d=m>>1; k=8*sizeof(I);
  while(!(c&BIT0)){c<<=1; d<<=1; --k;}
  c<<=1; d<<=1; --k;
  DO(k, RZ(ecd(n,a,b,q,q)); if(BIT0&(c^d))RZ(eca(n,a,b,q,c&BIT0?p:pm,q)); c<<=1; d<<=1;);
  z[0]=q[0]; z[1]=q[1]; z[2]=q[2];
 }
 gc3(z[0],z[1],z[2],old);
 R 1;
}    /* scalar mult ladder (mod proj coord) */

static B jtecm_s1(J jt,X n,X a,X b,I b1,X*q,X*z){A tt;D d,lg;I dd,m,old=jt->tbase+jt->ttop,*pv;X x[3];
 lg=log((D)b1); RE(m=i0(plt(sc(b1))));
 if(m<=AN(p4792))pv=AV(p4792); else{RZ(tt=prime1(IX(m))); pv=AV(tt);}
 x[0]=q[0]; x[1]=q[1]; x[2]=q[2];
 DO(m, d=(D)*pv++; dd=(I)pow(d,jfloor(5e-14+lg/log(d))); RZ(ecm(n,a,b,dd,x,x)););
 z[0]=x[0]; z[1]=x[1]; z[2]=x[2];
 gc3(z[0],z[1],z[2],old);
 R 1;
}

static B jtecm_s2(J jt,X n,X a,X b,I b1,I b2,X*q,X*z){A sda,tt;I d,di,i,k,m,old,p0,*pd,*v;X*s1,*sd,*sd0,*sdd,*t,x[3];
 RZ(tt=plt(v2(b1,b2))); v=AV(tt); m=(v[1]-v[0])-1;
 RZ(tt=prime1(apv(1+m,v[0],1L))); pd=v=AV(tt); p0=*v;
 d=0; DO(m, v[0]=k=-1+(v[1]-v[0])/2; ++v; d=MAX(d,k);); d=MIN(100,1+d);
 GA(sda,XNUM,3*d,2,0); sd0=sd=XAV(sda); v=AS(sda); v[0]=d; v[1]=3;
 RZ(ecd(n,a,b,q,sd)); s1=t=sd; sd+=3;
 DO(d-1, eca(n,a,b,s1,t,sd); t=sd; sd+=3;); sd=sd0; sdd=t;
 RZ(ecm(n,a,b,p0,q,x));
 old=jt->tbase+jt->ttop;
 for(i=0;i<m;++i){
  di=pd[i];
  DO(di/d, RZ(eca(n,a,b,x,sdd,x)););
  RZ(eca(n,a,b,x,sd+3*(di%d),x));
  gc3(x[0],x[1],x[2],old);
 }
 z[0]=x[0]; z[1]=x[1]; z[2]=x[2];
 R 1;
}

static XF1(jtfac_ecm){A tt;I b1,b2,*b1b2,i,old,m;X a,b,g,q[3];
 RZ(tt=db1b2(20L,w)); m=IC(tt); b1b2=AV(tt);
 old=jt->tbase+jt->ttop;
 for(i=0;i<m;++i){
  b1=b1b2[0]; b2=b1b2[1]; b1b2+=2;
  ranec(w,&g,&a,&b,q,q+1); q[2]=xone;
  if(xcompare(g,xone)&&xcompare(g,w))R g;
  RZ(ecm_s1(w,a,b,b1,q,q));
  RZ(g=xgcd(w,q[2]));
  if(xcompare(g,xone)&&xcompare(g,w))R g;
  if(0==xcompare(g,xone)){
   RZ(ecm_s2(w,a,b,b1,b2,q,q));
   RZ(g=xgcd(w,q[2]));
   if(xcompare(g,xone)&&xcompare(g,w))R g;
  }
  tpop(old);
 }
 R xone;
}

static F1(jtxfactor){PROLOG;A z;B b=0;I m;X g,x;
 F1RANK(0,jtxfactor,0);
 if(!(XNUM&AT(w)))RZ(w=cvt(XNUM,w));
 x=*XAV(w); m=XDIG(x);
 ASSERT(m!=XPINF&&m!=XNINF&&0<m,EVDOMAIN);
 if(1>xcompare(x,xc(2147483647L)))R xco1(factor(sc(xint(x))));
 RZ(smallprimes(1229L,x,&z,&x));
 while(1==xcompare(x,xc(2147483647L))){
  if(xprimeq(100L,x)){RZ(z=over(z,scx(x))); x=xone; break;}
  RZ(g=pollard_p_1(x)); if(g!=xone){RZ(z=over(z,scx(g))); RZ(x=xdiv(x,g,XMFLR)); continue;}
  RZ(g=pollard_rho(x)); if(g!=xone){RZ(z=over(z,scx(g))); RZ(x=xdiv(x,g,XMFLR)); continue;}
  if(!b){b=1; RZ(rngseeds(sc(jt->rngS[jt->rng]))); RZ(roll(v2(m,m*m)));} 
  RZ(g=fac_ecm(x));     if(g!=xone){RZ(z=over(z,scx(g))); RZ(x=xdiv(x,g,XMFLR)); continue;}
  ASSERT(0,EVNONCE);
 }
 if(1==xcompare(x,xone))RZ(z=over(z,factor(sc(xint(x)))));
 EPILOG(grade2(z,z));
}

/* ---------------------------------------------------- */

F1(test_ecm){A*wv,z;I wd;X*ab,n,*zv;
 RZ(w);
 if(!p4792){RZ(p4792=prime1(IX(4792L))); ACX(p4792);}
 ASSERT(4==AN(w),EVLENGTH);
 ASSERT(BOX&AT(w),EVDOMAIN);
 wv=AAV(w); wd=(I)w*ARELATIVE(w);
 ASSERT(XNUM&AT(WVR(0)),EVDOMAIN); ASSERT(1==AR(WVR(0)),EVRANK); ASSERT(2==AN(WVR(0)),EVLENGTH);
 ASSERT(XNUM&AT(WVR(1)),EVDOMAIN); ASSERT(0==AR(WVR(1)),EVRANK);
 ASSERT(INT&AT(WVR(2)),EVDOMAIN);
 ASSERT(XNUM&AT(WVR(3)),EVDOMAIN);
 n=*XAV(WVR(1));
 ab=XAV(WVR(0));
 GA(z,XNUM,3,1,0); zv=XAV(z);
 RZ(ecm(n,ab[0],ab[1],i0(WVR(2)),XAV(WVR(3)),zv));
 R z;
}

F1(test_ecm_s1){A*wv,z;I wd;X*ab,n,*zv;
 RZ(w);
 if(!p4792){RZ(p4792=prime1(IX(4792L))); ACX(p4792);}
 ASSERT(4==AN(w),EVLENGTH);
 ASSERT(BOX&AT(w),EVDOMAIN);
 wv=AAV(w); wd=(I)w*ARELATIVE(w);
 ASSERT(XNUM&AT(WVR(0)),EVDOMAIN); ASSERT(1==AR(WVR(0)),EVRANK); ASSERT(2==AN(WVR(0)),EVLENGTH);
 ASSERT(XNUM&AT(WVR(1)),EVDOMAIN); ASSERT(0==AR(WVR(1)),EVRANK);
 ASSERT(INT&AT(WVR(2)),EVDOMAIN);
 ASSERT(XNUM&AT(WVR(3)),EVDOMAIN);
 n=*XAV(WVR(1));
 ab=XAV(WVR(0));
 GA(z,XNUM,3,1,0); zv=XAV(z);
 RZ(ecm_s1(n,ab[0],ab[1],i0(WVR(2)),XAV(WVR(3)),zv));
 R z;
}

F1(test_ecm_s2){A*wv,z;I*b1b2,wd;X*ab,n,*zv;
 RZ(w);
 if(!p4792){RZ(p4792=prime1(IX(4792L))); ACX(p4792);}
 ASSERT(4==AN(w),EVLENGTH);
 ASSERT(BOX&AT(w),EVDOMAIN);
 wv=AAV(w); wd=(I)w*ARELATIVE(w);
 ASSERT(XNUM&AT(WVR(0)),EVDOMAIN); ASSERT(1==AR(WVR(0)),EVRANK); ASSERT(2==AN(WVR(0)),EVLENGTH);
 ASSERT(XNUM&AT(WVR(1)),EVDOMAIN); ASSERT(0==AR(WVR(1)),EVRANK);
 ASSERT(INT &AT(WVR(2)),EVDOMAIN); ASSERT(1==AR(WVR(2)),EVRANK); ASSERT(2==AN(WVR(0)),EVLENGTH);
 ASSERT(XNUM&AT(WVR(3)),EVDOMAIN);
 n=*XAV(WVR(1));
 ab=XAV(WVR(0));
 b1b2=AV(WVR(2));
 GA(z,XNUM,3,1,0); zv=XAV(z);
 RZ(ecm_s2(n,ab[0],ab[1],b1b2[0],b1b2[1],XAV(WVR(3)),zv));
 R z;
}

F1(test_fac_ecm){
 RZ(w);
 if(!p4792){RZ(p4792=prime1(IX(4792L))); ACX(p4792);}
 ASSERT(!AR(w),EVRANK);
 ASSERT(XNUM&AT(w),EVDOMAIN);
 R scx(fac_ecm(*XAV(w)));
}