Mercurial > hg > jgplsrc
view ar.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. */ /* */ /* Adverbs: Reduce (Insert) and Outer Product */ #include "j.h" #include "vasm.h" #include "ve.h" #include "vcomp.h" #include "ar.h" static DF1(jtreduce); #define PARITY2 u=(UC*)&s; b=0; b^=*u++; b^=*u++; #define PARITY4 u=(UC*)&s; b=0; b^=*u++; b^=*u++; b^=*u++; b^=*u++; #define PARITY8 u=(UC*)&s; b=0; b^=*u++; b^=*u++; b^=*u++; b^=*u++; b^=*u++; b^=*u++; b^=*u++; b^=*u++; #if SY_64 #define PARITYW PARITY8 #else #define PARITYW PARITY4 #endif #if SY_ALIGN #define VDONE(T,PAR) \ {I q=n/sizeof(T);T s,*y=(T*)x; DO(m, s=0; DO(q, s^=*y++;); PAR; *z++=b==pc;);} static void vdone(I m,I n,B*x,B*z,B pc){B b,*u; if(1==m){UI s,*xi; s=0; b=0; xi=(I*)x; DO(n/SZI, s^=*xi++;); u=(B*)xi; DO(n%SZI, b^=*u++;); u=(B*)&s; DO(SZI, b^=*u++;); *z=b==pc; }else if(0==n%sizeof(UI ))VDONE(UI, PARITYW) else if(0==n%sizeof(UINT))VDONE(UINT,PARITY4) else if(0==n%sizeof(US ))VDONE(US, PARITY2) else DO(m, b=0; DO(n, b^=*x++;); *z++=b==pc;); } #else static void vdone(I m,I n,B*x,B*z,B pc){B b;I q,r;UC*u;UI s,*y; q=n/SZI; r=n%SZI; y=(UI*)x; switch((r?2:0)+pc){ case 0: DO(m, s=0; DO(q, s^=*y++;); PARITYW; *z++=!b;); break; case 1: DO(m, s=0; DO(q, s^=*y++;); PARITYW; *z++= b;); break; case 2: DO(m, s=0; DO(q, s^=*y++;); PARITYW; u=(UC*)y; DO(r, b^=*u++;); *z++=!b; x+=n; y=(UI*)x;); break; case 3: DO(m, s=0; DO(q, s^=*y++;); PARITYW; u=(UC*)y; DO(r, b^=*u++;); *z++= b; x+=n; y=(UI*)x;); break; }} #endif #define RBFXLOOP(T,pfx) \ {T*xx=(T*)x,*yy,*z0,*zz=(T*)z; \ q=d/sizeof(T); \ for(j=0;j<m;++j){ \ yy=xx; xx-=q; z0=zz; DO(q, --xx; --yy; --zz; *zz=pfx(*xx,*yy);); \ DO(n-2, zz=z0; DO(q, --xx; --zz; *zz=pfx(*xx,*zz););); \ }} /* non-commutative */ #define RCFXLOOP(T,pfx) \ {T*xx=(T*)x,*yy,*z0,*zz=(T*)z; \ q=d/sizeof(T); \ for(j=0;j<m;++j){ \ yy=xx; xx+=q; z0=zz; DO(q, *zz++=pfx(*yy,*xx); ++xx; ++yy;); \ DO(n-2, zz=z0; DO(q, *zz++=pfx(*zz,*xx); ++xx; );); \ }} /* commutative */ #if SY_ALIGN #define RBFXODDSIZE(pfx,bpfx) RBFXLOOP(C,bpfx) #define REDUCECFX REDUCEBFX #else #define RBFXODDSIZE(pfx,bpfx) \ {B*zz;I r,t,*xi,*yi,*zi; \ q=d/SZI; r=d%SZI; xi=(I*)x; zz=z; \ for(j=0;j<m;++j,zz-=d){ \ yi=xi; xi=(I*)((B*)xi-d); zi=(I*)zz; \ DO(q, --xi; --yi; *--zi=pfx(*xi,*yi);); \ xi=(I*)((B*)xi-r); yi=(I*)((B*)yi-r); t=pfx(*xi,*yi); MC((B*)zi-r,&t,r); \ DO(n-2, zi=(I*)zz; DO(q, --xi; --zi; *zi=pfx(*xi,*zi);); \ xi=(I*)((B*)xi-r); zi=(I*)((B*)zi-r); t=pfx(*xi,*zi); MC( zi, &t,r);); \ }} /* non-commutative */ #define RCFXODDSIZE(pfx,bpfx) \ {I r,t,*xi,*yi,*zi; \ q=d/SZI; r=d%SZI; \ for(j=0;j<m;++j,x+=d,z+=d){ \ yi=(I*)x; x+=d; xi=(I*)x; zi=(I*)z; DO(q, *zi++=pfx(*yi,*xi); ++xi; ++yi;); t=pfx(*yi,*xi); MC(zi,&t,r); \ DO(n-2, x+=d; xi=(I*)x; zi=(I*)z; DO(q, *zi++=pfx(*zi,*xi); ++xi; ); t=pfx(*zi,*xi); MC(zi,&t,r);); \ }} /* commutative */ #define REDUCECFX(f,pfx,ipfx,spfx,bpfx,vdo) \ AHDRP(f,B,B){B*y=0;I d,j,q; \ if(c==n){vdo; R;} \ d=c/n; \ if(1==n)DO(d, *z++=*x++;) \ else if(0==d%sizeof(UI ))RCFXLOOP(UI, pfx) \ else if(0==d%sizeof(UINT))RCFXLOOP(UINT,ipfx) \ else if(0==d%sizeof(US ))RCFXLOOP(US, spfx) \ else RCFXODDSIZE(pfx,bpfx) \ } /* commutative */ #endif #define REDUCEBFX(f,pfx,ipfx,spfx,bpfx,vdo) \ AHDRP(f,B,B){B*y=0;I d,j,q; \ if(c==n){vdo; R;} \ d=c/n; x+=m*c; z+=m*d; \ if(1==n)DO(d, *--z=*--x;) \ else if(0==d%sizeof(UI ))RBFXLOOP(UI, pfx) \ else if(0==d%sizeof(UINT))RBFXLOOP(UINT,ipfx) \ else if(0==d%sizeof(US ))RBFXLOOP(US, spfx) \ else RBFXODDSIZE(pfx,bpfx) \ } /* non-commutative */ REDUCECFX( eqinsB, EQ, IEQ, SEQ, BEQ, vdone(m,n,x,z,(B)(n%2))) REDUCECFX( neinsB, NE, INE, SNE, BNE, vdone(m,n,x,z,1 )) REDUCECFX( orinsB, OR, IOR, SOR, BOR, DO(m, *z++=1&&memchr(x,C1,n); x+=c;)) REDUCECFX( andinsB, AND, IAND, SAND, BAND, DO(m, *z++=! memchr(x,C0,n); x+=c;)) REDUCEBFX( ltinsB, LT, ILT, SLT, BLT, DO(m, *z++= *(x+n-1)&&!memchr(x,C1,n-1)?1:0; x+=c;)) REDUCEBFX( leinsB, LE, ILE, SLE, BLE, DO(m, *z++=!*(x+n-1)&&!memchr(x,C0,n-1)?0:1; x+=c;)) REDUCEBFX( gtinsB, GT, IGT, SGT, BGT, DO(m, y=memchr(x,C0,n); *z++=1&&(y?1&(y-x):1&n); x+=c;)) REDUCEBFX( geinsB, GE, IGE, SGE, BGE, DO(m, y=memchr(x,C1,n); *z++=! (y?1&(y-x):1&n); x+=c;)) REDUCEBFX( norinsB, NOR, INOR, SNOR, BNOR, DO(m, y=memchr(x,C1,n); d=y?y-x:n; *z++=(1&d)==d<n-1; x+=c;)) REDUCEBFX(nandinsB, NAND,INAND,SNAND,BNAND,DO(m, y=memchr(x,C0,n); d=y?y-x:n; *z++=(1&d)!=d<n-1; x+=c;)) #if SY_ALIGN REDUCEPFX(plusinsB,I,B,PLUS) #else AHDRR(plusinsB,I,B){I d,dw,i,p,q,r,r1,s;UC*tu;UI*v; if(c==n&&n<SZI)DO(m, s=0; DO(n, s+=*x++;); *z++=s;) else if(c==n){UI t; p=n/SZI; q=p/255; r=p%255; r1=n%SZI; tu=(UC*)&t; for(i=0;i<m;++i){ s=0; v=(UI*)x; DO(q, t=0; DO(255, t+=*v++;); DO(SZI, s+=tu[i];)); t=0; DO(r, t+=*v++;); DO(SZI, s+=tu[i];); x=(B*)v; DO(r1, s+=*x++;); *z++=s; }}else{A t;UI*tv; d=c/n; dw=(d+SZI-1)/SZI; p=dw*SZI; memset(z,C0,m*d*SZI); q=n/255; r=n%255; t=ga(INT,dw,1,0); if(!t)R; tu=(UC*)AV(t); tv=(UI*)tu; v=(UI*)x; for(i=0;i<m;++i,z+=d){ DO(q, memset(tv,C0,p); DO(255, DO(dw,tv[i]+=v[i];); x+=d; v=(UI*)x;); DO(d,z[i]+=tu[i];)); memset(tv,C0,p); DO(r, DO(dw,tv[i]+=v[i];); x+=d; v=(UI*)x;); DO(d,z[i]+=tu[i];) ; }}} /* +/"r w on boolean w, originally by Roger Moore */ #endif REDUCEOVF( plusinsI, I, I, PLUSR, PLUSVV, PLUSRV) REDUCEOVF(minusinsI, I, I, MINUSR,MINUSVV,MINUSRV) REDUCEOVF(tymesinsI, I, I, TYMESR,TYMESVV,TYMESRV) REDUCCPFX( plusinsO, D, I, PLUSO) REDUCCPFX(minusinsO, D, I, MINUSO) REDUCCPFX(tymesinsO, D, I, TYMESO) REDUCENAN( plusinsD, D, D, PLUS ) REDUCENAN( plusinsZ, Z, Z, zplus ) REDUCEPFX( plusinsX, X, X, xplus ) REDUCEPFX(minusinsB, I, B, MINUS ) REDUCENAN(minusinsD, D, D, MINUS ) REDUCENAN(minusinsZ, Z, Z, zminus) REDUCEPFX(tymesinsD, D, D, TYMES ) REDUCEPFX(tymesinsZ, Z, Z, ztymes) REDUCENAN( divinsD, D, D, DIV ) REDUCENAN( divinsZ, Z, Z, zdiv ) REDUCEPFX( maxinsI, I, I, MAX ) REDUCEPFX( maxinsD, D, D, MAX ) REDUCEPFX( maxinsX, X, X, XMAX ) REDUCEPFX( maxinsS, SB,SB,SBMAX ) REDUCEPFX( mininsI, I, I, MIN ) REDUCEPFX( mininsD, D, D, MIN ) REDUCEPFX( mininsX, X, X, XMIN ) REDUCEPFX( mininsS, SB,SB,SBMIN ) static DF1(jtred0){DECLF;A x;I f,r,wr,*s; wr=AR(w); r=jt->rank?jt->rank[1]:wr; f=wr-r; s=AS(w); jt->rank=0; GA(x,AT(w),0L,r,f+s); R reitem(vec(INT,f,s),lamin1(df1(x,iden(fs)))); } /* f/"r w identity case */ static DF1(jtredg){PROLOG;DECLF;A y,z;B p;C*u,*v;I i,k,n,old,r,wr,yn,yr,*ys,yt; RZ(w); ASSERT(DENSE&AT(w),EVNONCE); wr=AR(w); r=jt->rank?jt->rank[1]:wr; jt->rank=0; if(r<wr)R rank1ex(w,self,r,jtredg); n=IC(w); p=ARELATIVE(w); RZ(z=tail(w)); yt=AT(z); yn=AN(z); yr=AR(z); ys=1+AS(w); k=yn*bp(yt); v=CAV(w)+k*(n-1); old=jt->tbase+jt->ttop; for(i=1;i<n;++i){ v-=k; GA(y,yt,yn,yr,ys); u=CAV(y); if(p){A1*wv=(A1*)v,*yv=(A1*)u;I d=(I)w-(I)y; AFLAG(y)=AFREL; DO(yn, yv[i]=d+wv[i];);}else MC(u,v,k); RZ(z=CALL2(f2,y,z,fs)); gc(z,old); } EPILOG(z); } /* f/"r w for general f and 1<(-r){$w */ static C fca[]={CSTAR, CPLUS, CEQ, CMIN, CMAX, CPLUSDOT, CSTARDOT, CNE, 0}; /* commutative & associative */ static A jtredsp1a(J jt,C id,A z,A e,I n,I r,I*s){A t;B b,p=0;D d=1; switch(id){ default: ASSERT(0,EVNONCE); case CPLUSDOT: R n?gcd(z,e):ca(e); case CSTARDOT: R n?lcm(z,e):ca(e); case CMIN: R n?minimum(z,e):ca(e); case CMAX: R n?maximum(z,e):ca(e); case CPLUS: if(n&&equ(e,zero))R z; DO(r, d*=s[i];); t=tymes(e,d>IMAX?scf(d-n):sc((I)d-n)); R n?plus (z,t):t; case CSTAR: if(n&&equ(e,one ))R z; DO(r, d*=s[i];); t=expn2(e,d>IMAX?scf(d-n):sc((I)d-n)); R n?tymes(z,t):t; case CEQ: p=1; /* fall thru */ case CNE: ASSERT(B01&AT(e),EVNONCE); if(!n)*BAV(z)=p; b=1; DO(r, if(!(s[i]%2)){b=0; break;}); R !p==*BAV(e)&&b!=n%2?not(z):z; }} /* f/w on sparse vector w, post processing */ static A jtredsp1(J jt,A w,A self,C id,VF ado,I cv,I f,I r,I zt){A e,x,z;I m,n;P*wp; RZ(w); wp=PAV(w); e=SPA(wp,e); x=SPA(wp,x); n=AN(x); m=*AS(w); GA(z,zt,1,0,0); if(n){ado(jt,1L,n,n,AV(z),AV(x)); RE(0); if(m==n)R z;} R redsp1a(id,z,e,n,AR(w),AS(w)); } /* f/"r w for sparse vector w */ DF1(jtredravel){A f,x,z;C id;I cv,n;P*wp;VF ado; RZ(w); f=VAV(self)->f; if(!(SPARSE&AT(w)))R reduce(AN(w)?gah(1L,w):mtv,f); wp=PAV(w); x=SPA(wp,x); n=AN(x); id=vaid(VAV(f)->f); while(1){ vains(id,AT(x),&ado,&cv); ASSERT(ado,EVNONCE); GA(z,rtype(cv),1,0,0); if(n)ado(jt,1L,n,n,AV(z),AV(x)); if(jt->jerr!=EWOV)R redsp1a(id,z,SPA(wp,e),n,AR(w),AS(w));; }} /* f/@, w */ static A jtredspd(J jt,A w,A self,C id,VF ado,I cv,I f,I r,I zt){A a,e,x,z,zx;I c,m,n,*s,t,*v,wr,*ws,xf,xr;P*wp,*zp; RZ(w); ASSERT(strchr(fca,id),EVNONCE); wp=PAV(w); a=SPA(wp,a); e=SPA(wp,e); x=SPA(wp,x); s=AS(x); xr=r; v=AV(a); DO(AN(a), if(f<v[i])--xr;); xf=AR(x)-xr; m=prod(xf,s); c=m?AN(x)/m:0; n=s[xf]; GA(zx,zt,AN(x)/n,AR(x)-1,s); ICPY(xf+AS(zx),1+xf+s,xr-1); ado(jt,m,c,n,AV(zx),AV(x)); RE(0); switch(id){ case CPLUS: if(!equ(e,zero))RZ(e=tymes(e,sc(n))); break; case CSTAR: if(!equ(e,one )&&!equ(e,zero))RZ(e=expn2(e,sc(n))); break; case CEQ: ASSERT(B01&AT(x),EVNONCE); if(!*BAV(e)&&0==n%2)e=one; break; case CNE: ASSERT(B01&AT(x),EVNONCE); if( *BAV(e)&&1==n%2)e=zero; } if(AT(e)!=AT(zx)){t=maxtype(AT(e),AT(zx)); if(t!=AT(zx))RZ(zx=cvt(t,zx));} wr=AR(w); ws=AS(w); GA(z,STYPE(AT(zx)),1,wr-1,ws); if(1<wr)ICPY(f+AS(z),f+1+ws,wr-1); zp=PAV(z); RZ(a=ca(a)); v=AV(a); DO(AN(a), if(f<v[i])--v[i];); SPB(zp,a,a); SPB(zp,e,cvt(AT(zx),e)); SPB(zp,i,SPA(wp,i)); SPB(zp,x,zx); R z; } /* f/"r w for sparse w, rank > 1, dense axis */ static B jtredspsprep(J jt,C id,I f,I zt,A a,A e,A x,A y,I*zm,I**zdv,B**zpv,I**zqv,C**zxxv,A*zsn){ A d,p,q,sn=0,xx;B*pv;C*xxv;I*dv,j,k,m,mm,*qv=0,*u,*v,yc,yr,yr1,*yv; v=AS(y); yr=v[0]; yc=v[1]; yr1=yr-1; RZ(d=grade1(eq(a,sc(f)))); dv=AV(d); DO(AN(a), if(i!=dv[i]){RZ(q=grade1p(d,y)); qv=AV(q); break;}); GA(p,B01,yr,1,0); pv=BAV(p); memset(pv,C0,yr); u=yv=AV(y); m=mm=0; j=-1; if(qv)v=yv+yc*qv[0]; for(k=0;k<yr1;++k){ if(qv){u=v; v=yv+yc*qv[1+k];}else v=u+yc; DO(yc-1, if(u[dv[i]]!=v[dv[i]]){++m; pv[k]=1; mm=MAX(mm,k-j); j=k; break;}); if(!qv)u+=yc; } if(yr){++m; pv[yr1]=1; mm=MAX(mm,yr1-j);} if(qv){j=mm*aii(x); GA(xx,AT(x),j,1,0); xxv=CAV(xx);} switch(id){ case CPLUS: case CPLUSDOT: j=!equ(e,zero); break; case CSTAR: case CSTARDOT: j=!equ(e,one); break; case CMIN: j=!equ(e,zt&B01?one :zt&INT?sc(IMAX):ainf ); break; case CMAX: j=!equ(e,zt&B01?zero:zt&INT?sc(IMIN):scf(infm)); break; case CEQ: j=!*BAV(e); break; case CNE: j= *BAV(e); break; } if(j)GA(sn,INT,m,1,0); *zm=m; *zdv=dv; *zpv=pv; *zqv=qv; *zxxv=xxv; *zsn=sn; R 1; } static B jtredspse(J jt,C id,I wm,I xt,A e,A zx,A sn,A*ze,A*zzx){A b;B nz;I t,zt; RZ(b=ne(zero,sn)); nz=!all0(b); zt=AT(zx); switch(id){ case CPLUS: if(nz)RZ(zx=plus (zx, tymes(e,sn) )); RZ(e= tymes(e,sc(wm)) ); break; case CSTAR: if(nz)RZ(zx=tymes(zx,bcvt(1,expn2(e,sn)))); RZ(e=bcvt(1,expn2(e,sc(wm)))); break; case CPLUSDOT: if(nz)RZ(zx=gcd(zx,from(b,over(zero,e)))); break; case CSTARDOT: if(nz)RZ(zx=lcm(zx,from(b,over(one ,e)))); break; case CMIN: if(nz)RZ(zx=minimum(zx,from(b,over(zt&B01?one: zt&INT?sc(IMAX):ainf, e)))); break; case CMAX: if(nz)RZ(zx=maximum(zx,from(b,over(zt&B01?zero:zt&INT?sc(IMIN):scf(infm),e)))); break; case CEQ: ASSERT(B01&xt,EVNONCE); if(nz)RZ(zx=eq(zx,eq(zero,residue(num[2],sn)))); if(!(wm%2))e=one; break; case CNE: ASSERT(B01&xt,EVNONCE); if(nz)RZ(zx=ne(zx,eq(one, residue(num[2],sn)))); if(!(wm%2))e=zero; break; } if(AT(e)!=AT(zx)){t=maxtype(AT(e),AT(zx)); if(t!=AT(zx))RZ(zx=cvt(t,zx));} *ze=e; *zzx=zx; R 1; } static A jtredsps(J jt,A w,A self,C id,VF ado,I cv,I f,I r,I zt){A a,a1,e,sn,x,x1=0,y,z,zx,zy;B*pv; C*xv,*xxv,*zv;I*dv,i,m,n,*qv,*sv,*v,wr,xk,xt,wm,*ws,xc,yc,yr,*yu,*yv,zk;P*wp,*zp; RZ(w); ASSERT(strchr(fca,id),EVNONCE); wr=AR(w); ws=AS(w); wm=ws[f]; wp=PAV(w); a=SPA(wp,a); e=SPA(wp,e); y=SPA(wp,i); v=AS(y); yr=v[0]; yc=v[1]; yv=AV(y); x=SPA(wp,x); xt=AT(x); xc=aii(x); RZ(redspsprep(id,f,zt,a,e,x,y,&m,&dv,&pv,&qv,&xxv,&sn)); xv=CAV(x); xk=xc*bp(xt); GA(zx,zt,m*xc,AR(x),AS(x)); *AS(zx)=m; zv=CAV(zx); zk=xc*bp(zt); GA(zy,INT,m*(yc-1),2,0); v=AS(zy); v[0]=m; v[1]=yc-1; yu=AV(zy); v=qv; if(sn)sv=AV(sn); for(i=0;i<m;++i){A y;B*p1;C*u;I*vv; p1=1+(B*)memchr(pv,C1,yr); n=p1-pv; if(sn)sv[i]=wm-n; pv=p1; vv=qv?yv+yc**v:yv; DO(yc-1, *yu++=vv[dv[i]];); if(1<n){if(qv){u=xxv; DO(n, MC(u,xv+xk*v[i],xk); u+=xk;);} ado(jt,1L,n*xc,n,zv,qv?xxv:xv); RE(0);} else if(zk==xk)MC(zv,qv?xv+xk**v:xv,xk); else {if(!x1)GA(x1,xt,xc,1,0); MC(AV(x1),qv?xv+xk**v:xv,xk); RZ(y=cvt(zt,x1)); MC(zv,AV(y),zk);} zv+=zk; if(qv)v+=n; else{xv+=n*xk; yv+=n*yc;} } if(sn)RZ(redspse(id,wm,xt,e,zx,sn,&e,&zx)); RZ(a1=ca(a)); v=AV(a1); n=0; DO(AN(a), if(f!=v[i])v[n++]=v[i]-(f<v[i]);); GA(z,STYPE(AT(zx)),1,wr-1,ws); if(1<r)ICPY(f+AS(z),f+1+ws,r-1); zp=PAV(z); SPB(zp,a,vec(INT,n,v)); SPB(zp,e,cvt(AT(zx),e)); SPB(zp,x,zx); SPB(zp,i,zy); R z; } /* f/"r w for sparse w, rank > 1, sparse axis */ static DF1(jtreducesp){A a,g,x,y,z;B b;C id;I cv,f,n,r,rr[2],*v,wn,wr,*ws,wt,zt;P*wp;VF ado; RZ(w); wr=AR(w); r=jt->rank?jt->rank[1]:wr; f=wr-r; wn=AN(w); ws=AS(w); n=r?ws[f]:1; wt=AT(w); wt=wn?DTYPE(wt):B01; g=VAV(self)->f; id=vaid(g); if(!n)R red0(w,self); vains(id,wt,&ado,&cv); if(2==n&&!(ado&&strchr(fca,id))){ rr[0]=0; rr[1]=r; jt->rank=rr; x=from(zero,w); jt->rank=rr; y=from(one, w); R df2(x,y,g); } if(!ado)R redg(w,self); if(1==n)R tail(w); zt=rtype(cv); jt->rank=0; if(1==wr)z=redsp1(w,self,id,ado,cv,f,r,zt); else{ wp=PAV(w); a=SPA(wp,a); v=AV(a); b=0; DO(AN(a), if(f==v[i]){b=1; break;}); z=b?redsps(w,self,id,ado,cv,f,r,zt):redspd(w,self,id,ado,cv,f,r,zt); } R jt->jerr==EWOV?(rr[1]=r,jt->rank=rr,reducesp(w,self)):z; } /* f/"r for sparse w */ #define BR2IFX(T,F) {T*u=(T*)wv,*v=u+d,x,y; \ GA(z,B01,wn/2,wr-1,ws); zv=BAV(z); \ if(1<d)DO(m, DO(d, x=*u++; y=*v++; *zv++=x F y; ); u+=d; v+=d;) \ else DO(m, x=*u++; y=*u++; *zv++=x F y; ); \ } #define BR2PFX(T,F) {T*u=(T*)wv,*v=u+d,x,y; \ GA(z,B01,wn/2,wr-1,ws); zv=BAV(z); \ if(1<d)DO(m, DO(d, x=*u++; y=*v++; *zv++=F(x,y);); u+=d; v+=d;) \ else DO(m, x=*u++; y=*u++; *zv++=F(x,y); ); \ } #define BTABIFX(F) {btab[0 ]=0 F 0; \ btab[SYS&SYS_LILENDIAN?256: 1]=0 F 1; \ btab[SYS&SYS_LILENDIAN? 1:256]=1 F 0; \ btab[257 ]=1 F 1; \ } #define BTABPFX(F) {btab[0 ]=F(0,0); \ btab[SYS&SYS_LILENDIAN?256: 1]=F(0,1); \ btab[SYS&SYS_LILENDIAN? 1:256]=F(1,0); \ btab[257 ]=F(1,1); \ } #define BR2CASE(t,id) ((id)+256*(t)) static B jtreduce2(J jt,A w,C id,I f,I r,A*zz){A z=0;B b=0,btab[258],*zv;I c,d,m,wn,wr,*ws,*wv; wn=AN(w); wr=AR(w); ws=AS(w); wv=AV(w); m=prod(f,ws); c=m?wn/m:prod(r,f+ws); d=c/2; switch(BR2CASE(AT(w),id)){ case BR2CASE(B01,CEQ ): if(b=1==r)BTABIFX(== ); break; case BR2CASE(B01,CNE ): if(b=1==r)BTABIFX(!= ); break; case BR2CASE(B01,CLT ): if(b=1==r)BTABIFX(< ); break; case BR2CASE(B01,CLE ): if(b=1==r)BTABIFX(<= ); break; case BR2CASE(B01,CGT ): if(b=1==r)BTABIFX(> ); break; case BR2CASE(B01,CGE ): if(b=1==r)BTABIFX(>= ); break; case BR2CASE(B01,CMAX ): case BR2CASE(B01,CPLUSDOT): if(b=1==r)BTABIFX(|| ); break; case BR2CASE(B01,CPLUSCO ): if(b=1==r)BTABPFX(BNOR ); break; case BR2CASE(B01,CMIN ): case BR2CASE(B01,CSTAR ): case BR2CASE(B01,CSTARDOT): if(b=1==r)BTABIFX(&& ); break; case BR2CASE(B01,CSTARCO ): if(b=1==r)BTABPFX(BNAND); break; case BR2CASE(LIT,CEQ ): BR2IFX(C,== ); break; case BR2CASE(LIT,CNE ): BR2IFX(C,!= ); break; case BR2CASE(INT,CEQ ): BR2IFX(I,== ); break; case BR2CASE(INT,CLT ): BR2IFX(I,< ); break; case BR2CASE(INT,CLE ): BR2IFX(I,<= ); break; case BR2CASE(INT,CGT ): BR2IFX(I,> ); break; case BR2CASE(INT,CGE ): BR2IFX(I,>= ); break; case BR2CASE(INT,CNE ): BR2IFX(I,!= ); break; case BR2CASE(FL, CEQ ): BR2PFX(D,TEQ); break; case BR2CASE(FL, CLT ): BR2PFX(D,TLT); break; case BR2CASE(FL, CLE ): BR2PFX(D,TLE); break; case BR2CASE(FL, CGT ): BR2PFX(D,TGT); break; case BR2CASE(FL, CGE ): BR2PFX(D,TGE); break; case BR2CASE(FL, CNE ): BR2PFX(D,TNE); break; } if(b){S*u=(S*)wv; GA(z,B01,wn/2,wr-1,ws); zv=BAV(z); DO(m, *zv++=btab[*u++];);} if(z&&1<r){I*u=f+AS(z),*v=f+1+ws; DO(r-1, *u++=*v++;);} *zz=z; R 1; } /* f/"r for dense w over an axis of length 2 */ static DF1(jtreduce){A z;C id;I c,cv,f,m,n,r,rr[2],t,wn,wr,*ws,wt,zt;VF ado; RZ(w); wr=AR(w); r=jt->rank?jt->rank[1]:wr; f=wr-r; wn=AN(w); ws=AS(w); n=r?ws[f]:1; if(SPARSE&AT(w))R reducesp(w,self); wt=AT(w); wt=wn?wt:B01; id=vaid(VAV(self)->f); switch(n){ case 0: R red0(w,self); case 1: R tail(w); case 2: RZ(reduce2(w,id,f,r,&z)); if(z)R z; } vains(id,wt,&ado,&cv); if(!ado)R redg(w,self); zt=rtype(cv); jt->rank=0; GA(z,zt,wn/n,MAX(0,wr-1),ws); if(1<r)ICPY(f+AS(z),f+1+ws,r-1); if((t=atype(cv))&&t!=wt)RZ(w=cvt(t,w)); m=prod(f,ws); c=m?wn/m:prod(r,f+ws); ado(jt,m,c,n,AV(z),AV(w)); if(jt->jerr)R jt->jerr==EWOV?(rr[1]=r,jt->rank=rr,reduce(w,self)):0; else R cv&VRI+VRD?cvz(cv,z):z; } /* f/"r w main control */ static A jtredcatsp(J jt,A w,A z,I r){A a,q,x,y;B*b;I c,d,e,f,j,k,m,n,n1,p,*u,*v,wr,*ws,xr;P*wp,*zp; ws=AS(w); wr=AR(w); f=wr-r; p=ws[1+f]; wp=PAV(w); x=SPA(wp,x); y=SPA(wp,i); a=SPA(wp,a); v=AV(a); m=*AS(y); n=AN(a); n1=n-1; xr=AR(x); RZ(b=bfi(wr,a,1)); c=b[f]; d=b[1+f]; if(c&&d)b[f]=0; e=f+!c; j=0; DO(n, if(e==v[i]){j=i; break;}); k=1; DO(f, if(!b[i])++k;); zp=PAV(z); SPB(zp,e,ca(SPA(wp,e))); GA(q,INT,n-(c&&d),1,0); v=AV(q); DO(wr, if(b[i])*v++=i-(i>f);); SPB(zp,a,q); if(c&&d){ /* sparse sparse */ SPB(zp,x,ca(x)); SPB(zp,i,q=repeatr(ne(a,sc(f)),y)); v=j+AV(q); u=j+AV(y); DO(m, *v=p*u[0]+u[1]; v+=n1; u+=n;); }else if(!c&&!d){ /* dense dense */ u=AS(x); GA(q,AT(x),AN(x),xr-1,u); v=k+AS(q); *v=u[k]*u[1+k]; ICPY(1+v,2+k+u,xr-k-2); MC(AV(q),AV(x),AN(x)*bp(AT(x))); SPB(zp,x,q); SPB(zp,i,ca(y)); }else{ /* other */ GA(q,INT,xr,1,0); v=AV(q); if(1!=k){*v++=0; *v++=k; e=0; DO(xr-1, ++e; if(e!=k)*v++=e;); RZ(x=cant2(q,x));} v=AV(q); u=AS(x); *v=u[0]*u[1]; ICPY(1+v,2+u,xr-1); RZ(x=reshape(vec(INT,xr-1,v),x)); e=ws[f+c]; RZ(y=repeat(sc(e),y)); v=j+AV(y); if(c)DO(m, k=p**v; DO(e, *v=k+ i; v+=n;);) else DO(m, k= *v; DO(e, *v=k+p*i; v+=n;);); RZ(q=grade1(y)); RZ(y=from(q,y)); RZ(x=from(q,x)); SPB(zp,x,x); SPB(zp,i,y); } R z; } /* ,/"r w for sparse w, 2<r */ static DF1(jtredcat){A z;B b;I f,r,*s,*v,wr; RZ(w); wr=AR(w); r=jt->rank?jt->rank[1]:wr; f=wr-r; s=AS(w); jt->rank=0; b=1==r&&1==s[f]; if(2>r&&!b)R ca(w); GA(z,AT(w),AN(w),wr-1,s); if(!b){v=f+AS(z); RE(*v=mult(s[f],s[1+f])); ICPY(1+v,2+f+s,r-2);} if(SPARSE&AT(w))R redcatsp(w,z,r); MC(AV(z),AV(w),AN(w)*bp(AT(w))); if(ARELATIVE(w)){AFLAG(z)=AFREL; z=relocate((I)w-(I)z,z);} R z; } /* ,/"r w */ static DF1(jtredsemi){I f,n,r,*s,wr; RZ(w); wr=AR(w); r=jt->rank?jt->rank[1]:wr; f=wr-r; s=AS(w); n=r?s[f]:1; if(2>n){ASSERT(n,EVDOMAIN); R tail(w);} if(BOX&AT(w))R irs2(rank1ex(curtail(w),0L,r-1,jtbox),tail(w),0L,r,r-1,jtover); else R irs1(w,0L,r-1,jtbox); } /* ;/"r w */ static DF1(jtredstitch){A c,y;I f,n,r,*s,*v,wr; RZ(w); wr=AR(w); r=jt->rank?jt->rank[1]:wr; f=wr-r; jt->rank=0; s=AS(w); n=r?s[f]:1; ASSERT(n,EVDOMAIN); if(1==n)R irs1(w,0L,r,jthead); if(1==r)R 2==n?ca(w):irs2(irs2(num[-2],w,0L,0L,1L,jtdrop),irs2(num[-2],w,0L,0L,1L,jttake),0L,1L,0L,jtover); if(2==r)R irs1(w,0L,2L,jtcant1); RZ(c=IX(wr)); v=AV(c); v[f]=f+1; v[f+1]=f; RZ(y=cant2(c,w)); if(SPARSE&AT(w)){A x; GA(x,INT,f+r-1,1,0); v=AV(x); ICPY(v,AS(y),f+1); RE(v[f+1]=mult(s[f],s[f+2])); ICPY(v+f+2,s+3+f,r-3); R reshape(x,y); }else{ v=AS(y); RE(v[f+1]=mult(s[f],s[f+2])); ICPY(v+f+2,s+3+f,r-3); --AR(y); R y; }} /* ,./"r w */ static DF1(jtredstiteach){A*wv,y;I n,p,r,t,wd; RZ(w); n=AN(w); if(!(2<n&&1==AR(w)&&BOX&AT(w)))R reduce(w,self); wv=AAV(w); wd=(I)w*ARELATIVE(w); y=WVR(0); p=IC(y); t=AT(y); DO(n, y=WVR(i); r=AR(y); if(!(r&&r<=2&&p==IC(y)&&t==AT(y)))R reduce(w,self);); R box(razeh(w)); } /* ,.&.>/ w */ static DF1(jtredcateach){A*u,*v,*wv,x,*xv,z,*zv;I f,m,mn,n,r,wd,wr,*ws,zm,zn; RZ(w); wr=AR(w); ws=AS(w); r=jt->rank?jt->rank[1]:wr; f=wr-r; jt->rank=0; n=r?ws[f]:1; if(!r||1>=n)R reshape(repeat(ne(sc(f),IX(wr)),shape(w)),n?w:ace); if(!(BOX&AT(w)))R df1(cant2(sc(f),w),qq(ds(CBOX),one)); zn=AN(w)/n; zm=prod(f,ws); m=zm?AN(w)/(zm*n):prod(r-1,ws+f+1); mn=m*n; GA(z,BOX,zn,wr-1,ws); ICPY(AS(z)+f,ws+f+1,r-1); GA(x,BOX,n,1,0); xv=AAV(x); zv=AAV(z); wv=AAV(w); wd=(I)w*ARELATIVE(w); DO(zm, u=wv; DO(m, v=u++; DO(n, xv[i]=AADR(wd,*v); v+=m;); RZ(*zv++=raze(x));); wv+=mn;); R z; } /* ,&.>/"r w */ static DF2(jtoprod){R df2(a,w,VAV(self)->h);} F1(jtslash){A h;AF f1=jtreduce;C c;V*v; RZ(w); if(NOUN&AT(w))R evger(w,sc(GINSERT)); v=VAV(w); switch(v->id){ case CCOMMA: f1=jtredcat; break; case CCOMDOT: f1=jtredstitch; break; case CSEMICO: f1=jtredsemi; break; case CUNDER: if(COPE==ID(v->g)){c=ID(v->f); if(c==CCOMMA)f1=jtredcateach; else if(c==CCOMDOT)f1=jtredstiteach;} } RZ(h=qq(w,v2(lr(w),RMAX))); R fdef(CSLASH,VERB, f1,jtoprod, w,0L,h, 0L, RMAX,RMAX,RMAX); } A jtaslash (J jt,C c, A w){RZ( w); R df1( w, slash(ds(c)) );} A jtaslash1(J jt,C c, A w){RZ( w); R df1( w,qq(slash(ds(c)),one));} A jtatab (J jt,C c,A a,A w){RZ(a&&w); R df2(a,w, slash(ds(c)) );} static AHDRR(jtmeanD,D,D){I d,i;D*y;D v,*zz; d=c/n; NAN0; if(1==d)DO(m, v= *x++; DO(n-1, v+=*x++;); *z++=v/n;) else for(i=0;i<m;++i){ y=x; x+=d; zz=z; DO(d, *z++ =*x+++ *y++;); DO(n-3, z=zz; DO(d, *z+++=*x++; )); z=zz; DO(d, *z =(*z+*x++)/n; ++z;); } NAN1V; } /* based on REDUCEPFX; 2<n */ static AHDRR(jtmeanI,D,I){I d,i;I*y;D v,*zz; d=c/n; if(1==d)DO(m, v=(D)*x++; DO(n-1, v+=*x++;); *z++=v/n;) else for(i=0;i<m;++i){ y=x; x+=d; zz=z; DO(d, *z++ =*x+++(D)*y++;); DO(n-3, z=zz; DO(d, *z+++=*x++; )); z=zz; DO(d, *z =(*z+*x++)/n; ++z;); }} /* based on REDUCEPFX; 2<n */ DF1(jtmean){A z;I c,f,m,n,r,wn,wr,*ws,wt; RZ(w); wr=AR(w); r=jt->rank?jt->rank[1]:wr; f=wr-r; jt->rank=0; wt=AT(w); wn=AN(w); ws=AS(w); n=r?ws[f]:1; if(!(wn&&2<n&&wt&INT+FL))R divide(df1(w,qq(slash(ds(CPLUS)),sc(r))),sc(n)); GA(z,FL,wn/n,MAX(0,wr-1),ws); if(1<r)ICPY(f+AS(z),f+1+ws,r-1); m=prod(f,ws); c=m?wn/m:prod(r,f+ws); if(wt&INT)meanI(m,c,n,DAV(z), AV(w)); else meanD(m,c,n,DAV(z),DAV(w)); RE(0); R z; } /* (+/%#)"r w */