view vf.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 (2013-11-25)
parents
children
line wrap: on
line source
/* Copyright 1990-2011, Jsoftware Inc.  All rights reserved. */
/* License in license.txt.                                   */
/*                                                                         */
/* Verbs: Fill-Dependent Verbs                                             */

#include "j.h"


F2(jtsetfv){A q=jt->fill;I t;
 RZ(a&&w);
 t=AN(a)?AT(a):AN(w)?AT(w):0;
 if(q&&AN(q)){
  RE(t=maxtype(t,AT(q))); 
  if(t!=AT(q))RZ(q=cvt(t,q));
  if(ARELATIVE(q))RZ(q=cpa(1,q));
  jt->fillv=CAV(q);
 }else{if(!t)t=AT(w); fillv(t,1L,jt->fillv0); jt->fillv=jt->fillv0;}
 if(ARELATIVE(w)){*(I*)(jt->fillv0)=AREL(*(A*)jt->fillv,w); jt->fillv=jt->fillv0;}
 R t==AT(w)?w:cvt(t,w);
}

F1(jtfiller){A z; RZ(w); GA(z,AT(w),1,0,0); fillv(AT(w),1L,CAV(z)); R z;}

void fillv(I t,I n,C*v){I k=bp(t);
 if     (t&RAT        )mvc(n*k,v,k,&zeroQ);
 else if(t&XNUM       )mvc(n*k,v,k,&xzero);
 else if(t&NUMERIC+SBT)memset(v,C0,k*n);
 else if(t&LIT        )memset(v,' ',n);
 else if(t&C2T        ){US x=32; mvc(n*k,v,k,&x);}
 else                  mvc(n*k,v,k,&mtv);
}


static F2(jtrotsp){PROLOG;A q,x,y,z;B bx,by;I acr,af,ar,*av,d,k,m,n,p,*qv,*s,*v,wcr,wf,wr;P*wp,*zp;
 RZ(a&&w);
 ASSERT(!jt->fill,EVNONCE);
 ar=AR(a); acr=jt->rank?jt->rank[0]:ar; af=ar-acr; p=acr?*(af+AS(a)):1;
 wr=AR(w); wcr=jt->rank?jt->rank[1]:wr; wf=wr-wcr; jt->rank=0; 
 if(1<acr||af)R df2(a,w,qq(qq(ds(CROT),v2(1L,RMAX)),v2(acr,wcr)));
 if(!wcr&&1<p){RZ(w=reshape(over(shape(w),apv(p,1L,0L)),w)); wr=wcr=p;}
 ASSERT(!wcr||p<=wcr,EVLENGTH);
 s=AS(w);
 GA(q,INT,wr,1L,0); qv=AV(q); memset(qv,C0,wr*SZI); 
 RZ(a=vi(a)); v=AV(a); 
 DO(p, k=v[i]; d=s[wf+i]; qv[wf+i]=!d?0:0<k?k%d:k==IMIN?d-(-d-k)%d:d-(-k)%d;);
 wp=PAV(w); a=SPA(wp,a); RZ(y=ca(SPA(wp,i))); m=IC(y);
 n=AN(a); RZ(a=paxis(wr,a)); av=AV(a);
 RZ(q=from(a,q)); qv=AV(q);
 GA(z,AT(w),1,wr,s); zp=PAV(z);
 by=0; DO(n,    if(qv[  i]){by=1; break;});
 bx=0; DO(wr-n, if(qv[n+i]){bx=1; break;});
 RZ(x=!bx?ca(SPA(wp,x)):irs2(vec(INT,wr-n,n+qv),SPA(wp,x),0L,1L,-1L,jtrotate));
 if(by){
  DO(n, if(k=qv[i]){d=s[av[i]]-k; v=i+AV(y); DO(m, *v<k?(*v+=d):(*v-=k); v+=n;);});
  RZ(q=grade1(y)); RZ(y=from(q,y)); RZ(x=from(q,x));
 }
 SPB(zp,a,ca(SPA(wp,a))); 
 SPB(zp,e,ca(SPA(wp,e))); 
 SPB(zp,x,x);
 SPB(zp,i,y);
 EPILOG(z);
}    /* a|."r w on sparse arrays */

#define ROF(r) r=r<-n?-n:n<r?n:r; x=dk*ABS(r); y=e-x; j=0>r?x:0; k=0>r?0:x;
#define ROT(r) r=r%n;             x=dk*ABS(r); y=e-x; j=0>r?y:x; k=0>r?x:y;

static void jtrot(J jt,I m,I c,I n,I k,I p,I*av,C*u,C*v){I dk,e,j,r,x,y;
 e=c*k; dk=e/n; if(jt->fill)mvc(m*e,v,k,jt->fillv);   
 switch((jt->fill?0:2)+(1<p)){
  case 0: r=p?*av:0;     ROF(r); DO(m, MC(j+v,k+u,y);            u+=e; v+=e;); break;
  case 1: DO(m, r=av[i]; ROF(r);       MC(j+v,k+u,y);            u+=e; v+=e;); break;
  case 2: r=p?*av:0;     ROT(r); DO(m, MC(v,j+u,k); MC(k+v,u,j); u+=e; v+=e;); break;
  case 3: DO(m, r=av[i]; ROT(r);       MC(v,j+u,k); MC(k+v,u,j); u+=e; v+=e;);
}}

/* m   # cells
   c   # atoms in each cell
   n   # items in each cell
   k   # bytes in each atom
   p   length of av
   av  rotation amount(s)
   u   source data area 
   v   target data area      */

F2(jtrotate){A y,z;B b;C*u,*v;I acr,af,ar,*av,k,m,n,p,*s,wcr,wf,wn,wr;
 RZ(a&&w);
 if(SPARSE&AT(w))R rotsp(a,w);
 ar=AR(a); acr=jt->rank?jt->rank[0]:ar; af=ar-acr; p=acr?*(af+AS(a)):1;
 wr=AR(w); wcr=jt->rank?jt->rank[1]:wr; wf=wr-wcr; jt->rank=0;
 if(1<acr||af&&acr||af&&!wf)R df2(a,w,qq(qq(ds(CROT),v2(1L,RMAX)),v2(acr,wcr)));
 if(!wcr&&1<p){RZ(w=reshape(over(shape(w),apv(p,1L,0L)),w)); wr=wcr=p;}
 ASSERT(!wcr||p<=wcr,EVLENGTH);
 RZ(a=vi(a)); av=AV(a);
 RZ(w=setfv(w,w)); u=CAV(w); wn=AN(w); s=AS(w); k=bp(AT(w));
 GA(z,AT(w),wn,wr,s); v=CAV(z);
 if(!wn)R z;
 m=prod(wf,s); n=wcr?s[wf]:1;
 rot(m,wn/m,n,k,1>=p?AN(a):1L,av,u,v);
 if(1<p){
  GA(y,AT(w),wn,wr,s); u=CAV(y); 
  b=0; s+=wf;
  DO(p-1, m*=n; n=*++s; rot(m,wn/m,n,k,1L,av+i+1,b?u:v,b?v:u); b=!b;);
  z=b?y:z;
 } 
 R RELOCATE(w,z);
}    /* a|.!.f"r w */


static F1(jtrevsp){A a,q,x,y,z;I c,f,k,m,n,r,*v,wr;P*wp,*zp;
 RZ(w);
 ASSERT(!jt->fill,EVNONCE);
 wr=AR(w); r=jt->rank?jt->rank[1]:wr; f=wr-r; jt->rank=0;
 m=*(f+AS(w)); wp=PAV(w);
 GA(z,AT(w),1,wr,AS(w)); zp=PAV(z);
 a=SPA(wp,a); n=AN(a); RZ(y=ca(SPA(wp,i))); x=SPA(wp,x);
 RZ(q=paxis(wr,a)); v=AV(q); DO(wr, if(f==v[i]){k=i; break;});
 if(!r)       RZ(x=ca(x))
 else if(k>=n)RZ(x=irs2(apv(m,m-1,-1L),x,0L,1L,wr-k,jtfrom))
 else         {v=k+AV(y); c=m-1; DO(IC(y), *v=c-*v; v+=n;); q=grade1(y); RZ(y=from(q,y)); RZ(x=from(q,x));}
 SPB(zp,a,ca(a)); 
 SPB(zp,e,ca(SPA(wp,e))); 
 SPB(zp,i,y); 
 SPB(zp,x,x);
 R z;
}    /* |."r w on sparse arrays */

F1(jtreverse){A z;C*wv,*zv;I f,k,m,n,nk,r,*v,*ws,wt,wr;
 RZ(w);
 if(SPARSE&AT(w))R revsp(w);
 if(jt->fill)R rotate(num[-1],w);
 wr=AR(w); r=jt->rank?jt->rank[1]:wr; f=wr-r;
 if(!(r&&AN(w))){RZ(z=ca(w)); R ARELATIVE(w)?relocate((I)w-(I)z,z):z;}
 wt=AT(w); ws=AS(w); wv=CAV(w);
 n=ws[f]; 
 m=1; DO(f, m*=ws[i];);
 k=bp(wt); v=1+f+ws; DO(r-1, k*=*v++;); nk=n*k;
 GA(z,wt,AN(w),wr,ws); zv=CAV(z);
 switch(k){
  default:        {C*s=wv-k,*t; DO(m, t=s+=nk; DO(n, memcpy(zv,t,k); zv+=k; t-=k;););} break;
  case sizeof(C): {C*s=    wv,*t,*u=    zv; DO(m, t=s+=n; DO(n, *u++=*--t;););} break;
  case sizeof(S): {S*s=(S*)wv,*t,*u=(S*)zv; DO(m, t=s+=n; DO(n, *u++=*--t;););} break;
  case sizeof(I): {I*s=(I*)wv,*t,*u=(I*)zv; DO(m, t=s+=n; DO(n, *u++=*--t;););} break;
#if !SY_64 && SY_WIN32
  case sizeof(D): {D*s=(D*)wv,*t,*u=(D*)zv; DO(m, t=s+=n; DO(n, *u++=*--t;););} break;
#endif
 }
 R RELOCATE(w,z);
}    /* |."r w */


static A jtreshapesp0(J jt,A a,A w,I wf,I wcr){A e,p,x,y,z;B*b,*pv;I c,d,r,*v,wr,*ws;P*wp,*zp;
 wr=AR(w); ws=AS(w);
 wp=PAV(w); RZ(b=bfi(wr,SPA(wp,a),1));
 RZ(e=ca(SPA(wp,e))); x=SPA(wp,x); y=SPA(wp,i);
 v=AS(y); r=v[0]; c=v[1]; d=0; DO(wf, if(b[i])++d;);
 if(!wf){if(r&&c){v=AV(y); DO(c, if(v[i])R e;);} R AN(x)?reshape(mtv,x):e;}
 GA(z,AT(w),1,wf,ws);
 zp=PAV(z); SPB(zp,e,e); SPB(zp,a,ifb(wf,b));
 GA(p,B01,r,1,0); pv=BAV(p);
 v=AV(y); 
 DO(r, *pv=1; DO(c-d, if(v[d+i]){*pv=0; break;}); ++pv; v+=c;);
 SPB(zp,i,repeat(p,taker(d,y)));
 SPB(zp,x,irs2(mtv,repeat(p,x),0L,1L,wcr-(c-d),jtreshape));
 R z;
}    /* '' ($,)"wcr w for sparse w */

static A jtreshapesp(J jt,A a,A w,I wf,I wcr){A a1,e,t,x,y,z;B az,*b,wz;I an,*av,c,d,j,m,*u,*v,wr,*ws;P*wp,*zp;
 RZ(a=cvt(INT,a)); an=AN(a); av=AV(a); wr=AR(w); ws=AS(w); d=an-wcr;
 az=0; DO(an,  if(!av[   i])az=1;);
 wz=0; DO(wcr, if(!ws[wf+i])wz=1;);
 ASSERT(az||!wz,EVLENGTH);
 if(!an)R reshapesp0(a,w,wf,wcr);
 wp=PAV(w); a1=SPA(wp,a); c=AN(a1); RZ(b=bfi(wr,a1,1));
 RZ(e=ca(SPA(wp,e))); x=SPA(wp,x); y=SPA(wp,i);
 u=av+an; v=ws+wr; m=0; DO(MIN(an,wcr-1), if(*--u!=*--v){m=1; break;});
 if(m||an<wcr) R reshapesp(a,irs1(w,0L,wcr,jtravel),wf,1L);
 ASSERT(!jt->fill,EVDOMAIN);
 GA(z,AT(w),1,wf+an,ws); ICPY(wf+AS(z),av,an);
 zp=PAV(z); SPB(zp,e,e);  
 GA(t,INT,c+d*b[wf],1,0); v=AV(t); 
 DO(wf, if(b[i])*v++=i;); if(b[wf])DO(d, *v++=wf+i;); j=wf; DO(wcr, if(b[j])*v++=d+j; ++j;);
 SPB(zp,a,t);
 if(b[wf]){I n,q,r,*v0;   /* sparse */
  if(wf!=*AV(a1))R rank2ex(a,w,0L,1L,wcr,jtreshape);
  RE(m=prod(1+d,av)); n=IC(y); q=n*(m/ws[wf]); r=m%ws[wf];
  v=AV(y); DO(n, if(r<=*v)break; ++q; v+=c;);
  GA(t,INT,q,1,0); u=AV(t); v=v0=AV(y);
  m=j=0; DO(q, u[i]=m+*v; v+=c; ++j; if(j==n){j=0; v=v0; m+=ws[wf];});
  SPB(zp,i,stitch(abase2(vec(INT,1+d,av),t),reitem(sc(q),dropr(1L,y))));
  SPB(zp,x,reitem(sc(q),x));
 }else{                   /* dense  */
  GA(t,INT,an,1,0); v=AV(t); ICPY(v,av,d); m=d; j=wf; DO(wcr, if(!b[j++])v[m++]=av[i+d];);
  SPB(zp,i,ca(y));
  SPB(zp,x,irs2(vec(INT,m,v),x,0L,1L,wcr-(an-m),jtreshape));
 }
 R z;
}    /* a ($,)"wcr w for sparse w and scalar or vector a */

F2(jtreshape){A z;B b;C*wv,*zv;I acr,ar,c,k,m,n,p,q,r,*s,t,*u,wcr,wf,wr,*ws,zn;
 RZ(a&&w);
 ar=AR(a); acr=jt->rank?jt->rank[0]:ar;
 wr=AR(w); wcr=jt->rank?jt->rank[1]:wr; wf=wr-wcr; ws=AS(w); jt->rank=0;
 if(1<acr||acr<ar)R rank2ex(a,w,0L,MIN(1,acr),wcr,jtreshape);
 RZ(a=vip(a)); r=AN(a); u=AV(a);
 if(SPARSE&AT(w))R reshapesp(a,w,wf,wcr);
 RE(m=prod(r,u)); RE(c=prod(wf,ws)); RE(n=c?AN(w)/c:prod(wcr,wf+ws)); 
 ASSERT(n||!m||jt->fill,EVLENGTH);
 b=jt->fill&&m>n; if(b)RZ(w=setfv(w,w)); 
 t=AT(w); k=bp(t); p=k*m; q=k*n;
 RE(zn=mult(c,m));
 GA(z,t,zn,r+wf,0); s=AS(z); ICPY(s,ws,wf); ICPY(wf+s,u,r);
 if(!zn)R z;
 zv=CAV(z); wv=CAV(w); 
 if(b)DO(c, mvc(q,zv,q,wv); mvc(p-q,q+zv,k,jt->fillv); zv+=p; wv+=q;)
 else DO(c, mvc(p,zv,q,wv); zv+=p; wv+=q;);
 R RELOCATE(w,z);
}    /* a ($,)"r w */

F2(jtreitem){A y;I acr,an,ar,m,r,*v,wcr,wr;
 RZ(a&&w);
 ar=AR(a); acr=jt->rank?jt->rank[0]:ar; m=MIN(1,acr);
 wr=AR(w); wcr=jt->rank?jt->rank[1]:wr; r=wcr-1; jt->rank=0;
 if(1<acr||acr<ar)R rank2ex(a,w,0L,m,wcr,jtreitem);
 if(1>=wcr)y=a;
 else{ 
  RZ(a=vi(a)); an=AN(a); m=1;
  GA(y,INT,an+r,1,0); v=AV(y);
  ICPY(v,AV(a),an); ICPY(v+an,AS(w)+wr-r,r);
 }
 R ar==acr&&wr==wcr?reshape(y,w):irs2(y,w,0L,m,wcr,jtreshape);
}    /* a $"r w */

#if SY_64
#define EXPAND(T)  \
  {T*u=(T*)wv,*v=(T*)zv,x;                                                \
   mvc(sizeof(T),&x,k,jt->fillv);                                         \
   DO(an, if(*av++){ASSERT(wx>(C*)u,EVLENGTH); *v++=*u++;}else *v++=x;);  \
   wv=(C*)u;                                                              \
  }
#else
#define EXPAND(T)  \
  {T*u=(T*)wv,*v=(T*)zv,x;                                                                       \
   mvc(sizeof(T),&x,k,jt->fillv);                                                                \
   for(i=0;i<q;++i)switch(*au++){                                                                \
    case B0000:                              *v++=x;    *v++=x;    *v++=x;    *v++=x;    break;  \
    case B0001: ASSERT(wx>  (C*)u,EVLENGTH); *v++=x;    *v++=x;    *v++=x;    *v++=*u++; break;  \
    case B0010: ASSERT(wx>  (C*)u,EVLENGTH); *v++=x;    *v++=x;    *v++=*u++; *v++=x;    break;  \
    case B0011: ASSERT(wx>1+(C*)u,EVLENGTH); *v++=x;    *v++=x;    *v++=*u++; *v++=*u++; break;  \
    case B0100: ASSERT(wx>  (C*)u,EVLENGTH); *v++=x;    *v++=*u++; *v++=x;    *v++=x;    break;  \
    case B0101: ASSERT(wx>1+(C*)u,EVLENGTH); *v++=x;    *v++=*u++; *v++=x;    *v++=*u++; break;  \
    case B0110: ASSERT(wx>1+(C*)u,EVLENGTH); *v++=x;    *v++=*u++; *v++=*u++; *v++=x;    break;  \
    case B0111: ASSERT(wx>2+(C*)u,EVLENGTH); *v++=x;    *v++=*u++; *v++=*u++; *v++=*u++; break;  \
    case B1000: ASSERT(wx>  (C*)u,EVLENGTH); *v++=*u++; *v++=x;    *v++=x;    *v++=x;    break;  \
    case B1001: ASSERT(wx>1+(C*)u,EVLENGTH); *v++=*u++; *v++=x;    *v++=x;    *v++=*u++; break;  \
    case B1010: ASSERT(wx>1+(C*)u,EVLENGTH); *v++=*u++; *v++=x;    *v++=*u++; *v++=x;    break;  \
    case B1011: ASSERT(wx>2+(C*)u,EVLENGTH); *v++=*u++; *v++=x;    *v++=*u++; *v++=*u++; break;  \
    case B1100: ASSERT(wx>1+(C*)u,EVLENGTH); *v++=*u++; *v++=*u++; *v++=x;    *v++=x;    break;  \
    case B1101: ASSERT(wx>2+(C*)u,EVLENGTH); *v++=*u++; *v++=*u++; *v++=x;    *v++=*u++; break;  \
    case B1110: ASSERT(wx>2+(C*)u,EVLENGTH); *v++=*u++; *v++=*u++; *v++=*u++; *v++=x;    break;  \
    case B1111: ASSERT(wx>3+(C*)u,EVLENGTH); *v++=*u++; *v++=*u++; *v++=*u++; *v++=*u++; break;  \
   }                                                                                             \
   if(r){av=(B*)au; DO(r, if(*av++){ASSERT(wx>(C*)u,EVLENGTH); *v++=*u++;}else *v++=x;);}        \
   wv=(C*)u;                                                                                     \
  }
#endif

F2(jtexpand){A z;B*av;C*wv,*wx,*zv;I an,*au,i,k,p,q,r,wc,wk,wn,wt,zn;
 RZ(a&&w);
 if(!(B01&AT(a)))RZ(a=cvt(B01,a));
 ASSERT(1==AR(a),EVRANK);
 RZ(w=setfv(w,w)); 
 if(!AR(w))R from(a,take(num[-2],w));
 av=BAV(a); an=AN(a); q=an/SZI; r=an%SZI; au=(I*)av;
 wv=CAV(w); wn=AN(w); wc=aii(w); wt=AT(w); k=bp(wt); wk=k*wc; wx=wv+wk**AS(w);
 RE(zn=mult(an,wc));
 GA(z,wt,zn,AR(w),AS(w)); *AS(z)=an; zv=CAV(z);
 switch(wk){
  case sizeof(C): EXPAND(C); break;
  case sizeof(S): EXPAND(S); break;
  case sizeof(I): EXPAND(I); break;
  default:  
   mvc(k*zn,zv,k,jt->fillv); 
   for(i=p=0;i<an;++i)
    if(*av++)p+=wk; 
    else{if(p){ASSERT(wx>=wv+p,EVLENGTH); MC(zv,wv,p); wv+=p; zv+=p; p=0;} zv+=wk;}
   if(p){ASSERT(wx>=wv+p,EVLENGTH); MC(zv,wv,p); wv+=p;}
 }
 ASSERT(wx==wv,EVLENGTH);
 R z;
}    /* a&#^:_1 w or a&#^:_1!.f w */