Mercurial > hg > jgplsrc
view vg.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: Grades */ #include "j.h" #include "vg.h" /************************************************************************/ /* */ /* merge sort with special code for n<:5 */ /* */ /************************************************************************/ static void jtmsmerge(J jt,I n,I*u,I*v){I m,q,*x,*xx,*y,*yy,*z;int c; q=n/2; z=v; x=u; xx=u+q-1; y=u+q; yy=u+n-1; while(1){ c=CALL1(jt->comp,*x,*y); if(0<c){*z++=*y++; if(y>yy){m=z-v; z=u+m; DO(1+xx-x, *z++=*x++;); DO(m, *u++=*v++;); break;}} else {*z++=*x++; if(x>xx){m=z-v; DO(m, *u++=*v++;); break;}} }} #define VS(i,j) (0<CALL1(jt->comp,u[i],u[j])) #define XC(i,j) {q=u[i]; u[i]=u[j]; u[j]=q;} #define P3(i,j,k) {ui=u[i]; uj=u[j]; uk=u[k]; u[0]=ui; u[1]=uj; u[2]=uk;} #define P5(i,j,k,l,m) {ui=u[i]; uj=u[j]; uk=u[k]; ul=u[l]; um=u[m]; \ u[0]=ui; u[1]=uj; u[2]=uk; u[3]=ul; u[4]=um;} void jtmsort(J jt,I n,I*u,I*v){I a,b,c,d,q,ui,uj,uk,ul,um; switch(n){ case 2: if(VS(0,1))XC(0,1); break; case 3: if(VS(0,1))XC(0,1); if(VS(1,2))if(VS(0,2))P3(2,0,1) else XC(1,2); break; case 4: if(VS(0,1))XC(0,1); if(VS(2,3))XC(2,3); if(VS(1,3)){XC(0,2); XC(1,3);} if(VS(1,2))if(VS(0,2))P3(2,0,1) else XC(1,2); break; case 5: if(VS(0,1))XC(0,1); if(VS(2,3))XC(2,3); if(VS(1,3)){XC(0,2); XC(1,3);} if(VS(4,1))if(VS(4,3)){a=0; b=1; c=3; d=4;}else{a=0; b=1; c=4; d=3;} else if(VS(4,0)){a=0; b=4; c=1; d=3;}else{a=4; b=0; c=1; d=3;} if(VS(2,b)){if(3!=c)if(VS(2,c))P5(a,b,c,2,d) else P5(a,b,2,c,d);} else { if(VS(2,a))P5(a,2,b,c,d) else P5(2,a,b,c,d);} break; default: if(5<n){ q=n/2; msort(q, u, v); msort(n-q,u+q,v); msmerge(n,u,v); }}} #define GF(f) B f(J jt,I m,I c,I n,A w,I*zv) /* m - # cells (# individual grades to do) */ /* c - # atoms in a cell */ /* n - length of sort axis */ /* w - array to be graded */ /* zv - result values */ static GF(jtgrx){A x;I ck,d,t,*xv; t=AT(w); ck=c*bp(t); jt->compk=ck/n; d=c/n; jt->compn=d; jt->compv=CAV(w); jt->compw=w; switch(t){ case BOX: jt->comp=ARELATIVE(w)?compr:compa; break; case C2T: jt->comp=compu; break; case INT: jt->comp=c==n?compi1:compi; break; case FL: jt->comp=c==n?compd1:compd; break; case CMPX: jt->comp=compd; jt->compn=2*d; break; case XNUM: jt->comp=compx; break; case RAT: jt->comp=compq; break; default: jt->comp=compc; } GA(x,INT,n,1,0); xv=AV(x); /* work area for msmerge() */ DO(m, DO(n, zv[i]=i;); msort(n,zv,xv); jt->compv+=ck; zv+=n;); R !jt->jerr; } /* grade"r w on general w */ /* grcol: grade/sort a halfword of an integer or a double */ /* d: # of possible different halfwords (65536 or 32768) */ /* c: smallest halfword value (0 or 32768) */ /* yv: halfword buckets work area */ /* n: # of sort elements */ /* xv: input permutation of sort elements */ /* zv: output permutation */ /* m: # of halfwords in a sort element (2 or 4) */ /* u: ptr to sort elements */ /* up: 1 if sort up; 0 if sort down */ /* split: 1 iff do split pass of halfword range */ /* sort: 1 if sort; 0 if grade */ void grcol(I d,I c,I*yv,I n,I*xv,I*zv,const I m,US*u,int up,int split,int sort){ D*xx,*zz;I k,s,*t;US*v; s=0; memset(c+yv,C0,d*SZI); v=u; DO(n, ++yv[*v]; v+=m;); switch(up+2*split){ case 0: t=yv+c+d; DO(d, --t; if(k=*t){*t=s; s+=k;}); break; case 1: t=yv+c-1; DO(d, ++t; if(k=*t){*t=s; s+=k;}); break; case 2: t=yv+c+d/2; DO(d/2, --t; if(k=*t){*t=s; s+=k;}); t=yv+c+d ; DO(d/2, --t; if(k=*t){*t=s; s+=k;}); break; case 3: t=yv+c+d/2-1; DO(d/2, ++t; if(k=*t){*t=s; s+=k;}); t=yv+c -1; DO(d/2, ++t; if(k=*t){*t=s; s+=k;}); } v=u; if(sort){ if(2==m) DO(n, zv[yv[*v ]++]=xv[i]; v+=m;) else {zz=(D*)zv; xx=(D*)xv; DO(n, zz[yv[*v ]++]=xx[i]; v+=m;);} }else if(!xv) DO(n, zv[yv[*v ]++]= i ; v+=m;) else DO(n, zv[yv[v[m*xv[i]]]++]=xv[i]; ); } static GF(jtgrd){A x,y;B b;D*v,*wv;I d,e,*g,*h,i,k,p,q,*xv,*yv;int up;US*u; if(!(c==n&&n>65536/3.5))R grx(m,c,n,w,zv); p=65536; q=p/2; up=1==jt->compgt; wv=DAV(w); GA(y,INT,p,1,0); yv=AV(y); GA(x,INT,n,1,0); xv=AV(x); #if SYS & SYS_LILENDIAN d= 1; e=0; #else d=-1; e=3; #endif for(i=0;i<m;++i){ u=e+(US*)wv; v=wv; k=0; DO(n, if(0>*v++)++k;); b=0<k&&k<n; g=b?xv:zv; h=b?zv:xv; grcol(p, 0L, yv,n,0L,h,sizeof(D)/sizeof(US),u+0*d,k==n?!up:up,0,0); grcol(p, 0L, yv,n,h, g,sizeof(D)/sizeof(US),u+1*d,k==n?!up:up,0,0); grcol(p, 0L, yv,n,g, h,sizeof(D)/sizeof(US),u+2*d,k==n?!up:up,0,0); grcol(b?p:q,k==n?q:0,yv,n,h, g,sizeof(D)/sizeof(US),u+3*d,k==n?!up:up,0,0); if(b){D d;I j,m,*u,*v,*vv; if(up){ICPY(k+zv, xv,n-k); u=zv; v=n+xv;} else {ICPY( zv,k+xv,n-k); u=zv+n-k; v=k+xv;} j=0; d=wv[*(v-1)]; DO(1+k, --v; if(d!=wv[*v]){vv=1+v; m=i-j; DO(m, *u++=*vv++;); j=i; d=wv[*v];}); } wv+=c; zv+=n; } R 1; } /* grade"r w on real w; main code here is for c==n */ static GF(jtgri1){A x,y;I*wv;I d,e,i,p,*xv,*yv;int up;US*u; p=65536; up=1==jt->compgt; wv=AV(w); GA(y,INT,p,1,0); yv=AV(y); GA(x,INT,n,1,0); xv=AV(x); e=SY_64?3:1; #if SYS & SYS_LILENDIAN d= 1; #else d=-1; #endif for(i=0;i<m;++i){ u=e*(-1==d)+(US*)wv; grcol(p,0L,yv,n,0L,xv,sizeof(I)/sizeof(US),u, up,0,0); #if SY_64 grcol(p,0L,yv,n,xv,zv,sizeof(I)/sizeof(US),u+1*d,up,0,0); grcol(p,0L,yv,n,zv,xv,sizeof(I)/sizeof(US),u+2*d,up,0,0); #endif grcol(p,0L,yv,n,xv,zv,sizeof(I)/sizeof(US),u+e*d,up,1,0); wv+=c; zv+=n; } R 1; } /* grade"r w on integer w where c==n */ void irange(I n,I*v,I*base,I*top){I d,i,m=n/2,p,q,x,y; if(n>m+m)p=q=*v++; else if(n){q=IMAX; p=IMIN;}else p=q=0; for(i=0;i<m;++i){ x=*v++; y=*v++; if(x<y){if(x<q)q=x; if(p<y)p=y;} else {if(y<q)q=y; if(p<x)p=x;} } *base=q; d=p-q; *top=0>d||d==IMAX?0:1+d; } /* min and max in 1.5*n comparisons */ F1(jtmaxmin){I base,top; RZ(w); ASSERT(INT&AT(w),EVDOMAIN); irange(AN(w),AV(w),&base,&top); R v2(base,base+top-1); } static GF(jtgri){A x,y;B b,up;I d,e,*g,*h,i,j,k,p,ps,q,s,*v,*wv,*xv,*yv; wv=AV(w); d=c/n; k=4*n; irange(AN(w),wv,&q,&p); if(!p||k<p||(0.69*d*(p+2*n))>n*log((D)n))R c==n&&n>65536/1.5?gri1(m,c,n,w,zv):grx(m,c,n,w,zv); if(0<q&&q<k-p){p+=q; q=0;} GA(y,INT,p,1,0); yv=AV(y); ps=p*SZI; up=1==jt->compgt; if(1<d){GA(x,INT,n,1,0); xv=AV(x);} for(i=0;i<m;++i){ s=0; j=p; memset(yv,C0,ps); v=wv+d-1; if(q) DO(n, ++yv[*v-q]; v+=d;) else DO(n, ++yv[*v ]; v+=d;); if(up)DO(p, if(k=yv[i]){yv[i]=s; s+=k;}) else DO(p, --j; if(k=yv[j]){yv[j]=s; s+=k;}); v=wv+d-1; if(q) DO(n, zv[yv[*v-q]++]=i; v+=d;) else DO(n, zv[yv[*v ]++]=i; v+=d;); v=wv+d-1; for(e=d-2,b=0;0<=e;--e){ --v; if(b){g=xv; h=zv; b=0;}else{g=zv; h=xv; b=1;} s=0; j=p; memset(yv,C0,ps); if(q) DO(n, ++yv[*(v+d*g[i])-q];) else DO(n, ++yv[*(v+d*g[i]) ];); if(up)DO(p, if(k=yv[i]){yv[i]=s; s+=k;}) else DO(p, --j; if(k=yv[j]){yv[j]=s; s+=k;}); if(q) DO(n, h[yv[*(v+d*g[i])-q]++]=g[i];) else DO(n, h[yv[*(v+d*g[i]) ]++]=g[i];); } if(b)DO(n, zv[i]=xv[i];); wv+=c; zv+=n; } R 1; } /* grade"r w on small-range integers w */ #define DOCOL1(p,iicalc0,iicalc1,ind,vinc) \ {I*g,*h, j=p-1,k,s=0;UC*v; \ if(b){g=xv; h=zv; b=0;}else{g=zv; h=xv; b=1;} \ memset(yv,C0,ps); \ v=vv; DO(n, ++yv[iicalc0]; v+=d;); \ if(up)DO(p, k=yv[i]; yv[i ]=s; s+=k;) \ else DO(p, k=yv[j]; yv[j--]=s; s+=k;); \ v=vv; DO(n, h[yv[iicalc1]++]=ind; vinc;); \ } #define DOCOL4(p,iicalc0,iicalc1,ind,vinc) \ {I*g,*h,ii,j=p-1,k,s=0;UC*v; \ if(b){g=xv; h=zv; b=0;}else{g=zv; h=xv; b=1;} \ memset(yv,C0,ps); \ v=vv; DO(n, IND4(iicalc0); ++yv[ii]; v+=d;); \ if(up)DO(p, k=yv[i]; yv[i ]=s; s+=k;) \ else DO(p, k=yv[j]; yv[j--]=s; s+=k;); \ v=vv; DO(n, IND4(iicalc1); h[yv[ii]++]=ind; vinc;); \ } static GF(jtgrb){A x;B b,up;I d,i,p,ps,q,*xv,yv[16];UC*vv,*wv; if(c>4*n*log((D)n))R grx(m,c,n,w,zv); d=c/n; q=d/4; p=16; ps=p*SZI; wv=UAV(w); up=1==jt->compgt; if(1<q){GA(x,INT,n,1,0); xv=AV(x);} for(i=0;i<m;++i){ vv=wv+d; b=1&&q%2; if(q){ vv-=4; DOCOL4(p, *(int*)v, *(int*)v, i, v+=d);} DO(q-1, vv-=4; DOCOL4(p, *(int*)v, *(int*)(v+d*g[i]),g[i],v );); wv+=c; zv+=n; } R 1; } /* grade"r w on boolean w, works 4 columns at a time (d%4 guaranteed to be 0)*/ static GF(jtgrc){A x;B b,q,up;I d,e,i,p,ps,*xv,yv[256];UC*vv,*wv; d=C2T&AT(w)?2*c/n:c/n; if(d>log((D)n))R grx(m,c,n,w,zv); p=B01&AT(w)?2:256; ps=p*SZI; wv=UAV(w); up=1==jt->compgt; q=C2T&AT(w) && SYS&SYS_LILENDIAN; if(1<d){GA(x,INT,n,1,0); xv=AV(x);} for(i=0;i<m;++i){ b=(B)(d%2); if(q){e=-3; vv=wv+d-2;}else{e=-1; vv=wv+d-1;} DOCOL1(p,*v,*v, i, v+=d); if(q)e=1==e?-3:1; DO(d-1, vv+=e; DOCOL1(p,*v,v[d*g[i]],g[i],v ); if(q)e=1==e?-3:1;); wv+=d*n; zv+=n; } R 1; } /* grade"r w on boolean or char or unicode w */ static GF(jtgrs){R gri(m,c,n,sborder(w),zv);} /* grade"r w on symbols w */ F2(jtgrade1p){PROLOG;A x,z;I n,*s,*xv,*zv; s=AS(w); n=s[0]; jt->compn=s[1]-1; jt->compk=SZI*s[1]; jt->comp=compp; jt->compsyv=AV(a); jt->compv=CAV(w); GA(z,INT,n,1,0); zv=AV(z); DO(n, zv[i]=i;); GA(x,INT,n,1,0); xv=AV(x); msort(n,zv,xv); EPILOG(z); } /* /:(}:a){"1 w , permutation a, integer matrix w */ /************************************************************************/ /* */ /* /: and \: main control */ /* */ /************************************************************************/ F1(jtgr1){PROLOG;A z;I c,f,m,n,r,*s,t,wr,zn; RZ(w); t=AT(w); wr=AR(w); r=jt->rank?jt->rank[1]:wr; jt->rank=0; f=wr-r; s=AS(w); m=prod(f,s); c=m?AN(w)/m:prod(r,f+s); n=r?s[f]:1; RE(zn=mult(m,n)); GA(z,INT,zn,1+f,s); if(!r)*(AS(z)+f)=1; if(!c||1>=n)R reshape(shape(z),IX(n)); if (t&B01&&0==(c/n)%4)RZ(grb(m,c,n,w,AV(z))) else if(t&SBT )RZ(grs(m,c,n,w,AV(z))) else if(t&FL )RZ(grd(m,c,n,w,AV(z))) else if(t&INT )RZ(gri(m,c,n,w,AV(z))) else if(t&IS1BYTE+C2T )RZ(grc(m,c,n,w,AV(z))) else RZ(grx(m,c,n,w,AV(z))); EPILOG(z); } /* grade"r w main control for dense w */ #define GBEGIN(G,L) A z;int ogt=jt->compgt,olt=jt->complt; jt->compgt=G; jt->complt=L #define GEND(z) jt->compgt=ogt; jt->complt=olt; R z F1(jtgrade1 ){GBEGIN( 1,-1); RZ( w); z=SPARSE&AT(w)?grd1sp( w):gr1( w); GEND(z);} F1(jtdgrade1){GBEGIN(-1, 1); RZ( w); z=SPARSE&AT(w)?grd1sp( w):gr1( w); GEND(z);} F2(jtgrade2 ){GBEGIN( 1,-1); RZ(a&&w); z=SPARSE&AT(w)?grd2sp(a,w):gr2(a,w); GEND(z);} F2(jtdgrade2){GBEGIN(-1, 1); RZ(a&&w); z=SPARSE&AT(w)?grd2sp(a,w):gr2(a,w); GEND(z);} #define OSGT(i,j) (u[i]>u[j]) #define SORT4 \ switch(n){ \ case 2: \ if(OSGT(0,1))XC(0,1); break; \ case 3: \ if(OSGT(0,1))XC(0,1); \ if(OSGT(1,2))if(OSGT(0,2))P3(2,0,1) else XC(1,2); break; \ case 4: \ if(OSGT(0,1))XC(0,1); \ if(OSGT(2,3))XC(2,3); \ if(OSGT(1,3)){XC(0,2); XC(1,3);} \ if(OSGT(1,2))if(OSGT(0,2))P3(2,0,1) else XC(1,2); \ } #define OSLOOP(T,ATOMF) \ {T p0,p1,q,*tv,*u,ui,uj,uk,*v,*wv; \ tv=wv=(T*)AV(w); \ while(1){ \ if(4>=n){u=tv; SORT4; R ATOMF(tv[j]);} \ p0=tv[qv[i]%n]; ++i; if(i==qn)i=0; \ p1=tv[qv[i]%n]; ++i; if(i==qn)i=0; if(p0>p1){q=p0; p0=p1; p1=q;} \ if(p0==p1){m0=m1=0; v=tv; DO(n, if(p0>*v)++m0; ++v;);} \ else {m0=m1=0; v=tv; DO(n, if(p0>*v)++m0; else if(p1>*v)++m1; ++v;);} \ c=m0+m1; m=j<m0?m0:j<c?m1:n-c; \ if(t)u=v=tv; else{GA(t,wt,m,1,0); u=tv=(T*)AV(t); v=wv;} \ if (j<m0){ DO(n, if(*v<p0 )*u++=*v; ++v;); n=m;} \ else if(j<c ){j-=m0; DO(n, if(p0<=*v&&*v<p1)*u++=*v; ++v;); n=m;} \ else if(c ){j-=c; DO(n, if(p1<=*v )*u++=*v; ++v;); n=m;} \ else{DO(n, if(p1<*v)*u++=*v; ++v;); m=u-tv; c=n-m; if(j<c)R ATOMF(p1); j-=c; n=m;} \ }} F2(jtordstat){A q,t=0;I c,i=0,j,m,m0,m1,n,qn=53,*qv,wt; RZ(a&&w); n=AN(w); wt=AT(w); if(!(!AR(a)&&AT(a)&B01+INT&&4<n&&1==AR(w)&&wt&FL+INT))R from(a,grade2(w,w)); RE(j=i0(a)); if(0>j)j+=n; ASSERT(0<=j&&j<n,EVINDEX); RZ(q=df2(sc(qn),sc(IMAX),atop(ds(CQUERY),ds(CDOLLAR)))); qv=AV(q); if(wt&FL)OSLOOP(D,scf) else OSLOOP(I,sc); } /* a{/:~w */ F2(jtordstati){A t;I j,n,wt; RZ(a&&w); n=AN(w); wt=AT(w); if(!(!AR(a)&&AT(a)&B01+INT&&4<n&&1==AR(w)&&wt&FL+INT))R from(a,grade1(w)); RZ(t=ordstat(a,w)); if(wt&FL){D p=*DAV(t),*v=DAV(w); DO(n, if(p==*v++){j=i; break;});} else {I p=* AV(t),*v= AV(w); DO(n, if(p==*v++){j=i; break;});} R sc(j); } /* a {/:w */