- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
RZ(z=tail(w)); k=AN(z)<<bplg(AT(z)); // k=length of input cell in bytes
// fill in the shape, offset, and item-count of the virtual block
AN(a)=AN(z); AK(a)+=(n-1)*k; MCISH(AS(a),AS(z),r-1); // make the virtual block look like the tail, except for the offset. We start out pointing
// to the last item; the pointer is unused in the first iteration, and we then back up to the second-last item, which is the first one we
// process as a
#define ZZPOPNEVER 1 // we mustn't TPOP after copying the result atoms, because they are reused. This will leave the memory used for type-conversions unclaimed.
// if we implement the annulment of tpop pointers, we should use that to hand-free results that have been converted
// We have to dance a bit for BOXATOP verbs, because the result comes back unboxed, but it has to be put into a box
// to be fed into the next iteration. This is still a saving, because we can use the same box to point to each successive result.
// Exception: if the reusable box gets incorporated, it is no longer reusable and must be reallocated. We will use the original z box,
// which will NEVER be virtual because it is an atom whenever BOXATOP is set, as the starting pointer to the prev boxed result
A boxedz = z; z=(state&ZZFLAGBOXATOP)?AAV(z)[0]:z; // init current pointer for the temp box; if BOXATOP, use >{:y as the first (to-be-boxed) result
#define ZZDECL
#define ZZSTARTATEND 1 // build result from bottom up
#include "result.h"
ZZPARMS(1,n,2)
#define ZZINSTALLFRAME(optr) *optr++=n;
AD * RESTRICT zz=0;
for(i=0;i<n;++i){ // loop through items, noting that the first is the tail itself
if(i){RZ(z=CALL2(f2,a,z,fs));} // apply the verb to the arguments (except the first time)
#define ZZBODY
#include "result.h"
// If BOXATOP, we need to reinstate the boxing around z for the next iteration.
if(state&ZZFLAGBOXATOP){
// If boxedz itself has been incorporated into the result, we have to reallocate it. We don't need the usual check for z==boxedz, because we know we INCORPed z into
// the boxed result, so if it was the same as boxedz, the usecount of boxedz was incremented then
if(!ACIPISOK(boxedz))GAT0(boxedz,BOX,1,0); // reallocate boxedz if needed
AAV(boxedz)[0]=z; z=boxedz; // point boxedz to the previous result, and make that the new argument for next time
}
// if result happens to be the same virtual block that we passed in, we have to clone it before we change the pointer
else if(a==z){RZ(z=virtual(z,0,AR(a))); AN(z)=AN(a); MCISH(AS(z),AS(a),r-1);}
AK(a)-=k; // back up to next input
}
A jtscansp(J jt,A w,A self,AF sf){A e,ee,x,z;B*b;I f,m,j,r,t,wr;P*wp,*zp;
wr=AR(w); r=(RANKT)jt->ranks; r=wr<r?wr:r; RESETRANK; f=wr-r;
wp=PAV(w); e=SPA(wp,e); RZ(ee=over(e,e));
if(!equ(ee,CALL1(sf,ee,self))){
RZ(x=denseit(w));
R IRS1(x,self,r,sf,z);
}else{
RZ(b=bfi(wr,SPA(wp,a),1));
if(r&&b[f]){b[f]=0; RZ(w=reaxis(ifb(wr,b),w));}
j=f; m=0; DQ(wr-f, m+=!b[j++];);
}
wp=PAV(w); e=SPA(wp,e); x=SPA(wp,x);
RZ(x=IRS1(x,self,m,sf,z));
t=maxtype(AT(e),AT(x)); RZ(e=cvt(t,e)); if(TYPESNE(t,AT(x)))RZ(x=cvt(t,x));
GASPARSE(z,STYPE(t),1,wr+!m,AS(w)); if(!m)*(wr+AS(z))=1;
zp=PAV(z);
SPB(zp,e,e);
SPB(zp,x,x);
SPB(zp,i,ca(SPA(wp,i)));
SPB(zp,a,ca(SPA(wp,a)));
R z;
} /* f/\"r or f/\."r on sparse w */
static DF1(jtsscan){A y,z;I d,f,m,n,r,t,wn,wr,*ws,wt;
RZ(w);F1PREFIP;
wt=AT(w);
if(SPARSE&wt)R scansp(w,self,jtsscan);
wn=AN(w); wr=AR(w); r=(RANKT)jt->ranks; r=wr<r?wr:r; f=wr-r; ws=AS(w); RESETRANK;
PROD(m,f,ws); PROD1(d,r-1,f+ws+1); n=r?ws[f]:1; // will not be used if WN==0, so PROD ok. n is # items along the selected rank
y=FAV(self)->fgh[0]; // y is f/
if(((n-2)|(wn-1))<0){if(vaid(FAV(y)->fgh[0])){R r?RETARG(w):reshape(over(shape(w),num[1]),w);}else R IRS1(w,self,r,jtsuffix,z);} // if empty arg, or just 1 cell in selected axis, convert to f/\ which handles the short arg
//