Skip to content

Commit c43438d

Browse files
committed
Support ($,)!.n allow _ in x of x $ y, and !.v for it
1 parent e3ab638 commit c43438d

File tree

6 files changed

+107
-16
lines changed

6 files changed

+107
-16
lines changed

jsrc/cv.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,19 @@ static DF1(jtfitpp1){DECLFG;A z;
6262
static DF1(jtfitf1){V*sv=FAV(self); A z; R df1(z, w,fit(fix(sv->fgh[0],zeroionei(0)),sv->fgh[1]));} // ?? noun~!.n
6363
static DF2(jtfitf2){V*sv=FAV(self); A z; R df2(z,a,w,fit(fix(sv->fgh[0],zeroionei(0)),sv->fgh[1]));}
6464

65-
// Fit conjunction u!.n
65+
// Fit conjunction u!.v
6666
// Preserve IRS1/IRS2 from u in result verb (exception: CEXP)
6767
// Preserve VISATOMIC1 from u (applies only to numeric atomic ops)
6868
// Preserve comparison-combination flags for tolerance fit, in case this is a fit-allowing primitive that uses them
6969
F2(jtfit){F2PREFIP;A f;C c;I k,l,m,r;V*sv;
70-
ASSERTVN(a,w); // a must be a verb, w a noun
71-
sv=FAV(a); m=sv->mr; l=lrv(sv); r=rrv(sv);
70+
// ASSERTVN(a,w); // a must be a verb, w a noun
71+
ASSERT(AT(a)&VERB,EVDOMAIN) // a must be a verb
7272
A z; fdefallo(z)
73-
I cno=0;
74-
switch(sv->id){I wval;
73+
sv=FAV(a); m=sv->mr; l=lrv(sv); r=rrv(sv);
74+
if(likely(!(AT(w)&VERB))){ // is v a noun?
75+
// Noun v.
76+
I cno=0;
77+
switch(sv->id){I wval;
7578
case CIOTA: ++cno; // i.!.1 supported only in viavx.c
7679
case CSLDOT: case CSLDOTDOT: ++cno; case CLE: case CLT: case CGE: case CGT: case CNE: case CEQ: ++cno;
7780
case CMATCH: case CEPS: case CICO: case CNUB: case CSTAR:
@@ -92,20 +95,26 @@ F2(jtfit){F2PREFIP;A f;C c;I k,l,m,r;V*sv;
9295
case CPOLY:
9396
ASSERT(AT(w)&NUMERIC,EVDOMAIN);
9497
fdeffill(z,0L,CFIT,VERB,jtvalenceerr,jtfitpoly2,a,w,0L,VFLAGNONE,m,l,r) RETF(z); // p.!.f
98+
99+
case CHOOK: // only ($,)
100+
if(sv->valencefns[1]==jtreshape)goto fillreshape;
101+
break;
95102
case CPOWOP: // support for #^:_1!.n
96103
if(sv->fgh[1]!=num(-1))R jtfitct(jt,a,w,0,z);
97104
f=sv->fgh[0]; c=ID(f);
98105
if(c==CPOUND){ASSERT(!AR(w),EVRANK); fdeffill(z,0L,CFIT,VERB,jtvalenceerr,jtfitfill2,a,w,0L,VFLAGNONE,m,l,r) RETF(z);} // #^:_1!.f
99106
ASSERT(c==CAMP,EVDOMAIN);
100107
f=FAV(f)->fgh[1]; ASSERT(CPOUND==ID(f),EVDOMAIN);
101-
// fall through for x&#^:_1!.f
102-
// fill atoms:
108+
// fall through for x&#^:_1!.f
109+
// fill atoms:
103110
case CPOUND: case CTAKE: case CTAIL: case CCOMMA: case CCOMDOT: case CLAMIN: case CRAZE:
104111
ASSERT(!AR(w),EVRANK); /* fall thru */
105112
case CROT: case CDOLLAR: // these allow an empty array
113+
fillreshape:;
106114
ASSERT(1>=AR(w),EVRANK);
107115
ASSERT(!AR(w)||!AN(w),EVLENGTH);
108-
fdeffill(z,0L,CFIT,VERB,jtfitfill1,jtfitfill2,a,w,0L,sv->flag&(VIRS1|VIRS2|VJTFLGOK1|VJTFLGOK2|VASGSAFE),m,l,r) RETF(z); // ^!.f
116+
fdeffill(z,0L,CFIT,VERB,jtfitfill1,jtfitfill2,a,w,0L,sv->flag&(VIRS1|VIRS2|VJTFLGOK1|VJTFLGOK2|VASGSAFE),m,l,r) RETF(z); // various allowing empty fill
117+
109118
case CTHORN:
110119
RE(w=sc(k=i0(w)));
111120
ASSERT(0<k,EVDOMAIN);
@@ -117,7 +126,14 @@ F2(jtfit){F2PREFIP;A f;C c;I k,l,m,r;V*sv;
117126
case CTILDE: // noun~!.n - what in the world is that?
118127
ASSERT(NOUN&AT(sv->fgh[0]),EVDOMAIN);
119128
fdeffill(z,0L,CFIT,VERB,jtfitf1,jtfitf2,a,w,0L,VFLAGNONE,m,l,r) RETF(z);
120-
default:
121-
ASSERT(0,EVDOMAIN);
122-
}}
129+
// other cases continue on to error
130+
}
131+
}else{
132+
// v is a verb. Supported now only in $[!.n]!.v or ($,)[!.n]!.v
133+
AF rtn1=sv->valencefns[1]; if(rtn1==jtfitfill2)rtn1=FAV(sv->fgh[0])->valencefns[1]; // what routine will process? (if fit, look back to underlying function)
134+
if(rtn1==jtreshape||rtn1==jtreitem)
135+
fdeffill(z,0L,CFIT,VERB,jtvalenceerr,jtreshapeblankfn,a,w,0L,sv->flag&(VIRS1|VIRS2|VJTFLGOK1|VJTFLGOK2|VASGSAFE),m,l,r) FAV(z)->localuse.lu1.fittype=rtn1==jtreitem; RETF(z); // fittype tells whether ($,) or $
136+
}
137+
ASSERT(0,EVDOMAIN);
138+
}
123139

jsrc/je.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,7 @@ extern DF2(jtpolymult);
652652
extern DF2(jtpowop);
653653
extern DF2(jtrazecut0);
654654
extern DF2(jtrazecut2);
655+
extern DF2(jtreshapeblankfn);
655656
extern DF2(jtrollk);
656657
extern F2(jtrollksub);
657658
extern DF2(jtrollkx);

jsrc/jtype.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1084,7 +1084,7 @@ typedef struct {
10841084
A cachedref; // for namerefs ('name'~), the cached value, or 0 if not cached
10851085
AF fork2hfn; // for dyad fork that is NOT a comparison combination or jtintersect, the function to call to process h (might be in h@][)
10861086
I forcetask; // for t., the flags extracted from n. Bits 0-7=thread pool; bit 8=worker thread only
1087-
I fittype; // for u!.t where t is a code, its value is stored here in the CFIT block
1087+
I fittype; // for u!.t where t is a code, its value is stored here in the CFIT block; for $!.v, 0 if the ultimate routine is ($,), 1 if $
10881088
I1 srank[4]; // for RANK conj, the signed ranks. srank[3] is nonzero if the given rank was floating-point - means 'don't combine'
10891089
UI mrecip; // for u m. n m&|@^ and m&|@(n&^), the reciprocal of m, with binary point above 2^BW
10901090
S foreignmn[2]; // in m!:n, the arguments

jsrc/vf.c

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,14 +261,28 @@ 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
261261
R z;
262262
} /* a ($,)"wcr w for sparse w and scalar or vector a */
263263

264+
// x is floating-point left side of x $ y, w is right side. Result is INT x, but if x contains _, replace _ with the number needed to use up y exactly.
265+
// Give rndfn a chance to adjust the number. nlens is #axes before inner cell: wcr for ($,) 1 for $ wcr is cell-rank of w, if "r given
266+
static A jtreshapeblank(J jt, A a, A w, A rndfn, I nlens, I wcr){
267+
RZ(a=vib(a)); RZ(a=mkwris(a)) // convert to int, converting _ to IMAX; make it writable since we will change _
268+
I upos=IMAX, xprod=1; DO(AN(a), I xval=IAV(a)[i]; I nupos=xval==IMAX?i:upos; xval=xval==IMAX?1:xval; ASSERT(nupos<=upos,EVDOMAIN) upos=nupos; DPMULD(xprod,xval,xprod,ASSERT(0,EVLIMIT));) // multiple non-_, error if overflow of >1 _
269+
if(upos==IMAX)R a; // if x didn't contain _, just use it as is
270+
ASSERT(xprod!=0,EVDOMAIN); // if result is empty, we cannot calculate a value
271+
I nw; PRODX(nw,nlens,AS(w)+AR(w)-wcr,1) // calculate # cells in a wcr-cell of w: use all axes or just the first
272+
A nblank; df1(nblank,divide(sc(nw),sc(xprod)),rndfn); RZ(nblank); // rndfn */ (x-._) % */ $`#@.isitem y
273+
ASSERT(AR(nblank)==0,EVRANK) if(!(AT(nblank)&INT))RZ(nblank=cvt(INT,nblank)) // nblank must be stomic
274+
IAV(a)[upos]=IAV(nblank)[0]; R a; // replace _ with calculated value and return new x
275+
}
276+
264277
F2(jtreshape){A z;B filling;C*wv,*zv;I acr,ar,c,k,m,n,p,q,r,*s,t,* RESTRICT u,wcr,wf,wr,* RESTRICT ws,zn;
265278
F2PREFIP;
266279
ARGCHK2(a,w);
267280
ar=AR(a); acr=jt->ranks>>RANKTX; acr=ar<acr?ar:acr;
268281
wr=AR(w); wcr=(RANKT)jt->ranks; wcr=wr<wcr?wr:wcr; wf=wr-wcr; ws=AS(w); RESETRANK;
269282
if((I )(1<acr)|(I )(acr<ar)){z=rank2ex(a,w,DUMMYSELF,MIN(acr,1),wcr,acr,wcr,jtreshape); PRISTCLRF(w) RETF(z);} // multiple cells - must lose pristinity
270283
// now a is an atom or a list. w can have any rank
271-
RZ(a=vip(a)); r=AN(a); u=AV(a); // r=length of a u->values of a
284+
if(unlikely(AT(a)&FL))RZ(a=jtreshapeblank(jt,a,w,ds(CRIGHT),wcr,wcr)) else RZ(a=vip(a)); // convert a to integer & audit; if FL, also check for _ and handle
285+
r=AN(a); u=AV(a); // r=length of a u->values of a
272286
if(unlikely(ISSPARSE(AT(w)))){RETF(reshapesp(a,w,wf,wcr));}
273287
PRODX(m,r,u,1) // m=*/a (#atoms in result) c=#cells of w n=#atoms/cell of w
274288
CPROD(,c,wf,ws); CPROD(,n,wcr,wf+ws);
@@ -311,13 +325,30 @@ F2(jtreitem){A y,z;I acr,an,ar,r,*v,wcr,wr;
311325
fauxblockINT(yfaux,4,1);
312326
if(1>=wcr)y=a; // y is atom or list: $ is the same as ($,)
313327
else{ // rank y > 1: append the shape of an item of y to x
314-
RZ(a=vi(a)); an=AN(a); acr=1; // if a was an atom, now it is a list
328+
// obsolete RZ(a=vi(a));
329+
if(unlikely(AT(a)&FL))RZ(a=jtreshapeblank(jt,a,w,ds(CRIGHT),MIN(1,wcr),wcr)) else RZ(a=vip(a)); // convert a to integer & audit; if FL, also check for _ and handle
330+
an=AN(a); acr=1; // if a was an atom, now it is a list
315331
fauxINT(y,yfaux,an+r,1) v=AV(y);
316332
MCISH(v,AV(a),an); MCISH(v+an,AS(w)+wr-r,r);
317333
}
318-
R wr==wcr?jtreshape(jtinplace,y,w):IRS2(y,w,0L,acr,wcr,jtreshape,z); // Since a has no frame, we dont have to check agreement
334+
R wr==wcr?jtreshape(jtinplace,y,w):IRS2(y,w,0L,acr,wcr,jtreshape,z); // Since a has no frame, we don't have to check agreement
319335
} /* a $"r w */
320336

337+
// x $[!.n]!.v y or x ($,)[!.n]!.v y which uses fn v if needed to resolve _ in x
338+
DF2(jtreshapeblankfn){I acr,ar,r,wcr,wr;
339+
F2PREFIP;
340+
ARGCHK2(a,w);
341+
ar=AR(a); acr=jt->ranks>>RANKTX; acr=ar<acr?ar:acr;
342+
wr=AR(w); wcr=(RANKT)jt->ranks; wcr=wr<wcr?wr:wcr; RESETRANK;
343+
if((I )(1<acr)|(I )(acr<ar)){A z=rank2ex(a,w,DUMMYSELF,MIN(acr,1),wcr,acr,wcr,jtreshapeblankfn); PRISTCLRF(w) RETF(z);} // multiple cells - must lose pristinity
344+
A fs=FAV(self)->fgh[0]; AF reshapefn=FAV(fs)->valencefns[1]; // next routine to call, $ ($,) or !.n
345+
if(likely(AT(a)&FL)){ // if there might be _, check for it
346+
I nlens=FAV(self)->localuse.lu1.fittype?1:wcr; nlens=wcr<nlens?wcr:nlens; // # axes to use for counting result cells: the w-cell, or 1 item thereof
347+
RZ(a=jtreshapeblank(jt,a,w,FAV(self)->fgh[1],nlens,wcr)) // replace the blank, applying function in g
348+
}
349+
RETF((*reshapefn)(jtinplace,a,w,fs)) // do the reshape, with _ replaced
350+
}
351+
321352
#define EXPAND(T) \
322353
{T*u=(T*)wv,*v=(T*)zv,x; \
323354
mvc(sizeof(T),&x,k,jt->fillv); \

test/g210.ijs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,49 @@ NB. x$!.f y -------------------------------------------------------------
422422
'domain error' -: 9 3 $!.(<4) etx s:@<"0 'eleemosynary'
423423
'domain error' -: 9 3 $!.(<4) etx i.2 3
424424

425+
NB. x $ y where x contains _
426+
(1 $ 2) -: _ $ 2
427+
(1 $ 2) -: _ $ ,2
428+
(3 $ 2 3 4) -: _ $ 2 3 4
429+
(2 $ i. 2 3 4) -: _ $ i. 2 3 4
430+
(3 2 $ i. 6 3) -: _ 2 $ i. 6 3
431+
(2 3 $ i. 6 3) -: 2 _ $ i. 6 3
432+
(2 1 3 $ i. 6 3) -: 2 _ 3 $ i. 6 3
433+
(1 $"1 0 i. 6 3) -: _ $"1 0 i. 6 3
434+
(3 $"1 1 i. 6 3) -: _ $"1 1 i. 6 3
435+
(3 2 $"1 1 i. 3 6) -: _ 2 $"1 1 i. 3 6
436+
(3 $"1 2 i. 6 3 5) -: _ $"1 2 i. 6 3 5
437+
(4 2 $"1 2 i. 6 8 5) -: 4 _ $"1 2 i. 6 8 5
438+
439+
(1 ($,) 2) -: _ ($,) 2
440+
(1 ($,) 2) -: _ ($,) ,2
441+
(3 ($,) 2 3 4) -: _ ($,) 2 3 4
442+
(24 ($,) i. 2 3 4) -: _ ($,) i. 2 3 4
443+
(9 2 ($,) i. 6 3) -: _ 2 ($,) i. 6 3
444+
(2 9 ($,) i. 6 3) -: 2 _ ($,) i. 6 3
445+
(2 3 3 ($,) i. 6 3) -: 2 _ 3 ($,) i. 6 3
446+
(1 ($,)"1 0 i. 6 3) -: _ ($,)"1 0 i. 6 3
447+
(3 ($,)"1 1 i. 6 3) -: _ ($,)"1 1 i. 6 3
448+
(3 2 ($,)"1 1 i. 3 6) -: _ 2 ($,)"1 1 i. 3 6
449+
(15 ($,)"1 2 i. 6 3 5) -: _ ($,)"1 2 i. 6 3 5
450+
(4 10 ($,)"1 2 i. 6 8 5) -: 4 _ ($,)"1 2 i. 6 8 5
451+
452+
'domain error' -: _ 2 $ etx i. 13
453+
'limit error' -: _ ($,)"2 etx i. 0 1e15 1e15
454+
'domain error' -: _ 0 $ etx i. 10
455+
'domain error' -: _ _ 1 $ etx i. 10
456+
457+
NB. x $!.v y
458+
(9 2 ($,) i. 6 3) -: _ 2 ($,)!.<. i. 6 3
459+
(7 2 ($,) i. 5 3) -: _ 2 ($,)!.<. i. 5 3
460+
(8 2 ($,) i. 5 3) -: _ 2 ($,)!.>. i. 5 3
461+
'domain error' -: _ 2 ($,)!.] etx i. 5 3
462+
(9 2 ($,)!.99 i. 6 3) -: _ 2 ($,)!.99!.<. i. 6 3
463+
(7 2 ($,)!.99 i. 5 3) -: _ 2 ($,)!.99!.<. i. 5 3
464+
(8 2 ($,)!.99 i. 5 3) -: _ 2 ($,)!.99!.>. i. 5 3
465+
466+
467+
425468
4!:55 ;:'adot1 adot2 sdot0 b f res rk s t ya xa yb yc'
426469
randfini''
427470

test/g231.ijs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ _2 3 (|."1 2 -: rot"1 2) j./?2 2 3 7$1000
404404
NB. Inplace if fill
405405
a =: i. 1e6
406406
5000 > 7!:2 'a =: 5 |.!.0 a'
407-
a =. i. 100 100 100
407+
a =: i. 100 100 100
408408
5000 > 7!:2 'a =: 5 6 |.!.0 a'
409409
5000 > 7!:2 'a =: 5 6 7 |.!.0 a'
410410

0 commit comments

Comments
 (0)