# HG changeset patch # User Jordi GutiƩrrez Hermoso # Date 1385398590 18000 # Node ID e0bbaa717f4120952bc3b0eb81c5e712752a9c1e lol J diff --git a/a.c b/a.c new file mode 100644 --- /dev/null +++ b/a.c @@ -0,0 +1,163 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Adverbs */ + +#include "j.h" + + +static DF1(swap1){DECLF; R jt->rank?irs2(w,w,fs,jt->rank[1],jt->rank[1],f2):CALL2(f2,w,w,fs);} +static DF2(swap2){DECLF; R jt->rank?irs2(w,a,fs,jt->rank[1],jt->rank[0],f2):CALL2(f2,w,a,fs);} + +F1(jtswap){A y;C*s;I n; + RZ(w); + if(VERB&AT(w))R ADERIV(CTILDE,swap1,swap2,RMAX,rr(w),lr(w)); + else{ + if(C2T&AT(w))RZ(w=cvt(LIT,w)) else ASSERT(LIT&AT(w),EVDOMAIN); + ASSERT(1>=AR(w),EVRANK); + n=AN(w); s=CAV(w); + ASSERT(vnm(n,s),EVILNAME); + RZ(y=nfs(AN(w),CAV(w))); + R nameref(y); +}} + + +static B booltab[64]={ + 0,0,0,0, 0,0,0,1, 0,0,1,0, 0,0,1,1, 0,1,0,0, 0,1,0,1, 0,1,1,0, 0,1,1,1, + 1,0,0,0, 1,0,0,1, 1,0,1,0, 1,0,1,1, 1,1,0,0, 1,1,0,1, 1,1,1,0, 1,1,1,1, +}; + +static DF2(jtbdot2){R from(plus(duble(cvt(B01,a)),cvt(B01,w)),VAV(self)->h);} + +static DF1(jtbdot1){R bdot2(zero,w,self);} + +static DF1(jtbasis1){DECLF;A z;D*x;I j;V*v; + PREF1(jtbasis1); + RZ(w=vi(w)); + switch(*AV(w)){ + case 0: + GA(z,FL,3,1,0); x=DAV(z); v=VAV(fs); + j=v->mr; x[0]=j<=-RMAX?-inf:j>=RMAX?inf:j; + j=v->lr; x[1]=j<=-RMAX?-inf:j>=RMAX?inf:j; + j=v->rr; x[2]=j<=-RMAX?-inf:j>=RMAX?inf:j; + R pcvt(INT,z); + case -1: R lrep(inv (fs)); + case 1: R lrep(iden(fs)); + default: ASSERT(0,EVDOMAIN); +}} + +F1(jtbdot){A b,h=0;I j,n,*v; + RZ(w); + if(VERB&AT(w))R ADERIV(CBDOT, jtbasis1,0L, 0,0,0); + RZ(w=vi(w)); + n=AN(w); v=AV(w); + if(1==n){j=*v; ASSERT(-16<=j&&j<=34,EVINDEX);} + else DO(n, j=*v++; ASSERT(-16<=j&&j<16,EVINDEX);); + if(1!=n||j<16){ + GA(b,B01,64,2,0); *AS(b)=16; *(1+AS(b))=4; MC(AV(b),booltab,64L); + RZ(h=cant2(IX(AR(w)),from(w,b))); + R fdef(CBDOT,VERB, jtbdot1,jtbdot2, w,0L,h, 0L, RMAX,0L,0L); + }else switch(j){ + default: ASSERT(0,EVNONCE); + case 16: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise0000, w,0L,0L, VIRS2, 0L,0L,0L); + case 17: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise0001, w,0L,0L, VIRS2, 0L,0L,0L); + case 18: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise0010, w,0L,0L, VIRS2, 0L,0L,0L); + case 19: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise0011, w,0L,0L, VIRS2, 0L,0L,0L); + case 20: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise0100, w,0L,0L, VIRS2, 0L,0L,0L); + case 21: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise0101, w,0L,0L, VIRS2, 0L,0L,0L); + case 22: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise0110, w,0L,0L, VIRS2, 0L,0L,0L); + case 23: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise0111, w,0L,0L, VIRS2, 0L,0L,0L); + case 24: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise1000, w,0L,0L, VIRS2, 0L,0L,0L); + case 25: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise1001, w,0L,0L, VIRS2, 0L,0L,0L); + case 26: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise1010, w,0L,0L, VIRS2, 0L,0L,0L); + case 27: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise1011, w,0L,0L, VIRS2, 0L,0L,0L); + case 28: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise1100, w,0L,0L, VIRS2, 0L,0L,0L); + case 29: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise1101, w,0L,0L, VIRS2, 0L,0L,0L); + case 30: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise1110, w,0L,0L, VIRS2, 0L,0L,0L); + case 31: R fdef(CBDOT,VERB, jtbitwise1,jtbitwise1111, w,0L,0L, VIRS2, 0L,0L,0L); + case 32: R ADERIV(CBDOT,jtbitwise1,jtbitwiserotate,0,0,0); + case 33: R ADERIV(CBDOT,jtbitwise1,jtbitwiseshift, 0,0,0); + case 34: R ADERIV(CBDOT,jtbitwise1,jtbitwiseshifta,0,0,0); +}} + + +/* The h parameter in self for u M. */ +/* 3 elememt boxed list */ +/* 0 - integer atom of # of entries in hash table */ +/* 1 - 2-column integer table of arguments */ +/* arguments are machine word integers */ +/* column 1 is right arg; column 1 is left arg */ +/* column 0 is IMIN for monad */ +/* 2 - box list of results corresp. to arguments */ +/* unused entries are set to 0 */ + +#if SY_64 +#define HIC(x,y) ((UI)x+10495464745870458733U*(UI)y) +#else +#define HIC(x,y) ((UI)x+2838338383U*(UI)y) +#endif + +static A jtmemoget(J jt,I x,I y,A self){A h,*hv,q;I*jv,k,m,*v; + h=VAV(self)->h; hv=AAV(h); + q=hv[1]; jv=AV(q); m=*AS(q); + k=HIC(x,y)%m; v=jv+2*k; while(IMIN!=*v&&!(y==*v&&x==v[1])){v+=2; if(v==jv+2*m)v=jv;} + R*(AAV(hv[2])+(v-jv)/2); +} + +static A jtmemoput(J jt,I x,I y,A self,A z){A*cv,h,*hv,q;I c,*jv,k,m,*mv,*v; + RZ(z); + c=AC(self); h=VAV(self)->h; hv=AAV(h); + q=hv[0]; mv= AV(q); + q=hv[1]; jv= AV(q); + q=hv[2]; cv=AAV(q); m=AN(q); + if(m<=2**mv){A cc,*cu=cv,jj;I i,*ju=jv,n=m,*u; + v=ptab; while(m>=*v)++v; m=*v; + RZ(jj=reshape(v2(m,2L),sc(IMIN))); jv= AV(jj); + GA(cc,BOX,m,1,0); cv=AAV(cc); + for(i=0,u=ju;imr,v->lr,v->rr); +} diff --git a/a.h b/a.h new file mode 100644 --- /dev/null +++ b/a.h @@ -0,0 +1,48 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Adverbs: Macros and Defined-Constants (for Adverbs and Conjunctions) */ + + +#define GAPPEND (I)0 +#define GINSERT (I)3 +#define GTRAIN (I)6 + +#define COMPOSE(c) ((c)==CAT||(c)==CATCO||(c)==CAMP||(c)==CAMPCO) + +#define CONJCASE(a,w) (2*!(VERB&AT(a))+!(VERB&AT(w))) +#define NN 3 /* NOUN NOUN */ +#define NV 2 /* NOUN VERB */ +#define VN 1 /* VERB NOUN */ +#define VV 0 /* VERB VERB */ + +#define DECLF V*sv=VAV(self);A fs=sv->f; \ + AF f1=fs?VAV(fs)->f1:0,f2=fs?VAV(fs)->f2:0 + +#define DECLG V*sv=VAV(self);A gs=sv->g; \ + AF g1=gs?VAV(gs)->f1:0,g2=gs?VAV(gs)->f2:0 + +#define DECLFG DECLF; A gs=sv->g; \ + AF g1=gs?VAV(gs)->f1:0,g2=gs?VAV(gs)->f2:0 + +#define DECLFGH DECLFG; A hs=sv->h; \ + AF h1=hs?VAV(hs)->f1:0,h2=hs?VAV(hs)->f2:0 + +#define PREF1(f) {I m=mr(self); F1RANK( m,f,self);} +#define PREF2(f) {I l=lr(self),r=rr(self); F2RANK(l,r,f,self);} + +#define AS1(f,exp) DF1(f){PROLOG;DECLF ;A z; PREF1(f); z=(exp); EPILOG(z);} +#define AS2(f,exp) DF2(f){PROLOG;DECLF ;A z; PREF2(f); z=(exp); EPILOG(z);} +#define CS1(f,exp) DF1(f){PROLOG;DECLFG;A z; PREF1(f); z=(exp); EPILOG(z);} +#define CS2(f,exp) DF2(f){PROLOG;DECLFG;A z; PREF2(f); z=(exp); EPILOG(z);} + +#define ADERIV(id,f1,f2,m,l,r) fdef(id,VERB,(AF)(f1),(AF)(f2),w,0L,0L,0L,(I)(m),(I)(l),(I)(r)) +#define CDERIV(id,f1,f2,m,l,r) fdef(id,VERB,(AF)(f1),(AF)(f2),a,w ,0L,0L,(I)(m),(I)(l),(I)(r)) + +#define ASSERTVV(a,w) RZ(a&&w); ASSERT(VERB&AT(a)&&VERB&AT(w),EVDOMAIN) +#define ASSERTVN(a,w) RZ(a&&w); ASSERT(VERB&AT(a)&&NOUN&AT(w),EVDOMAIN) +#define ASSERTNN(a,w) RZ(a&&w); ASSERT(NOUN&AT(a)&&NOUN&AT(w),EVDOMAIN) + +#define SCALARFN(id,w) (id==ID(w)&&!lr(w)&&!rr(w)) + +#define FIT0(c,v) (CFIT==v->id&&c==ID(v->f)&&equ(zero,v->g)) diff --git a/ab.c b/ab.c new file mode 100644 --- /dev/null +++ b/ab.c @@ -0,0 +1,182 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Adverbs: b. bitwise functions */ + +#include "j.h" +#include "ve.h" +#include "ar.h" + + +APFX(bw0000II, UI,UI,UI, BW0000) static APFX(bw0000CC, UC,UC,UC, BW0000) +APFX(bw0001II, UI,UI,UI, BW0001) static APFX(bw0001CC, UC,UC,UC, BW0001) +APFX(bw0010II, UI,UI,UI, BW0010) static APFX(bw0010CC, UC,UC,UC, BW0010) +APFX(bw0011II, UI,UI,UI, BW0011) static APFX(bw0011CC, UC,UC,UC, BW0011) +APFX(bw0100II, UI,UI,UI, BW0100) static APFX(bw0100CC, UC,UC,UC, BW0100) +APFX(bw0101II, UI,UI,UI, BW0101) static APFX(bw0101CC, UC,UC,UC, BW0101) +APFX(bw0110II, UI,UI,UI, BW0110) static APFX(bw0110CC, UC,UC,UC, BW0110) +APFX(bw0111II, UI,UI,UI, BW0111) static APFX(bw0111CC, UC,UC,UC, BW0111) +APFX(bw1000II, UI,UI,UI, BW1000) static APFX(bw1000CC, UC,UC,UC, BW1000) +APFX(bw1001II, UI,UI,UI, BW1001) static APFX(bw1001CC, UC,UC,UC, BW1001) +APFX(bw1010II, UI,UI,UI, BW1010) static APFX(bw1010CC, UC,UC,UC, BW1010) +APFX(bw1011II, UI,UI,UI, BW1011) static APFX(bw1011CC, UC,UC,UC, BW1011) +APFX(bw1100II, UI,UI,UI, BW1100) static APFX(bw1100CC, UC,UC,UC, BW1100) +APFX(bw1101II, UI,UI,UI, BW1101) static APFX(bw1101CC, UC,UC,UC, BW1101) +APFX(bw1110II, UI,UI,UI, BW1110) static APFX(bw1110CC, UC,UC,UC, BW1110) +APFX(bw1111II, UI,UI,UI, BW1111) static APFX(bw1111CC, UC,UC,UC, BW1111) + +/* see below */ /* see below */ +REDUCEPFX(bw0001insI, UI,UI, BW0001) static REDUCEPFX(bw0001insC, UC,UC, BW0001) +REDUCEPFX(bw0010insI, UI,UI, BW0010) static REDUCEPFX(bw0010insC, UC,UC, BW0010) +/* see below */ /* see below */ +REDUCEPFX(bw0100insI, UI,UI, BW0100) static REDUCEPFX(bw0100insC, UC,UC, BW0100) +/* see below */ /* see below */ +REDUCEPFX(bw0110insI, UI,UI, BW0110) static REDUCEPFX(bw0110insC, UC,UC, BW0110) +REDUCEPFX(bw0111insI, UI,UI, BW0111) static REDUCEPFX(bw0111insC, UC,UC, BW0111) +REDUCEPFX(bw1000insI, UI,UI, BW1000) static REDUCEPFX(bw1000insC, UC,UC, BW1000) +REDUCEPFX(bw1001insI, UI,UI, BW1001) static REDUCEPFX(bw1001insC, UC,UC, BW1001) +/* see below */ /* see below */ +REDUCEPFX(bw1011insI, UI,UI, BW1011) static REDUCEPFX(bw1011insC, UC,UC, BW1011) +/* see below */ /* see below */ +REDUCEPFX(bw1101insI, UI,UI, BW1101) static REDUCEPFX(bw1101insC, UC,UC, BW1101) +REDUCEPFX(bw1110insI, UI,UI, BW1110) static REDUCEPFX(bw1110insC, UC,UC, BW1110) +/* see below */ /* see below */ + + AHDRR(bw0000insI,UI,UI){I k=SZI*m*c/n; if(1wr; \ + DO(MIN(ar,wr), ASSERT(as[i]==ws[i],EVLENGTH);); \ + GA(z,INT,b?an:wn,MAX(ar,wr),b?as:ws); zv=(T*)AV(z); \ + if(!AN(z))R z; \ + if (ar==wr)DO(an, x=*av++; y=*wv++; *zv++=op(x,y); ) \ + else if(ar< wr)DO(an, x=*av++; DO(wn/an, y=*wv++; *zv++=op(x,y););) \ + else DO(wn, y=*wv++; DO(an/wn, x=*av++; *zv++=op(x,y););); \ + RE(0); R z; \ + } + +#if SY_64 +#define WLEN 64 +#else +#define WLEN 32 +#endif + +#define BWROT(x,y) (0>x ? (y>>(-x%WLEN))|(y<<(WLEN+(x%WLEN))) : (y<<(x%WLEN))|(y>>(WLEN-(x%WLEN))) ) +#define BWSHIFT(x,y) (0>x ? (x<=-WLEN?0:y>>-x) : (x>=WLEN?0:y<x ? (x<=-WLEN?(y<0?-1:0):y>>-x) : (x>=WLEN?0:y<f2,zero,w,self);} + + +static VF bwC[16]={bw0000CC,bw0001CC,bw0010CC,bw0011CC, bw0100CC,bw0101CC,bw0110CC,bw0111CC, + bw1000CC,bw1001CC,bw1010CC,bw1011CC, bw1100CC,bw1101CC,bw1110CC,bw1111CC}; + +static VF bwI[16]={bw0000II,bw0001II,bw0010II,bw0011II, bw0100II,bw0101II,bw0110II,bw0111II, + bw1000II,bw1001II,bw1010II,bw1011II, bw1100II,bw1101II,bw1110II,bw1111II}; + +/* a m b.&.(a.&i.) w */ +/* a m b.&.(a.i.]) w */ +/* m e. 16+i.16 */ + +DF2(jtbitwisechar){DECLFG;A*p,x,y,z;B b;I an,ar,*as,at,d,j,m,n,wn,wr,*ws,wt,zn;VF f; + RZ(a&&w); + d=SZI; + x=a; an=AN(a); ar=AR(a); as=AS(a); at=AT(a); + y=w; wn=AN(w); wr=AR(w); ws=AS(w); wt=AT(a); + if(!(an&&wn&&at&LIT&&wt&LIT))R from(df2(indexof(alp,a),indexof(alp,w),fs),alp); + b=ar<=wr; zn=b?wn:an; m=b?an:wn; n=zn/m; + ASSERT(!ICMP(as,ws,MIN(ar,wr)),EVLENGTH); + j=i0(VAV(fs)->f)-16; + GA(z,d==SZI?LIT:C2T,zn,MAX(ar,wr),b?ws:as); + if(1==n) {f=bwI[j]; m=(m+d-1)/d;} + else if(!ar||!wr||0==n%d){f=bwI[j]; n=(n+d-1)/d; p=b?&x:&y; RZ(*p=irs2(sc(d),*p,0L,0L,0L,jtrepeat));} + else f=bwC[j]; + f(jt,b,m,n,AV(z),AV(x),AV(y)); + *(zn+CAV(z))=0; + R z; +} + +/* compute z=: t{~ a.i.w if t=: c&(m b.) a. */ +/* http://www.jsoftware.com/jwiki/Essays/Bitwise_Functions_on_Charcters */ + +B jtbitwisecharamp(J jt,UC*t,I n,UC*wv,UC*zv){I p;UC c,i,j,*pv,s[256];VF f; + i=t[0]; j=t[255]; + if (i==0 ){c=j; f=bw0001II;} + else if(j==i ){c=i; f=bw0011II;} + else if(j==255 ){c=i; f=bw0111II;} + else if(j==255-i){c=i; f=bw0110II;} + else if(j==0 ){c=i; f=bw0010II;} + else if(i==255 ){c=j; f=bw1011II;} + else R 0; + pv=(UC*)&p; DO(SZI, pv[i]=c;); + f(jt,1,1L,256L/SZI,s,pv,AV(alp)); if(memcmp(s,t,256L))R 0; + f(jt,1,1L,(n+SZI-1)/SZI,zv,pv,wv); zv[n]=0; + R 1; +} + + +static VF bwinsC[16]={bw0000insC,bw0001insC,bw0010insC,bw0011insC, bw0100insC,bw0101insC,bw0110insC,bw0111insC, + bw1000insC,bw1001insC,bw1010insC,bw1011insC, bw1100insC,bw1101insC,bw1110insC,bw1111insC}; + +static VF bwinsI[16]={bw0000insI,bw0001insI,bw0010insI,bw0011insI, bw0100insI,bw0101insI,bw0110insI,bw0111insI, + bw1000insI,bw1001insI,bw1010insI,bw1011insI, bw1100insI,bw1101insI,bw1110insI,bw1111insI}; + +/* m b./&.(a.&i.) w */ +/* m b./&.(a.i.]) w */ +/* m e. 16+i.16 */ + +DF1(jtbitwiseinsertchar){A fs,z;I c,d=SZI,j,m,n,r,wn,wr;UC*u,*v,*wv,x,*zv;VF f; + RZ(w&&self); + wr=AR(w); c=wn=AN(w); n=wr?*AS(w):1; z=VAV(self)->f; fs=VAV(z)->f; + if(!(wn&&df)-16; f=bwinsC[j]; + if(1==wr)switch(j){ + case 0: R scc(0); + case 3: R scc(*wv); + case 5: R scc(*(wv+wn-1)); + case 10: x=*(wv+wn-1); R scc((UC)(wn%2?x:~x)); + case 12: R scc((UC)~*wv); + case 15: R scc((UC)255); + case 1: case 6: case 7: case 9: f=bwinsI[j]; c=n=n/d; + }else if(0==m%d){f=bwinsI[j]; c/=d;} + GA(z,LIT,m,wr-1,1+AS(w)); zv=CAV(z); + f(jt,1L,c,n,zv,wv); + if(1==wr){ + r=wn-n*d; u=wv+n*d; x=*zv; v=1+zv; + switch(j){ + case 1: DO(d-1, x=BW0001(x,*v); ++v;); DO(r, x=BW0001(x,*u); ++u;); break; + case 6: DO(d-1, x=BW0110(x,*v); ++v;); DO(r, x=BW0110(x,*u); ++u;); break; + case 7: DO(d-1, x=BW0111(x,*v); ++v;); DO(r, x=BW0111(x,*u); ++u;); break; + case 9: DO(d-1, x=BW1001(x,*v); ++v;); DO(r, x=BW1001(x,*u); ++u;); break; + } + *(I*)zv=0; *zv=x; + } + R z; +} diff --git a/af.c b/af.c new file mode 100644 --- /dev/null +++ b/af.c @@ -0,0 +1,99 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Adverbs: Fix */ + +#include "j.h" + + +F1(jtunname){A x;V*v; + RZ(w); + v=VAV(w); + if(CTILDE==v->id&&!jt->glock&&!(VLOCK&v->flag)){x=v->f; if(NAME&AT(x))R symbrd(x);} + R w; +} + +static B jtselfq(J jt,A w){A hs,*u;V*v; + RZ(w); + if(AT(w)&NOUN+NAME)R 0; + v=VAV(w); + switch(v->id){ + case CSELF: + R 1; + case CATDOT: + case CGRCO: + if(hs=v->h){u=AAV(hs); DO(AN(hs), if(selfq(u[i]))R 1;);} + R 0; + default: + if(v->f&&selfq(v->f))R 1; + if(v->g&&selfq(v->g))R 1; + if(v->h&&selfq(v->h))R 1; + } + R 0; +} /* 1 iff w contains $: */ + +static F2(jtfixa){A aa,f,g,h,wf,x,y,z=w;V*v; + RZ(a&&w); + if(NOUN&AT(w)||VFIX&VAV(w)->flag)R w; + v=VAV(w); f=v->f; g=v->g; h=v->h; wf=ds(v->id); aa=a==zero?num[3]:a; + if(!(f||g))R w; + switch(v->id){ + case CSLASH: + R df1(fixa(num[2],f),wf); + case CSLDOT: case CBSLASH: case CBSDOT: + R df1(fixa(one,f),wf); + case CAT: case CATCO: case CCUT: + R df2(fixa(one,f),fixa(aa,g),wf); + case CAMP: case CAMPCO: case CUNDER: case CUNDCO: + R df2(fixa(aa,f),fixa(one,g),wf); + case CCOLON: + R df2(fixa(one,f),fixa(num[2],g),wf); + case CADVF: + R hook(fixa(num[3],f),fixa(num[3],g)); + case CHOOK: + R hook(fixa(num[2],f),fixa(one,g)); + case CFORK: + f=fixa(aa,f); g=fixa(num[ID(f)==CCAP?1:2],g); h=fixa(aa,h); R folk(f,g,h); + case CATDOT: + case CGRCO: + RZ(f=every(every2(aa,h,0L,jtfixa),0L,jtaro)); + RZ(g=fixa(aa,g)); + R df2(f,g,wf); + case CIBEAM: + if(f)RZ(f=fixa(aa,f)); + if(g)RZ(g=fixa(aa,g)); + R f&&g ? (VDDOP&v->flag?df2(f,g,df2(head(h),tail(h),wf)):df2(f,g,wf)) : + (VDDOP&v->flag?df1(f, df2(head(h),tail(h),wf)):df1(f, wf)) ; + case CTILDE: + if(f&&NAME&AT(f)){ + RZ(y=sfn(0,f)); + if(all1(eps(box(y),jt->fxpath)))R w; + ASSERT(jt->fxi,EVLIMIT); + jt->fxpv[--jt->fxi]=y; + if(x=symbrdlock(f)){ + RZ(z=fixa(aa,x)); + if(a!=zero&&selfq(x))RZ(z=fixrecursive(a,z)); + } + jt->fxpv[jt->fxi++]=mtv; + RE(z); + ASSERT(AT(w)==AT(z)||AT(w)&NOUN&&AT(z)&NOUN,EVDOMAIN); + R z; + }else R df1(fixa(num[2],f),wf); + default: + if(f)RZ(f=fixa(aa,f)); + if(g)RZ(g=fixa(aa,g)); + R f&&g?df2(f,g,wf):f?df1(f,wf):w; +}} /* 0=a if fix names; 1=a if fix names only if does not contain $: */ + + +F1(jtfix){PROLOG;A z;I*rv=jt->rank; + RZ(w); + jt->rank=0; + RZ(jt->fxpath=reshape(sc(jt->fxi=(I)255),ace)); jt->fxpv=AAV(jt->fxpath); + if(LIT&AT(w)){ASSERT(1>=AR(w),EVRANK); RZ(w=nfs(AN(w),CAV(w)));} + ASSERT(AT(w)&NAME+VERB,EVDOMAIN); + RZ(z=fixa(zero,AT(w)&VERB?w:symbrdlock(w))); + if(AT(z)&VERB+ADV+CONJ){V*v=VAV(z); if(v->f){v->flag|=VFIX+VNAMED; v->flag^=VNAMED;}} + jt->rank=rv; jt->fxpath=0; + EPILOG(z); +} diff --git a/ai.c b/ai.c new file mode 100644 --- /dev/null +++ b/ai.c @@ -0,0 +1,381 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Adverbs: Inverse & Identity Functions */ + +#include "j.h" + + +static F1(jtinvamp); + +static B ip(A w,C c,C d){A f,g;V*v; + v=VAV(w); f=v->f; g=v->g; + R CSLASH==ID(f)&&c==ID(VAV(f)->f)&&d==ID(g); +} + +static B consf(A w){A f;C c; + c=ID(w); + if(c==CFCONS||c==CQQ&&(f=VAV(w)->f,NOUN&AT(f)))R 1; + R 0; +} /* 1 iff w is a constant function */ + +static F2(jtfong){A f;C c;V*v; + RZ(a&&w); + v=VAV(a); c=v->id; f=v->f; + R c==CRIGHT ? w : c==CFORK&&(NOUN&AT(f)||CCAP==ID(f)) ? folk(f,v->g,fong(v->h,w)) : folk(ds(CCAP),a,w); +} /* [: f g with simplifications */ + +static F1(jtinvfork){A f,fi,g,gi,h,k;B b,c;V*v; + RZ(w); + v=VAV(w); RZ(f=unname(v->f)); g=v->g; RZ(h=unname(v->h)); + if(CCAP==ID(f))R fong(inv(h),inv(g)); + c=1&&NOUN&AT(f); b=c||consf(f); + ASSERT(b!=consf(h),EVDOMAIN); + RZ(k=c?f:df1(zero,b?f:h)); + RZ(gi=inv(b?amp(k,g):amp(g,k))); + RZ(fi=inv(b?h:f)); + if(CAMP==ID(gi)){ + v=VAV(gi); + if (NOUN&AT(v->f))RZ(gi=folk(v->f, v->g, ds(CRIGHT))) + else if(NOUN&AT(v->g))RZ(gi=folk(v->g,swap(v->f),ds(CRIGHT))); + } + R fong(fi,gi); +} + +static DF1(jtexpandf){A f; RZ(w&&self); f=VAV(self)->f; R expand(VAV(f)->f,w);} + +static DF1(jtexpandg){A f,g,z;V*v; + RZ(w&&self); + f=VAV(self)->f; v=VAV(f); g=v->g; + jt->fill=VAV(g)->g; z=expand(v->f,w); jt->fill=0; + R z; +} + +static F2(jtdiag){I d,k,m,p,r,t,*v; + RZ(a&&w); + r=AR(w); t=AT(w); k=bp(t); + v=AS(w); m=0; DO(r, m=MIN(m,v[i]);); + v=AS(w)+r; p=1; d=0; DO(r, d+=p; p*=*--v;); + if(t!=AT(a))RZ(a=cvt(t,a)); + if(AR(a)){ + ASSERT(m==AN(a),EVLENGTH); + ASSERT(0,EVNONCE); + }else{ + ASSERT(0,EVNONCE); +}} + +static F1(jtbminv){A*wv,x,z=w;I i,j,m,r,*s,t=0,*u,**v,*y,wn,wr,*ws,wd; + RZ(w); + ASSERT(0,EVNONCE); + ASSERT(BOX&AT(w),EVDOMAIN); + wn=AN(w); wr=AR(w); ws=AS(w); wv=AAV(w); wd=(I)w*ARELATIVE(w); + if(1>=wr)R raze(w); + if(!wn)R iota(reshape(sc(wr),zero)); + GA(x,INT,wr,1,0); u=AV(x); memset(u,C0,wr*SZI); + GA(x,INT,wr,1,0); v=(I**)AV(x); + DO(wr, m=ws[i]; GA(x,INT,m,1,0); memset(v[i]=AV(x),CFF,m*SZI);); + for(i=0;ir||r==wr,EVRANK); + if(2>r)z=0; + else DO(wr, y=v[i]+u[i]; if(0>*y)*y=s[i]; else ASSERT(*y==s[i],EVLENGTH);); + j=wr; while(1){--j; ++u[j]; if(ws[j]>u[j])break; u[j]=0;} + } + if(!z){A f,h,*zv;I*hv; + GA(z,BOX,wn,2,ws); zv=AAV(z); + GA(h,INT,wr,1,0); hv=AV(h); + GA(f,t,1,1,0); RZ(f=filler(f)); memset(u,C0,wr*SZI); + for(i=0;iAR(x)){DO(wr, hv[i]=*(v[i]+u[i]);); RZ(zv[i]=diag(x,reshape(h,f)));} + j=wr-1; while(1){--j; ++u[j]; if(ws[j]>u[j])break; u[j]=0;} + }} + DO(wr, RZ(z=df1(z,slash(under(qq(ds(CCOMMA),sc(wr-i)),ds(COPE)))));); + R ope(z); +} /* <;.1 or <;.2 inverse on matrix argument */ + + +static F1(jtinvamp){A f,ff,g,h,*q,x,y;B nf,ng;C c,d,*yv;I n;V*u,*v; + RZ(w); + v=VAV(w); + f=v->f; nf=!!(NOUN&AT(f)); + g=v->g; ng=!!(NOUN&AT(g)); + h=nf?g:f; x=nf?f:g; c=ID(h); u=VAV(h); + switch(c){ + case CPLUS: R amp(negate(x),h); + case CSTAR: R amp(recip(x), h); + case CMINUS: R nf?w:amp(x,ds(CPLUS)); + case CDIV: R nf?w:amp(x,ds(CSTAR)); + case CROOT: R amp(ds(nf?CEXP:CLOG),x); + case CEXP: R ng&&equ(x,num[2])?ds(CROOT):amp(x,ds(nf?CLOG:CROOT)); + case CLOG: R nf?amp(x,ds(CEXP)):amp(ds(CROOT),x); + case CJDOT: R nf?atop(inv(ds(CJDOT)),amp(ds(CMINUS),x)):amp(ds(CMINUS),jdot1(x)); + case CRDOT: R nf?atop(inv(ds(CRDOT)),amp(ds(CDIV ),x)):amp(ds(CDIV ),rdot1(x)); + case CLBRACE: R nf?amp(pinv(x),h):amp(x,ds(CIOTA)); + case COBVERSE: ff=VAV(h)->g; R amp(nf?x:ff,nf?ff:x); + case CPDERIV: if(!AR(h))R ds(CPDERIV); + case CXCO: RE(n=i0(x)); ASSERT(n&&-3f,VERB&AT(ff))R invamp(amp(nf?ff:x,nf?x:ff)); + else{ff=unname(h); R invamp(amp(nf?x:ff,nf?ff:x));} + case CSCO: + ASSERT(nf,EVDOMAIN); + RE(n=i0(x)); ASSERT(n&&-6<=n&&n<=6,EVDOMAIN); + R amp(sc(-n),h); + case CUCO: + ASSERT(nf,EVDOMAIN); + RE(n=i0(x)); ASSERT(1<=n&&n<=4||7<=n&&n<=8,EVDOMAIN); + R amp(sc(1==n?2L:2==n?1L:3==n?4L:4==n?3L:7==n?8L:7L),h); + case CCANT: + ASSERT(nf,EVDOMAIN); + R obverse(eva(x,"] |:~ x C.^:_1 i.@#@$"),w); + case CPCO: + if(nf){ + RE(n=i0(x)); + switch(n){ + case -4: case 4: R amp(negate(x),h); + case -1: R ds(CPCO); + case 2: R obverse(eval("*/@(^/)\"2"),w); + case 3: R eval("*/"); + }} + break; + case CQCO: + if(nf){ + ASSERT(!AR(x),EVRANK); + R obverse(eval(all1(lt(x,zero))?"*/@(^/)\"2":"(p:@i.@# */ .^ ])\"1"),w); + } + break; + case CFIT: + ASSERT(nf&&(CPOUND==ID(VAV(g)->f)),EVDOMAIN); + ASSERT(1==AR(x),EVRANK); + R fdef(CPOWOP,VERB, jtexpandg,0L, w,num[-1],0L, 0L, RMAX,0L,0L); + case CPOUND: + ASSERT(nf,EVDOMAIN); + ASSERT(1==AR(x),EVRANK); + R fdef(CPOWOP,VERB, jtexpandf,0L, w,num[-1],0L, 0L, RMAX,0L,0L); + break; + case CPOWOP: + if(VGERL&u->flag){ff=*(1+AAV(u->h)); R amp(nf?x:ff,nf?ff:x);} + break; + case CCOMMA: + n=IC(x); + R obverse(1==n?ds(nf?CDROP:CCTAIL):amp(sc(nf?n:-n),ds(CDROP)),w); + case CBASE: + if(!nf)break; + R AR(x) ? amp(x,ds(CABASE)) : + obverse(evc(x,mag(x),"$&x@>:@(y&(<.@^.))@(1&>.)@(>./)@:|@, #: ]"),w); + case CBANG: + ASSERT(!AR(x),EVRANK); + ASSERT(all1(lt(zero,x)),EVDOMAIN); + GA(y,BOX,9,1,0); q=AAV(y); + q[0]=cstr("3 :'(-("); q[1]=q[3]=lrep(w); + q[2]=cstr("-y\"_)%1e_3&* "); q[4]=cstr("\"0 D:1 ])^:_["); + h=lrep(x); + if(nf){q[5]=over(over(h,cstr("&<@|@{:}")),over(h,cstr(",:"))); q[6]=over(h,cstr("%:y*!")); q[7]=h;} + else {q[5]=cstr("1>.{.@/:\"1|y-/(i.!])"); q[6]=h; q[7]=mtv;} + RE(q[8]=cstr("'")); RZ(y=raze(y)); + R obverse(eval(CAV(y)),w); + case CATOMIC: + if(ng){ASSERT(equ(x,nub(x)),EVDOMAIN); R obverse(atop(f,amp(x,ds(CIOTA))),w);} + case CCYCLE: + if(nf&&AR(x)<=(c==CCYCLE))R obverse(eva(w,"/:@x@(i.@#) { ]"),w); break; + case CDROP: + if(!(nf&&1>=AR(x)))break; + RZ(x=cvt(INT,x)); + RZ(y=eps(v2(-1L,1L),signum(x))); yv=CAV(y); + f=amp(mag(x),ds(CPLUS)); + g=1==AN(x)?ds(CPOUND):atop(amp(tally(x),ds(CTAKE)),ds(CDOLLAR)); + h=!yv[1]?f:atop(!yv[0]?ds(CMINUS):amp(negate(signum(x)),ds(CSTAR)),f); + R obverse(hook(swap(ds(CTAKE)),atop(h,g)),w); + case CDOMINO: + if(!(2==AR(x)&&*AS(x)==*(1+AS(x))))break; + ff=eval("+/ .*"); + R nf?atop(h,amp(ff,minv(x))):amp(x,ff); + case CDOT: + if(ip(h,CPLUS,CSTAR)){ + ASSERT(2==AR(x),EVRANK); + ASSERT(*AS(x)==*(1+AS(x)),EVLENGTH); + R nf?amp(ds(CDOMINO),x):amp(h,minv(x)); + } + break; + case CQQ: + if(ng&&equ(x,one)&&equ(f,eval("i.\"1")))R hook(ds(CFROM),ds(CEQ)); + break; + case CBSLASH: + if(nf&&(n=i0(x),0>n)&&(d=ID(u->f),d==CLEFT||d==CRIGHT))R slash(ds(CCOMMA)); + break; + case CIBEAM: + x=VAV(h)->f; y=VAV(h)->g; + if(NOUN&AT(x)&&equ(x,num[3])&&NOUN&AT(y)){ + RE(n=i0(f)); + if(all1(eps(y,v2(4L,5L)))){ASSERT(n&&-2<=n&&n<=2,EVDOMAIN); R amp(sc(-n),g);} + if(all1(eps(y,v2(1L,3L)))){ASSERT(0==n||1==n||10==n||11==n,EVDOMAIN); R foreign(x,num[2]);} + } + break; + case CBDOT: + RE(n=i0(x)); + switch(i0(VAV(h)->f)){ + case 22: case 25: R w; + case 19: case 28: if(ng)R w; break; + case 21: case 26: if(nf)R w; break; + case 32: case 33: case 34: ASSERT(nf,EVDOMAIN); R amp(negate(x),h); + } + break; + case CPOLY: + if(nf&&1==AR(x)&&2==AN(x)&&NUMERIC&AT(x)&&!equ(zero,tail(x))){ + RZ(y=recip(tail(x))); + R amp(over(tymes(y,negate(head(x))),y),h); + }} + ASSERT(0,EVDOMAIN); +} + +static C invf[2][29] = { + CDIV, CPLUS, CMINUS, CLEFT, CRIGHT, CREV, CCANT, CPOLY, + CNOT, CGRADE, CCYCLE, CDOMINO, COPE, CBOX, CLOG, CEXP, + CGE, CLE, CHALVE, CPLUSCO, CSQRT, CSTARCO, CHEAD, CLAMIN, + CABASE, CBASE, CTHORN, CEXEC, 0, + CDIV, CPLUS, CMINUS, CLEFT, CRIGHT, CREV, CCANT, CPOLY, + CNOT, CGRADE, CCYCLE, CDOMINO, CBOX, COPE, CEXP, CLOG, + CLE, CGE, CPLUSCO, CHALVE, CSTARCO, CSQRT, CLAMIN, CHEAD, + CBASE, CABASE, CEXEC, CTHORN, 0 +}; + +F1(jtinv){A f,ff,g;B b,nf,ng,vf,vg;C id,*s;I p,q;V*v; + RZ(w); + ASSERT(VERB&AT(w),EVDOMAIN); + id=ID(w); v=VAV(w); + if(s=strchr(invf[0],id))R ds(invf[1][s-invf[0]]); + f=v->f; nf=f&&AT(f)&NOUN+NAME; vf=f&&!nf; + g=v->g; ng=g&&AT(g)&NOUN+NAME; vg=g&&!ng; + switch(id){ + case CCIRCLE: R eval("1p_1&*"); + case CJDOT: R eval("0j_1&*"); + case CRDOT: R eval("%&0j1@^."); + case CPLUSDOT: R eval("j./\"1\"_ :. +."); + case CSTARDOT: R eval("r./\"1\"_ :. *."); + case CDGRADE: R eval("/:@|."); + case CWORDS: R eval("}:@;@(,&' '&.>\"1) :. ;:"); + case CBANG: R eval("3 :'(-(!-y\"_)%1e_3&* !\"0 D:1 ])^:_ <.&170^:(-:+)^.y' :. !"); + case CXCO: R amp(num[-1],w); + case CSPARSE: R fdef(CPOWOP,VERB,jtdenseit,0L, w,num[-1],0L, 0L, RMAX,RMAX,RMAX); + case CPCO: R fdef(CPOWOP,VERB,jtplt, 0L, w,num[-1],0L, 0L, 0L, 0L, 0L ); + case CQCO: R eval("*/"); + case CUCO: R amp(num[3],w); + case CUNDER: R under(inv(f),g); + case CFORK: R invfork(w); + case CAMP: if(nf!=ng)R invamp(w); /* fall thru */ + case CAT: if(vf&&vg)R atop(inv(g),inv(f)); break; + case CAMPCO: + case CATCO: if(vf&&vg)R atco(inv(g),inv(f)); break; + case CSLASH: if(CSTAR==ID(f))R ds(CQCO); break; + case CQQ: if(vf)R qq(inv(f),g); break; + case COBVERSE: if(vf&&vg)R obverse(g,f); break; + case CSCO: R amp(num[5],w); + case CPOWOP: + if(vf&&ng){RE(p=i0(g)); R -1==p?f:1==p?inv(f):powop(0>p?f:inv(f),sc(ABS(p)));} + if(VGERL&v->flag)R*(1+AAV(v->h)); + break; + case CTILDE: + if(nf)R inv(symbrd(f)); + switch(ID(f)){ + case CPLUS: R ds(CHALVE); + case CSTAR: R ds(CSQRT); + case CJDOT: R eval("0.5j_0.5&*"); + case CLAMIN: R eval("{. :. (,:~)"); + case CSEMICO:R eval(">@{. :. (;~)"); + case CCOMMA: R eval("<.@-:@# {. ] :. (,~)"); + case CEXP: R eval("3 : '(- -&b@(*^.) % >:@^.)^:_ ]1>.b=.^.y' \" 0 :. (^~)"); + } + break; + case CBSLASH: + case CBSDOT: + if(CSLASH==ID(f)&&(ff=VAV(f)->f,ff&&VERB&AT(ff))){ + b=id==CBSDOT; + switch(ID(ff)){ + case CPLUS: R obverse(eval(b?"- 1&(|.!.0)":" - |.!.0"),w); + case CSTAR: R obverse(eval(b?"% 1&(|.!.1)":" % |.!.1"),w); + case CEQ: R obverse(eval(b?"= 1&(|.!.1)":" = |.!.1"),w); + case CNE: R obverse(eval(b?"~:1&(|.!.0)":" ~:|.!.0"),w); + case CMINUS:R obverse(eval(b?"+ 1&(|.!.0)":"(- |.!.0) *\"_1 $&1 _1@#"),w); + case CDIV: R obverse(eval(b?"* 1&(|.!.1)":"(% |.!.1) ^\"_1 $&1 _1@#"),w); + }} + break; + case CCUT: + if(CBOX==ID(f)&&ng&&(p=i0(g),1==p||2==p))R fdef(CPOWOP,VERB, jtbminv,0L, w,num[-1], 0L,0L, RMAX,RMAX,RMAX); + break; + case CIBEAM: + p=i0(f); q=i0(g); + if(3==p&&1==q)R foreign(f,num[2]); + if(3==p&&2==q)R foreign(f,one ); + if(3==p&&3==q)R foreign(f,num[2]); + break; + case CHOOK: + if(CFROM==ID(f)&&CEQ==ID(g))R eval("i.\"1&1"); + break; + } + if(!nameless(w))R inv(fix(w)); + ASSERT(0,EVDOMAIN); +} + +static F1(jtneutral){A x,y;B b;V*v; + RZ(w); + v=VAV(w); + ASSERT(!v->lr&&!v->rr,EVDOMAIN); + RZ(y=v2(0L,1L)); + RZ(x=scf(infm)); b=equ(y,CALL2(v->f2,x,y,w)); RESETERR; if(b)R x; + x=ainf; b=equ(y,CALL2(v->f2,x,y,w)); RESETERR; if(b)R x; + x=zero; b=equ(y,CALL2(v->f2,x,y,w)); RESETERR; if(b)R x; + x=one; b=equ(y,CALL2(v->f2,x,y,w)); RESETERR; if(b)R x; + RZ(x=scf(infm)); b=equ(y,CALL2(v->f2,y,x,w)); RESETERR; if(b)R x; + x=ainf; b=equ(y,CALL2(v->f2,y,x,w)); RESETERR; if(b)R x; + x=zero; b=equ(y,CALL2(v->f2,y,x,w)); RESETERR; if(b)R x; + x=one; b=equ(y,CALL2(v->f2,y,x,w)); RESETERR; if(b)R x; + ASSERT(0,EVDOMAIN); +} /* neutral of arbitrary rank-0 function */ + +F1(jtiden){A f,g,x=0;V*u,*v; + RZ(w=fix(w)); ASSERT(VERB&AT(w),EVDOMAIN); + v=VAV(w); f=v->f; g=v->g; + switch(v->id){ + default: RZ(x=neutral(w)); break; + case CCOMMA: R eval("i.@(0&,)@(2&}.)@$"); + case CDOT: if(!(ip(w,CPLUS,CSTAR)||ip(w,CPLUSDOT,CSTARDOT)||ip(w,CNE,CSTARDOT)))break; + case CDOMINO: R atop(atop(ds(CEQ),ds(CGRADE)),ds(CHEAD)); + case CCYCLE: + case CLBRACE: R atop(ds(CGRADE),ds(CHEAD)); + case CSLASH: if(VERB&AT(f))R atop(iden(f),ds(CPOUND)); break; + case CPLUS: case CMINUS: case CSTILE: case CNE: + case CGT: case CLT: case CPLUSDOT: case CJDOT: case CRDOT: + x=zero; break; + case CSTAR: case CDIV: case CEXP: case CROOT: case CBANG: + case CEQ: case CGE: case CLE: case CSTARDOT: + x=one; break; + case CMAX: x=scf(infm); break; + case CMIN: x=ainf; break; + case CUNDER: x=df1(df1(mtv,iden(f)),inv(g)); break; + case CAT: + if(CAMP==ID(f)&&(u=VAV(f),NOUN&AT(u->f)&&!AR(u->f)&&CSTILE==ID(u->g)))switch(ID(g)){ + case CSTAR: case CEXP: x=one; break; + case CPLUS: x=zero; + } + break; + case CBDOT: + switch(i0(f)){ + case 25: x=num[-1]; break; + case 2: case 4: case 5: case 6: case 7: + case 18: case 20: case 21: case 22: case 23: + x=zero; break; + case 1: case 9: case 11: case 13: case 17: + case 27: case 29: + x=one; + }} + ASSERT(x,EVDOMAIN); + R folk(x,swap(ds(CDOLLAR)),atop(ds(CBEHEAD),ds(CDOLLAR))); +} diff --git a/am.c b/am.c new file mode 100644 --- /dev/null +++ b/am.c @@ -0,0 +1,217 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Adverbs: Amend */ + +#include "j.h" + + +/* +static A jtmerge1(J jt,A w,A ind){PROLOG;A z;C*v,*x;I c,k,r,*s,t,*u; + RZ(w&&ind); + RZ(ind=pind(IC(w),ind)); + r=MAX(0,AR(w)-1); s=1+AS(w); t=AT(w); c=aii(w); + ASSERT(!(t&SPARSE),EVNONCE); + ASSERT(r==AR(ind),EVRANK); + ASSERT(!ICMP(s,AS(ind),r),EVLENGTH); + GA(z,t,c,r,s); x=CAV(z); v=CAV(w); u=AV(ind); k=bp(t); + DO(c, MC(x+k*i,v+k*(i+c*u[i]),k);); + EPILOG(z); +} +*/ + +#define MCASE(t,k) ((t)+16*(k)) +#define MINDEX {j=*u++; if(0>j)j+=m; ASSERT(0<=j&&jj){j+=m; ASSERT(0<=j,EVINDEX);}else ASSERT(jc||1=r,EVINDEX); + ASSERT(n<=wr,EVINDEX); + d=n; DO(n, --d; if(!equ(ace,AADR(id,v[d])))break;); if(n)++d; n=d; + j=zero; + for(i=0;if,0);} +static DF2(amipn2){R amendn2(a,w,VAV(self)->f,(B)(!(AT(w)&RAT+XNUM)&&(1==AC(w)||AFNJA&AFLAG(w))));} + +static DF2(amccv2){DECLF; + RZ(a&&w); + ASSERT(DENSE&AT(w),EVNONCE); + R merge2(a,w,pind(AN(w),CALL2(f2,a,w,fs)),0); +} + +static DF2(amipv2){DECLF; + RZ(a&&w); + ASSERT(DENSE&AT(w),EVNONCE); + R merge2(a,w,pind(AN(w),CALL2(f2,a,w,fs)),(B)(!(AT(w)&RAT+XNUM)&&(1==AC(w)||AFNJA&AFLAG(w)))); +} + +static DF1(mergn1){ R merge1(w,VAV(self)->f);} +static DF1(mergv1){DECLF; R merge1(w,CALL1(f1,w,fs));} + +static B ger(A w){A*wv,x;I wd; + if(!(BOX&AT(w)))R 0; + wv=AAV(w); wd=(I)w*ARELATIVE(w); + DO(AN(w), x=WVR(i); if(BOX&AT(x)&&1==AR(x)&&2==AN(x))x=AAV0(x); if(!(LIT&AT(x)&&1>=AR(x)&&AN(x)))R 0;); + R 1; +} /* 0 if w is definitely not a gerund; 1 if possibly a gerund */ + +static A jtamend(J jt,A w,B ip){ + RZ(w); + if(VERB&AT(w)) R ADERIV(CRBRACE,mergv1,ip?amipv2:amccv2,RMAX,RMAX,RMAX); + else if(ger(w))R gadv(w,CRBRACE); + else R ADERIV(CRBRACE,mergn1,ip?amipn2:amccn2,RMAX,RMAX,RMAX); +} + +F1(jtrbrace){R amend(w,0);} +F1(jtamip ){R amend(w,1);} + + +static DF2(jtamen2){ASSERT(0,EVNONCE);} + +F1(jtemend){ + ASSERT(NOUN&AT(w),EVDOMAIN); + R ADERIV(CEMEND,0L,jtamen2,RMAX,RMAX,RMAX); +} diff --git a/am1.c b/am1.c new file mode 100644 --- /dev/null +++ b/am1.c @@ -0,0 +1,205 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Adverbs: a ind}z for sparse z & ind is box a0;a1;a2;... or integer */ + +/* am1e a is the sparse element */ +/* am1a a is an arbitrary dense array */ +/* am1sp a an arbitrary sparse array */ + +#include "j.h" + + +static A jtistd1(J jt,A z,A ind){A*iv,j,*jv,x;I d,i,id,n,r,*s; + RZ(z&&ind); + ASSERT(1>=AR(ind),EVRANK); + if(AN(ind)&&!(BOX&AT(ind))){ASSERT(NUMERIC&AT(ind),EVINDEX); RZ(ind=every(ind,0L,jtright1));} + s=AS(z); n=AN(ind); iv=AAV(ind); id=(I)ind*ARELATIVE(ind); + ASSERT(n<=AR(z),EVINDEX); + d=n; DO(n, --d; x=IVR(d); if(!equ(x,ace))break;); n=n?1+d:d; + GA(j,BOX,n,1,0); jv=AAV(j); + for(i=0;i=AN(ind))break; + x=IVR(j); + if(x!=ace){ + u=yv+i; DO(m, v[i]=b[i]?*u:-1; u+=c;); + RZ(p=eps(q,1i-j)qv[i]=1; j=i;} v+=n;); if(d>(m-1)-j)qv[m-1]=1;} + RZ(y1=repeat(q,y1)); c=*AS(y1); + if(!c)R mtm; + R less(stitch(repeat(sc(d),y1),reitem(sc(c*d),odom(2L,h,sv))),y); +} /* new rows for the index matrix of z for existing cells */ + +static A jtscube(J jt,A z,A i1,A p){A a,y;P*zp; + zp=PAV(z); a=SPA(zp,a); y=SPA(zp,i); + R !AN(a)&&!*AS(y)?take(one,mtm):over(scubb(z,i1),scubc(z,i1,p)); +} /* new rows for the index matrix of z */ + +static A jtiindx(J jt,A z,A i1){A q,j,j1,y;I c,d,e,h,i,*jv,m,n,*qv,*v,*yv;P*zp; + c=AN(i1); zp=PAV(z); y=SPA(zp,i); + if(c==*(1+AS(y)))R indexof(y,scuba(z,i1,0)); + /* when y has excess columns, do progressive indexing */ + RZ(y=taker(c,y)); + RZ(j=indexof(y,scuba(z,i1,0))); /* j: group indices */ + n= AN(j); jv=AV(j); + m=*AS(y); yv=AV(y); + GA(q,INT,n,1,0); qv=AV(q); /* q: # members in each group */ + for(i=h=0;iu[i])v[e++]=s[i]; else d*=s[i];); + RZ(*i2=jj=tymes(sc(d),base2(vec(INT,e,v),repeatr(eps(ai,as),ind)))); + c=*(1+AS(y)); + if(!c){ + n=AN(jj); + RZ(*i1=repeat(sc(n),IX(m))); + RZ(*i2=reshape(sc(m*n),jj)); + R 1; + } + RZ(*i1=ii=indexof(y,repeatr(eps(ai,a),ind))); /* group indices in index mat */ + if(c==AN(a))R 1; + n=AN(ii); iv=AV(ii); jv=AV(jj); /* do progressive iota */ + GA(q,INT,n,1,0); qv=AV(q); /* group sizes */ + for(i=h=0;iiv[i])mvc(vk,v+xk*iv[i]+k*jv[i],k,u);); + R z; +} /* a (<"1 ind)}z, sparse z, integer array ind, sparse element a replacement */ + +A jtamna(J jt,A a,A z,A ind,B ip){A i1,i2,x;C*u,*v;I*iv,*jv,k,n,vk,xk;P*zp; + RZ(a&&z&&ind); + RZ(z=zpadn(z,ind,ip)); + RZ(a=astdn(a,z,ind)); + RZ(iaddr(z,ind,&i1,&i2)); + zp=PAV(z); x=SPA(zp,x); n=AN(i1); + k=bp(AT(x)); xk=k*aii(x); vk=k*csize(z,ind); + u=CAV(a); v=CAV(x); iv=AV(i1); jv=AV(i2); + if(AR(a))DO(n, mvc(vk,v+xk*iv[i]+k*jv[i],vk,u); u+=vk;) + else DO(n, mvc(vk,v+xk*iv[i]+k*jv[i],k,u);); + R z; +} /* a (<"1 ind)}z, dense a,integer array ind, sparse z */ + +A jtamnsp(J jt,A a,A z,A ind,B ip){A i1,i2,t;C*ev,*u,*v,*vv;I c,*dv,i,*iv,j,*jv,k,m,n,p,q,r,*s,*yv,zk;P*ap,*zp; + RZ(a&&z&&ind); + r=AR(a); ap=PAV(a); t=SPA(ap,a); if(r>AN(t))RZ(a=reaxis(IX(r),a)); + RZ(a=astdn(a,z,ind)); ap=PAV(a); + RZ(z=zpadn(z,ind,ip)); zp=PAV(z); + RZ(iaddr(z,ind,&i1,&i2)); + s=AS(a); n=AN(i1); c=csize(z,ind); iv=AV(i1); jv=AV(i2); + t=SPA(ap,i); yv= AV(t); m=*AS(t); p=0; + t=SPA(ap,e); ev=CAV(t); + t=SPA(ap,x); u =CAV(t); + t=SPA(zp,x); v =CAV(t); k=bp(AT(t)); zk=k*aii(t); + GA(t,INT,r,1,0); dv=AV(t); memset(dv,C0,SZI*r); dv[r-1]=-1; + for(i=0;i=r){*v=m=AN(w); n=1;}else{m=*u++; n=*u++; *v++=m*n; ICPY(v,u,r-2);} + RZ(x=irs2(IX(m),IX(n),0L,0L,1L,jtplus)); AR(x)=1; *AS(x)=AN(x); + R df2(x,y,sldot(VAV(self)->f)); +} + + +#define OBQCASE(id,t) ((id)+(256*(t))) + +#define OBQLOOP(Tw,Tz,zt,init,expr) \ + {Tw*u,*v,*ww=(Tw*)wv;Tz x,*zz; \ + b=1; k=n1; \ + GA(z,zt,d*c,r-1,1+s); *AS(z)=d; zz=(Tz*)AV(z); \ + DO(n, v=ww+i; u=v+n1*MIN(i,m1); init; while(v<=(u-=n1))expr; *zz++=x;); \ + DO(m1, v=ww+(k+=n); u=v+n1*MIN(m-i-2,n1); init; while(v<=(u-=n1))expr; *zz++=x;); \ + } + +static DF1(jtobqfslash){A y,z;B b=0,p;C er,id,*wv;I c,d,k,m,m1,mn,n,n1,r,*s,wt; + RZ(w); + r=AR(w); s=AS(w); wt=AT(w); wv=CAV(w); + if(!(AN(w)&&1f; y=VAV(y)->f; id=vaid(y); + m=s[0]; m1=m-1; + n=s[1]; n1=n-1; mn=m*n; d=m+n-1; c=prod(r-2,2+s); + if(1==m||1==n){GA(z,wt,AN(w),r-1,1+s); *AS(z)=d; MC(AV(z),wv,AN(w)*bp(wt)); R z;} + if(wt&FL+CMPX)NAN0; + if(1==c)switch(OBQCASE(wt,id)){ + case OBQCASE(B01, CNE ): OBQLOOP(B,B,wt,x=*u, x^=*u ); break; + case OBQCASE(B01, CEQ ): OBQLOOP(B,B,wt,x=*u, x=x==*u ); break; + case OBQCASE(B01, CMAX ): + case OBQCASE(B01, CPLUSDOT): OBQLOOP(B,B,wt,x=*u, x|=*u ); break; + case OBQCASE(B01, CMIN ): + case OBQCASE(B01, CSTAR ): + case OBQCASE(B01, CSTARDOT): OBQLOOP(B,B,wt,x=*u, x&=*u ); break; + case OBQCASE(B01, CLT ): OBQLOOP(B,B,wt,x=*u, x=*u< x ); break; + case OBQCASE(B01, CLE ): OBQLOOP(B,B,wt,x=*u, x=*u<=x ); break; + case OBQCASE(B01, CGT ): OBQLOOP(B,B,wt,x=*u, x=*u> x ); break; + case OBQCASE(B01, CGE ): OBQLOOP(B,B,wt,x=*u, x=*u>=x ); break; + case OBQCASE(B01, CPLUS ): OBQLOOP(B,I,INT,x=*u, x+=*u ); break; + case OBQCASE(FL, CMAX ): OBQLOOP(D,D,wt,x=*u, x=MAX(x,*u) ); break; + case OBQCASE(FL, CMIN ): OBQLOOP(D,D,wt,x=*u, x=MIN(x,*u) ); break; + case OBQCASE(FL, CPLUS ): OBQLOOP(D,D,wt,x=*u, x+=*u ); break; + case OBQCASE(CMPX,CPLUS ): OBQLOOP(Z,Z,wt,x=*u, x=zplus(x,*u)); break; + case OBQCASE(XNUM,CMAX ): OBQLOOP(X,X,wt,x=*u, x=1==xcompare(x,*u)? x:*u); break; + case OBQCASE(XNUM,CMIN ): OBQLOOP(X,X,wt,x=*u, x=1==xcompare(x,*u)?*u: x); break; + case OBQCASE(XNUM,CPLUS ): OBQLOOP(X,X,wt,x=*u, x=xplus(x,*u)); break; + case OBQCASE(RAT, CMAX ): OBQLOOP(Q,Q,wt,x=*u, x=1==QCOMP(x,*u)? x:*u); break; + case OBQCASE(RAT, CMIN ): OBQLOOP(Q,Q,wt,x=*u, x=1==QCOMP(x,*u)?*u: x); break; + case OBQCASE(RAT, CPLUS ): OBQLOOP(Q,Q,wt,x=*u, x=qplus(x,*u)); break; + case OBQCASE(INT, CBW0001 ): OBQLOOP(I,I,wt,x=*u, x&=*u ); break; + case OBQCASE(INT, CBW0110 ): OBQLOOP(I,I,wt,x=*u, x^=*u ); break; + case OBQCASE(INT, CBW0111 ): OBQLOOP(I,I,wt,x=*u, x|=*u ); break; + case OBQCASE(INT, CMAX ): OBQLOOP(I,I,wt,x=*u, x=MAX(x,*u) ); break; + case OBQCASE(INT, CMIN ): OBQLOOP(I,I,wt,x=*u, x=MIN(x,*u) ); break; + case OBQCASE(INT, CPLUS ): + er=0; OBQLOOP(I,I,wt,x=*u, {p=0>x; x+=*u; BOV(p==0>*u&&p!=0>x);}); + if(er==EWOV)OBQLOOP(I,D,FL,x=(D)*u, x+=*u); + } + if(wt&FL+CMPX)NAN1; RE(0); + R b?z:oblique(w,self); +} /* f//.y for atomic f */ + + +#if SY_64 +#define TYMESF(x) {LD t=*u--*(LD)*v++; x=(I)t; BOV(tx; x+=y; BOV(p==0>y&&p!=0>x);} + +#define PMCASE(t,c,d) (65536*(c)+256*(d)+(t)) + +#define PMLOOP(Tw,Tz,zt,expr0,expr) \ + {Tw*aa=(Tw*)av,*u,*v,*ww=(Tw*)wv;Tz x,*zv; \ + b=1; GA(z,zt,zn,1,0); zv=(Tz*)AV(z); \ + for(i=0;if; y=VAV(f)->f; y=VAV(y)->f; c=vaid(y); + g=v->g; y=VAV(g)->f; d=vaid(y); + if(!(m&&1==AR(a)&&n&&1==AR(w)))R obqfslash(df2(a,w,g),f); + if(t&FL+CMPX)NAN0; + switch(PMCASE(t,c,d)){ + case PMCASE(B01, CNE, CMAX ): + case PMCASE(B01, CNE, CPLUSDOT): PMLOOP(B,B,B01, x=*u--|*v++, x^=*u--|*v++); break; + case PMCASE(B01, CNE, CSTAR ): + case PMCASE(B01, CNE, CMIN ): + case PMCASE(B01, CNE, CSTARDOT): PMLOOP(B,B,B01, x=*u--&*v++, x^=*u--&*v++); break; + case PMCASE(B01, CPLUS, CMAX ): + case PMCASE(B01, CPLUS, CPLUSDOT): PMLOOP(B,I,INT, x=*u--|*v++, x+=*u--|*v++); break; + case PMCASE(B01, CPLUS, CSTAR ): + case PMCASE(B01, CPLUS, CMIN ): + case PMCASE(B01, CPLUS, CSTARDOT): PMLOOP(B,I,INT, x=*u--&*v++, x+=*u--&*v++); break; + case PMCASE(FL, CPLUS, CSTAR ): PMLOOP(D,D,FL, x=*u--**v++, x+=*u--**v++); break; + case PMCASE(CMPX,CPLUS, CSTAR ): PMLOOP(Z,Z,CMPX, x=ztymes(*u--,*v++), x=zplus(x,ztymes(*u--,*v++))); break; + case PMCASE(XNUM,CPLUS, CSTAR ): PMLOOP(X,X,XNUM, x=xtymes(*u--,*v++), x=xplus(x,xtymes(*u--,*v++))); break; + case PMCASE(RAT, CPLUS, CSTAR ): PMLOOP(Q,Q,RAT, x=qtymes(*u--,*v++), x=qplus(x,qtymes(*u--,*v++))); break; + case PMCASE(INT, CBW0110,CBW0001 ): PMLOOP(I,I,INT, x=*u--&*v++, x^=*u--&*v++); break; + case PMCASE(INT, CPLUS, CSTAR ): +/* + er=0; PMLOOP(I,I,INT, TYMESF(x), ACCUMF); +*/ + {A a1,y;I*aa,i,*u,*ww=(I*)wv,*v,*yv,*zv;VF adotymes,adosum; + b=1; + RZ(var(CSTAR,a,w,at,wt,&adotymes,&i)); vains(CPLUS,wt,&adosum,&i); + GA(a1,INT,m,1,0); aa=AV(a1); u=m+(I*)av; DO(m, aa[i]=*--u;); + GA(y,INT,MIN(m,n),1,0); yv=AV(y); + GA(z,INT,zn,1,0); zv=AV(z); + for(i=0;ijerr){RESETERR; fa(z); PMLOOP(I,D,FL, x=*u--*(D)*v++, x+=*u--*(D)*v++);} + }} + if(t&FL+CMPX)NAN1; RE(0); + if(!b)R obqfslash(df2(a,w,g),f); + R z; +} /* f//.@(g/) for atomic f, g */ + + +static DF2(jtkey); + +static DF2(jtkeysp){PROLOG;A b,by,e,q,x,y,z;I j,k,n,*u,*v;P*p; + RZ(a&&w); + n=IC(a); + RZ(q=indexof(a,a)); p=PAV(q); + x=SPA(p,x); u=AV(x); + y=SPA(p,i); v=AV(y); + e=SPA(p,e); k=i0(e); + j=0; DO(AN(x), if(k<=u[i])break; if(u[i]==v[i])++j;); + RZ(b=ne(e,x)); + RZ(by=repeat(b,y)); + RZ(x=key(repeat(b,x),from(ravel(by),w),self)); + GA(q,SB01,1,1,0); *AS(q)=n; /* q=: 0 by}1$.n;0;1 */ + p=PAV(q); SPB(p,a,iv0); SPB(p,e,one); SPB(p,i,by); SPB(p,x,reshape(tally(by),zero)); + RZ(z=over(df1(repeat(q,w),VAV(self)->f),x)); + EPILOG(j?cdot2(box(IX(1+j)),z):z); +} + +static DF2(jtkeyi){PROLOG;A j,p;B*pv;I*av,c,d=-1,n,*jv; + RZ(a&&w); + n=IC(a); av=AV(a); + RZ(j=grade1(a)); jv=AV(j); + GA(p,B01,n,1,0); pv=BAV(p); + DO(n, c=d; d=av[*jv++]; *pv++=cf,one))); +} /* a f/. w where a is i.~x for dense x & w */ + +static DF2(jtkeybox){PROLOG;B b;I*wv; + RZ(a&&w); + ASSERT(IC(a)==IC(w),EVLENGTH); + if(SPARSE&AT(a))R keysp(a,w,self); + if(b=INT&AT(w)&&1==AR(w)){wv=AV(w); DO(AN(w), if(i!=*wv++){b=0; break;});} + if(b)R group(a); + EPILOG(keyi(indexof(a,a),w,self)); +} /* a =ac)switch(at){ + case C2T: if(1==ac)s=65536; break; + case B01: if(1==ac)s=2; else{s=258; at=C2T;} break; + case LIT: if(1==ac)s=256; else{s=65536; at=C2T;} break; + case INT: if(1==ac)irange(AN(a),AV(a),&r,&s); break; + case SBT: if(1==ac){at=INT; s=jt->sbun; if(65536f; d=vaid(VAV(x)->f); if(B01&wt)d=d==CMAX?CPLUSDOT:d==CMIN||d==CSTAR?CSTARDOT:d; + if(!(AN(a)&&AN(w)&&at&DENSE&& + (wt&B01&&(d==CEQ||d==CPLUSDOT||d==CSTARDOT||d==CNE||d==CPLUS)|| + wt&INT&&(17<=d&&d<=25)|| + wt&INT+FL&&(d==CMIN||d==CMAX||d==CPLUS) )))R key(a,w,self); + at=keyrs(a,&r,&s); c=aii(w); m=s; + zt=d==CPLUS?(wt&B01?INT:wt&INT?FL:wt):wt; bb=s&&s<=MAX(2*n,65536); + if(bb){ + GA(b,B01,s, 1,0); bv=BAV(b); memset(bv,C1,s); bv-=r; + GA(q,zt, s*c,1,0); qv0=AV(q); + }else{RZ(x=indexof(a,a)); xv=AV(x); m=0; u=xv; DO(n, *u=i==*u?m++:xv[*u]; ++u;);} + GA(z,zt,m*c,wr,AS(w)); *AS(z)=m; zv0=AV(z); + if(wt&FL)NAN0; + switch(KCASE(d,wt)){ + case KCASE(CEQ, B01): KACC(*v==y, B, B, 1 ); break; + case KCASE(CPLUSDOT,B01): KACC(*v||y, B, B, 0 ); break; + case KCASE(CSTARDOT,B01): KACC(*v&&y, B, B, 1 ); break; + case KCASE(CNE, B01): KACC(*v!=y, B, B, 0 ); break; + case KCASE(CMIN, INT): KACC(MIN(*v,y),I, I, IMAX); break; + case KCASE(CMIN, FL ): KACC(MIN(*v,y),D, D, inf ); break; + case KCASE(CMAX, INT): KACC(MAX(*v,y),I, I, IMIN); break; + case KCASE(CMAX, FL ): KACC(MAX(*v,y),D, D, infm); break; + case KCASE(CPLUS, B01): KACC(*v+y, I, B, 0 ); break; + case KCASE(CPLUS, INT): KACC(*v+y, D, I, 0.0 ); pp=1; break; + case KCASE(CPLUS, FL ): KACC(*v+y, D, D, 0.0 ); break; + case KCASE(17, INT): KACC(*v&y, UI,UI,-1 ); break; + case KCASE(22, INT): KACC(*v^y, UI,UI,0 ); break; + case KCASE(23, INT): KACC(*v|y, UI,UI,0 ); break; + case KCASE(25, INT): KACC(~(*v^y), UI,UI,-1 ); + } + if(wt&FL)NAN1; + *AS(z)=m; AN(z)=m*c; if(pp)RZ(z=pcvt(INT,z)); + EPILOG(z); +} /* x f//.y */ + + +#define KMCASE(ta,tw) (ta+65536*tw) +#define KMACC(Ta,Tw) \ + {Ta*u=(Ta*)av;Tw*v=(Tw*)wv; \ + if(1==c)DO(n, ++pv[*u]; qv[*u]+=*v++; ++u;) \ + else DO(n, ++pv[*u]; vv=qv+c**u; DO(c, *vv++ +=*v++;); ++u;); \ + } +#define KMSET(Ta) \ + {Ta*u=(Ta*)av; \ + if(1==c)DO(n, if(pv[j=*u++]){ *zv++=qv[j]/pv[j]; pv[j]=0; if(s==++m)break;}) \ + else DO(n, if(pv[j=*u++]){vv=qv+c*j; d=(D)pv[j]; DO(c, *zv++=*vv++/d;); pv[j]=0; if(s==++m)break;}); \ + } +#define KMFUN(Tw) \ + {Tw*v=(Tw*)wv; \ + if(1==c)DO(n, j=*xv++; ++pv[j]; zv[j]+=*v++;) \ + else DO(n, j=*xv++; ++pv[j]; vv=zv+j*c; DO(c, *vv+++=*v++;);); \ + } + +static DF2(jtkeymean){PROLOG;A p,q,x,z;D d,*qv,*vv,*zv;I at,*av,c,j,m=0,n,*pv,r,s,*u,wr,wt,*wv,*xv; + RZ(a&&w); + at=AT(a); av=AV(a); n=IC(a); + wt=AT(w); wv=AV(w); wr=AR(w); + ASSERT(n==IC(w),EVLENGTH); + if(!(AN(a)&&AN(w)&&at&DENSE&&wt&B01+INT+FL))R df2(a,w,folk(sldot(slash(ds(CPLUS))),ds(CDIV),sldot(ds(CPOUND)))); + at=keyrs(a,&r,&s); c=aii(w); + if(wt&FL)NAN0; + if(s&&s<=MAX(2*n,65536)){ + GA(p,INT,s, 1, 0 ); pv= AV(p); memset(pv,C0,s* SZI); pv-=r; + GA(q,FL, s*c,1, 0 ); qv=DAV(q); memset(qv,C0,s*c*SZD); qv-=r*c; + GA(z,FL, s*c,wr,AS(w)); zv=DAV(z); + switch(KMCASE(at,wt)){ + case KMCASE(B01,B01): KMACC(B, B); break; + case KMCASE(B01,INT): KMACC(B, I); break; + case KMCASE(B01,FL ): KMACC(B, D); break; + case KMCASE(LIT,B01): KMACC(UC,B); break; + case KMCASE(LIT,INT): KMACC(UC,I); break; + case KMCASE(LIT,FL ): KMACC(UC,D); break; + case KMCASE(C2T,B01): KMACC(US,B); break; + case KMCASE(C2T,INT): KMACC(US,I); break; + case KMCASE(C2T,FL ): KMACC(US,D); break; + case KMCASE(INT,B01): KMACC(I ,B); break; + case KMCASE(INT,INT): KMACC(I ,I); break; + case KMCASE(INT,FL ): KMACC(I ,D); + } + switch(at){ + case B01: KMSET(B ); break; + case LIT: KMSET(UC); break; + case C2T: KMSET(US); break; + case INT: KMSET(I ); + } + *AS(z)=m; AN(z)=m*c; + }else{ + RZ(x=indexof(a,a)); xv=AV(x); m=0; u=xv; DO(n, *u=i==*u?m++:xv[*u]; ++u;); + GA(p,INT,m, 1, 0 ); pv= AV(p); memset(pv,C0,m* SZI); + GA(z,FL, m*c,wr,AS(w)); *AS(z)=m; zv=DAV(z); memset(zv,C0,m*c*SZD); + switch(wt){ + case B01: KMFUN(B); break; + case INT: KMFUN(I); break; + case FL: KMFUN(D); + } + if(1==c)DO(m, *zv++/=*pv++;) else DO(m, d=(D)*pv++; DO(c, *zv++/=d;);); + } + if(wt&FL)NAN1; + EPILOG(z); +} /* x (+/%#)/.y */ + + +#define GRPCD(T) {T*v=(T*)wv; DO(n, j=*v++; if(0<=dv[j])++cv[j]; else{dv[j]=i; cv[j]=1; ++zn;});} +#define GRPIX(T,asgn,j,k) {T*v=(T*)wv; DO(n, j=asgn; if(m>=j)*cu[k]++=i; \ + else{GA(x,INT,cv[k],1,0); *zv++=x; u=AV(x); *u++=m=j; cu[k]=u;})} + +F1(jtgroup){PROLOG;A c,d,x,z,*zv;B b;I**cu,*cv,*dv,j,k,m,n,p,q,t,*u,*v,*wv,zn=0; + RZ(w); + if(SPARSE&AT(w))RZ(w=denseit(w)); + n=IC(w); t=AT(w); p=q=0; b=0; k=n?aii(w)*bp(t):0; + if(!AN(w)){GA(z,BOX,n?1:0,1,0); if(n)RZ(*AAV(z)=IX(n)); R z;} + if(2>=k)q=t&B01?(1==k?2:258):t&LIT?(1==k?256:65536):t&C2T?65536:0; + if(k==SZI&&t&INT+SBT)irange(n,AV(w),&p,&q); + if(b=q&&(2>=k||q<=2*n)){ + GA(c,INT,q,1,0); cv=AV(c)-p; /* counts */ + GA(d,INT,q,1,0); dv=AV(d)-p; /* indices */ + wv=AV(w); v=dv+p; DO(q, *v++=-1;); + switch(k){ + case 1: GRPCD(UC); break; + case 2: GRPCD(US); break; + case SZI: GRPCD(I); + }}else{ + RZ(w=indexof(w,w)); wv=AV(w); + GA(c,INT,n,1,0); cv=AV(c); + m=-1; v=wv; DO(n, j=*v++; if(m>=j)++cv[j]; else{m=j; cv[j]=1; ++zn;}); + } + GA(z,BOX,zn,1,0); zv=AAV(z); + m=-1; cu=(I**)cv; + switch(b*k){ + case 1: GRPIX(UC,dv[k=*v++],j,k); break; + case 2: GRPIX(US,dv[k=*v++],j,k); break; + case SZI: GRPIX(I ,dv[k=*v++],j,k); break; + default: GRPIX(I , *v++ ,j,j); + } + EPILOG(z); +} /* (=AR(a)){B*b=(B*)av; k=bsum(n,b); R !k||n==k?vci(k?k:n):v2(*b?k:n-k,*b?n-k:k);} + if(s&&s<=MAX(2*n,65536)){A z;I*zv; + GA(z,INT,s,1,0); zv=AV(z); + GA(q,INT,s,1,0); qv=AV(q)-r; + u=qv+r; DO(s, *u++=0;); + switch(at){ + case LIT: KEYTALLY(UC); break; + case C2T: KEYTALLY(US); break; + case INT: KEYTALLY(I ); + } + AN(z)=*AS(z)=j; + EPILOG(z); + } + RZ(q=indexof(a,a)); + if(!AR(q))R iv1; + v=qv=AV(q); + u=qv; DO(n, ++*(qv+*u++);); + u=qv; DO(n, k=*u++; if(if; f=VAV(f)->f; b=CHEAD==ID(f); + if(at&B01&&1>=AR(a)){B*c,*d,*p=(B*)av;I i,j,m; + c=d=p; + if(*p){i=0; d=(B*)memchr(p,C0,n); j=d?d-p:0;} + else {j=0; c=(B*)memchr(p,C1,n); i=c?c-p:0;} + k=bsum(n,p); m=c&&d?2:1; + GA(x,INT,m,1,0); v=AV(x); *v++=MIN(i,j); if(c&&d)*v=MAX(i,j); + GA(y,INT,m,1,0); v=AV(y); *v++=if))f1=jtobqfslash; break; + case CBOX: f2=jtkeybox; break; + case CFORK: if(v->f1==(AF)jtmean){f2=jtkeymean; break;} + c=ID(v->f); d=ID(v->g); e=ID(v->h); + if(d==CCOMMA&&(c==CHEAD&&e==CPOUND||c==CPOUND&&e==CHEAD))f2=jtkeyheadtally; + }} + R fdef(CSLDOT,VERB, f1,f2, w,0L,h, flag, RMAX,RMAX,RMAX); +} diff --git a/ap.c b/ap.c new file mode 100644 --- /dev/null +++ b/ap.c @@ -0,0 +1,540 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Adverbs: Prefix and Infix */ + +#include "j.h" +#include "vasm.h" +#include "ve.h" + + +#define MINUSPA(b,r,u,v) r=b?u-v:u+v; +#define MINUSPZ(b,r,u,v) if(b)r=zminus(u,v); else r=zplus(u,v); +#define MINUSPX(b,r,u,v) if(b)r=xminus(u,v); else r=xplus(u,v); +#define MINUSPQ(b,r,u,v) if(b)r=qminus(u,v); else r=qplus(u,v); + +#define DIVPA(b,r,u,v) r=b?(!u&&!v?0:u/(D)v):u*v; +#define DIVPZ(b,r,u,v) if(b)r=zdiv(u,v); else r=ztymes(u,v); + +#define PREFIXPFX(f,Tz,Tx,pfx) \ + AHDRP(f,Tz,Tx){I d=c/n,i;Tz v,*y; \ + if(1==d)DO(m, *z++=v= *x++; DO(n-1, *z=v=pfx(v,*x); ++z; ++x;)) \ + else for(i=0;i >: +: *: */ + +AHDRP( gtpfxB,B,B){pscangt(m,c,n,z,x,C0,C1,C0,C0);} +AHDRP( gepfxB,B,B){pscangt(m,c,n,z,x,C1,C0,C1,C1);} +AHDRP( norpfxB,B,B){pscangt(m,c,n,z,x,C1,C0,C1,C0);} +AHDRP(nandpfxB,B,B){pscangt(m,c,n,z,x,C0,C1,C0,C1);} + + +PREFIXOVF( pluspfxI, I, I, PLUSP, PLUSVV) +PREFIXOVF(tymespfxI, I, I, TYMESP,TYMESVV) + +AHDRP(minuspfxI,I,I){C er=0;I d=c/n,i,j,n1=n-1,*xx=x,*y,*zz=z; + if(1==d){ + if(1==n)DO(m, *z++=*x++;) + else DO(m, MINUSP(n,z,x); RER; z=zz+=c; x=xx+=c;); + }else for(i=0;irank&&jt->rank[1]rank[1]; jt->rank=0; R rank1ex(w,self,r,jtprefix);} + jt->rank=0; + R eachl(apv(IC(w),1L,1L),w,atop(fs,ds(CTAKE))); +} /* f\"r w for general f */ + +static DF1(jtgprefix){A h,*hv,z,*zv;I m,n,r; + RZ(w); + ASSERT(DENSE&AT(w),EVNONCE); + if(jt->rank&&jt->rank[1]rank[1]; jt->rank=0; R rank1ex(w,self,r,jtgprefix);} + jt->rank=0; + n=IC(w); + h=VAV(self)->h; hv=AAV(h); m=AN(h); + GA(z,BOX,n,1,0); zv=AAV(z); + DO(n, RZ(zv[i]=df1(take(sc(1+i),w),hv[i%m]));); + R ope(z); +} /* g\"r w for gerund g */ + +static DF1(jtpscan){A y,z;C id;I c,cv,f,m,n,r,rr[2],t,wn,wr,*ws,wt,zt;VF ado; + RZ(w); + wt=AT(w); + if(SPARSE&wt)R scansp(w,self,jtpscan); + wn=AN(w); wr=AR(w); r=jt->rank?jt->rank[1]:wr; f=wr-r; ws=AS(w); + m=prod(f,ws); c=m?AN(w)/m:prod(r,f+ws); n=r?ws[f]:1; + y=VAV(self)->f; id=vaid(VAV(y)->f); + if(2>n||!wn){if(id){jt->rank=0; R r?ca(w):reshape(over(shape(w),one),w);}else R prefix(w,self);} + vapfx(id,wt,&ado,&cv); + if(!ado)R prefix(w,self); + if((t=atype(cv))&&t!=wt)RZ(w=cvt(t,w)); + zt=rtype(cv); jt->rank=0; + GA(z,zt,wn,wr,ws); + ado(jt,m,c,n,AV(z),AV(w)); + if(jt->jerr)R jt->jerr==EWOV?(rr[1]=r,jt->rank=rr,pscan(w,self)):0; else R cv&VRI+VRD?cvz(cv,z):z; +} /* f/\"r w atomic f main control */ + + +static F2(jtseg){A z;I c,k,m,n,*u,zn; + RZ(a&&w); + if(INT&AT(a)){u=AV(a); m=*u; n=*(1+u);} else m=n=0; + c=aii(w); k=c*bp(AT(w)); RE(zn=mult(n,c)); + GA(z,AT(w),zn,MAX(1,AR(w)),AS(w)); *AS(z)=n; + if(ARELATIVE(w)){A*u=AAV(z),*v=AAV(w)+m; DO(n, *u++=(A)AABS(w,*v++););} + else MC(AV(z),CAV(w)+m*k,n*k); + R z; +} + +static A jtifxi(J jt,I m,A w){A z;I d,j,k,n,p,*x; + RZ(w); + p=ABS(m); n=IC(w); d=0>m?(I)((n+(D)p-1)/p):MAX(0,1+n-m); + GA(z,INT,2*d,2,0); *AS(z)=d; *(1+AS(z))=2; + x=AV(z); k=0>m?p:1; j=-k; DO(d, *x++=j+=k; *x++=p;); if(d)*--x=MIN(p,n-j); + R z; +} + +static DF2(jtinfix){PROLOG;DECLF;A x,z;I m; + PREF2(jtinfix); + if(a==ainf)R repeat(zero,w); + RE(m=i0(vib(a))); + RZ(x=ifxi(m,w)); + if(*AS(x))z=eachl(x,w,atop(fs,ac2(jtseg))); + else{A s;I r; + r=AR(w); r=MAX(0,r); GA(s,INT,r,1,0); if(r)ICPY(AV(s),AS(w),r); *AV(s)=0>m?0:m; + RZ(x=df1(reshape(s,filler(w)),fs)); + z=reshape(over(zero,shape(x)),x); + } + EPILOG(z); +} + +static DF2(jtinfix2){PROLOG;A f,x,y;B d;I c,m,n,n1,r,*s,t; + PREF2(jtinfix); + RE(m=i0(vib(a))); t=AT(w); n=IC(w); + if(!(2==m&&2<=n&&t&DENSE))R infix(a,w,self); + c=AN(w)/n; d=1&&t&DIRECT; r=AR(w); s=AS(w); n1=n-1; + if(d ){RZ(x=gah(r,w)); ICPY(AS(x),s,r); *AS(x)=n1; AN(x)=c*n1;} + else RZ(x=curtail(w)); + if(d&!(t&IS1BYTE)){RZ(y=gah(r,w)); ICPY(AS(y),s,r); *AS(y)=n1; AN(y)=c*n1; AK(y)=AK(w)+(I)w+c*bp(t)-(I)y;} + else RZ(y= behead(w)); + f=VAV(self)->f; f=VAV(f)->f; + EPILOG(df2(x,y,vaid(f)?f:qq(f,num[-1]))); +} /* 2 f/\w */ + +static DF2(jtginfix){A h,*hv,x,z,*zv;I d,m,n; + RE(m=i0(vib(a))); + RZ(x=ifxi(m,w)); + h=VAV(self)->h; hv=AAV(h); d=AN(h); + if(n=IC(x)){ + GA(z,BOX,n,1,0); zv=AAV(z); + DO(n, RZ(zv[i]=df1(seg(from(sc(i),x),w),hv[i%d]));); + R ope(z); + }else{A s; + RZ(s=AR(w)?shape(w):ca(iv0)); *AV(s)=ABS(m); + RZ(x=df1(reshape(s,filler(w)),*hv)); + R reshape(over(zero,shape(x)),x); +}} + +#define MCREL(uu,vv,n) {A*u=(A*)(uu),*v=(A*)(vv); DO((n), *u++=(A)AABS(wd,*v++););} + +static DF2(jtinfixd){A fs,z;C*x,*y;I c=0,d,k,m,n,p,q,r,*s,wd,wr,*ws,wt,zc; + F2RANK(0,RMAX,jtinfixd,self); + wr=AR(w); ws=AS(w); wt=AT(w); n=IC(w); + RE(m=i0(a)); p=m==IMIN?IMAX:ABS(m); + if(0>m){p=MIN(p,n); d=p?(n+p-1)/p:0;}else{ASSERT(IMAX-1>n-m,EVDOMAIN); d=MAX(0,1+n-m);} + if(fs=VAV(self)->f,CCOMMA==ID(fs)){RE(c=aii(w)); RE(zc=mult(p,c)); r=2;} + else{if(n)RE(c=aii(w)); zc=p; r=wr?1+wr:2;} + GA(z,wt,d*p*c,r,0); x=CAV(z); y=CAV(w); + s=AS(z); *s++=d; *s++=zc; ICPY(s,1+ws,r-2); + k=c*bp(wt); wd=(I)w*ARELATIVE(w); + if(AN(z))switch((0>m?2:0)+(wd?1:0)){ + case 0: q=p*k; DO(d, MC(x,y,q); x+=q; y+=k;); break; + case 1: q=p*k; DO(d, MCREL(x,y,p); x+=q; y+=k;); break; + case 2: MC(x,y,n*k); if(q=d*p-n)fillv(wt,q*c,x+n*k); break; + case 3: MCREL(x,y,n); if(q=d*p-n)fillv(wt,q*c,x+n*k); break; + } + R z; +} /* a[\w and a]\w and a,\w */ + + +#define SETZ {s=yv; DO(c, *zv++=*s++; );} +#define SETZD {s=yv; DO(c, *zv++=*s++/d;);} + +#define MOVSUMAVG(Tw,Ty,ty,Tz,tz,xd,SET) \ + {Tw*u,*v;Ty*s,x=0,*yv;Tz*zv; \ + GA(z,tz,c*(1+p),AR(w),AS(w)); *AS(z)=1+p; \ + zv=(Tz*)AV(z); u=v=(Tw*)AV(w); \ + if(1==c){ \ + DO(m, x+=*v++;); *zv++=xd; \ + DO(p, x+=(Ty)*v++-(Ty)*u++; *zv++=xd;); \ + }else{ \ + GA(y,ty,c,1,0); s=yv=(Ty*)AV(y); DO(c, *s++=0;); \ + DO(m, s=yv; DO(c, *s+++=*v++;);); SET; \ + DO(p, s=yv; DO(c, x=*s+++=(Ty)*v++-(Ty)*u++; *zv++=xd;);); \ + }} + +static A jtmovsumavg1(J jt,I m,A w,A fs,B avg){A y,z;D d=(D)m;I c,p,s,t,wt; + p=IC(w)-m; wt=AT(w); c=aii(w); + switch((wt&B01?0:wt&INT?2:4)+avg){ + case 0: MOVSUMAVG(B,I,INT,I,INT,x, SETZ ); break; + case 1: MOVSUMAVG(B,I,INT,D,FL, x/d,SETZD); break; + case 2: + irange(AN(w),AV(w),&s,&t); t=0=d*((D)s+(D)t); + if(t) MOVSUMAVG(I,I,INT,I,INT,x, SETZ ) + else MOVSUMAVG(I,D,FL, D,FL, x, SETZ ); break; + case 3: MOVSUMAVG(I,D,FL, D,FL, x/d,SETZD); break; + case 4: NAN0; MOVSUMAVG(D,D,FL, D,FL, x, SETZ ); NAN1; break; + case 5: NAN0; MOVSUMAVG(D,D,FL, D,FL, x/d,SETZD); NAN1; break; + } + R z; +} /* m +/\w or (if 0=avg) m (+/%#)\w (if 1=avg); bool or integer or float; 0jerr==EVNAN)RESETERR else R z; + R infix(sc(m),w,fs); +} + +static DF2(jtmovavg){I m; + PREF2(jtmovavg); + RE(m=i0(vib(a))); + if(0=); break; + case 2: MOVMINMAX(D,FL, inf ,<=); break; + case 3: MOVMINMAX(D,FL, infm,>=); + } + R z; +} /* a <./\w (0=max) or a >./\ (1=max); vector w; integer or float; 0f; x=VAV(x)->f; id=ID(x); + if(wt&B01)id=id==CMIN?CSTARDOT:id==CMAX?CPLUSDOT:id; + if(id==CBDOT&&(x=VAV(x)->f,INT&AT(x)&&!AR(x)))id=(C)*AV(x); + switch(0p)R infix(a,w,self); + d=0<=m0?1+p-m:(p+m-1)/m; c=aii(w); cm=c*m; b=0>m0&&0rank=0; + GA(z,zt,c*d,AR(w),AS(w)); *AS(z)=d; + if((t=atype(cv))&&t!=wt){RZ(w=cvt(t,w)); wt=AT(w);} + zv=CAV(z); zk=bp(zt)*c; + wv=CAV(w); wk=bp(wt)*(0<=m0?c:c*m); + DO(d-b, ado(jt,1L,cm,m,zv,wv); zv+=zk; wv+=wk;); + if(b)ado(jt,1L,c*(p%m),p%m,zv,wv); + if(jt->jerr==EWOV){RESETERR; R movfslash(a,cvt(FL,w),self);}else R z; +} /* a f/\w */ + +static DF1(jtiota1){R apv(IC(w),1L,1L);} + +F1(jtbslash){A f;AF f1=jtprefix,f2=jtinfix;V*v; + RZ(w); + if(NOUN&AT(w))R fdef(CBSLASH,VERB, jtgprefix,jtginfix, w,0L,fxeachv(1L,w), VGERL, RMAX,0L,RMAX); + v=VAV(w); f=VAV(w)->f; + switch(v->id){ + case CPOUND: + f1=jtiota1; break; + case CLEFT: case CRIGHT: case CCOMMA: + f2=jtinfixd; break; + case CFORK: + if(v->f1==(AF)jtmean)f2=jtmovavg; break; + case CSLASH: + f2=jtmovfslash; if(vaid(f))f1=jtpscan; + } + R ADERIV(CBSLASH,f1,f2,RMAX,0L,RMAX); +} + +A jtascan(J jt,C c,A w){RZ(w); R df1(w,bslash(slash(ds(c))));} diff --git a/ar.c b/ar.c new file mode 100644 --- /dev/null +++ b/ar.c @@ -0,0 +1,613 @@ +/* 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;jrank?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(rtbase+jt->ttop; + for(i=1;iIMAX?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 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 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 ); 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&&1rank?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(1jerr)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, 2rank?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/ 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;irank?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 v ) +SUFFIXBFX( gesfxB, GE, IGE, SGE, BGE, *x>=v ) +SUFFIXBFX( norsfxB, NOR, INOR, SNOR, BNOR, !(*x||v)) +SUFFIXBFX( nandsfxB, NAND,INAND,SNAND,BNAND,!(*x&&v)) + +SUFFIXOVF( plussfxI, I, I, PLUSS, PLUSVV) +SUFFIXOVF(minussfxI, I, I, MINUSS,MINUSVV) +SUFFIXOVF(tymessfxI, I, I, TYMESS,TYMESVV) + +SUFFICPFX( plussfxO, D, I, PLUS ) +SUFFICPFX(minussfxO, D, I, MINUS ) +SUFFICPFX(tymessfxO, D, I, TYMES ) + +SUFFIXPFX( plussfxB, I, B, PLUS ) +SUFFIXNAN( plussfxD, D, D, PLUS ) +SUFFIXNAN( plussfxZ, Z, Z, zplus ) +SUFFIXPFX( plussfxX, X, X, xplus ) +SUFFIXPFX( plussfxQ, Q, Q, qplus ) + +SUFFIXPFX(minussfxB, I, B, MINUS ) +SUFFIXNAN(minussfxD, D, D, MINUS ) +SUFFIXNAN(minussfxZ, Z, Z, zminus) + +SUFFIXPFX(tymessfxD, D, D, TYMES ) +SUFFIXPFX(tymessfxZ, Z, Z, ztymes) +SUFFIXPFX(tymessfxX, X, X, xtymes) +SUFFIXPFX(tymessfxQ, Q, Q, qtymes) + +SUFFIXNAN( divsfxD, D, D, DIV ) +SUFFIXNAN( divsfxZ, Z, Z, zdiv ) + +SUFFIXPFX( maxsfxI, I, I, MAX ) +SUFFIXPFX( maxsfxD, D, D, MAX ) +SUFFIXPFX( maxsfxX, X, X, XMAX ) +SUFFIXPFX( maxsfxQ, Q, Q, QMAX ) +SUFFIXPFX( maxsfxS, SB,SB,SBMAX ) + +SUFFIXPFX( minsfxI, I, I, MIN ) +SUFFIXPFX( minsfxD, D, D, MIN ) +SUFFIXPFX( minsfxX, X, X, XMIN ) +SUFFIXPFX( minsfxQ, Q, Q, QMIN ) +SUFFIXPFX( minsfxS, SB,SB,SBMIN ) + +SUFFIXPFX(bw0000sfxI, UI,UI, BW0000) +SUFFIXPFX(bw0001sfxI, UI,UI, BW0001) +SUFFIXPFX(bw0010sfxI, UI,UI, BW0010) +SUFFIXPFX(bw0011sfxI, UI,UI, BW0011) +SUFFIXPFX(bw0100sfxI, UI,UI, BW0100) +SUFFIXPFX(bw0101sfxI, UI,UI, BW0101) +SUFFIXPFX(bw0110sfxI, UI,UI, BW0110) +SUFFIXPFX(bw0111sfxI, UI,UI, BW0111) +SUFFIXPFX(bw1000sfxI, UI,UI, BW1000) +SUFFIXPFX(bw1001sfxI, UI,UI, BW1001) +SUFFIXPFX(bw1010sfxI, UI,UI, BW1010) +SUFFIXPFX(bw1011sfxI, UI,UI, BW1011) +SUFFIXPFX(bw1100sfxI, UI,UI, BW1100) +SUFFIXPFX(bw1101sfxI, UI,UI, BW1101) +SUFFIXPFX(bw1110sfxI, UI,UI, BW1110) +SUFFIXPFX(bw1111sfxI, UI,UI, BW1111) + + +static DF1(jtsuffix){DECLF;I r; + RZ(w); + if(jt->rank&&jt->rank[1]rank[1]; jt->rank=0; R rank1ex(w,self,r,jtsuffix);} + jt->rank=0; + R eachl(IX(IC(w)),w,atop(fs,ds(CDROP))); +} /* f\."r w for general f */ + +static DF1(jtgsuffix){A h,*hv,z,*zv;I m,n,r; + RZ(w); + if(jt->rank&&jt->rank[1]rank[1]; jt->rank=0; R rank1ex(w,self,jt->rank[1],jtgsuffix);} + jt->rank=0; + n=IC(w); + h=VAV(self)->h; hv=AAV(h); m=AN(h); + GA(z,BOX,n,1,0); zv=AAV(z); + DO(n, RZ(zv[i]=df1(drop(sc(i),w),hv[i%m]));); + R ope(z); +} /* g\."r w for gerund g */ + +#define SSGULOOP(T) \ + {T*v=(T*)zv; \ + for(i=0;if)->f; f2=VAV(fs)->f2; + r=AR(w)-1; n1=IC(w)-1; m=aii(w); t=AT(w); k=m*bp(t); + RZ(z=ca(w)); zv=CAV(z)+k*n1; + RZ(q=tail(w)); + RZ(y=gah(r,q)); ICPY(AS(y),AS(q),r); AK(y)=(I)zv-(I)y; zv-=k; + RZ(x=gah(r,q)); ICPY(AS(x),AS(q),r); AK(x)=(I)zv-(I)x; + old=jt->tbase+jt->ttop; + switch(r?0:k){ + case sizeof(C): SSGULOOP(C); break; + case sizeof(I): SSGULOOP(I); break; + case sizeof(S): SSGULOOP(S); break; +#if ! SY_64 + case sizeof(D): SSGULOOP(D); break; +#endif + case sizeof(Z): SSGULOOP(Z); break; + default: + for(i=0;irank&&jt->rank[1]rank[1],jtssg); + jt->rank=0; + fs=VAV(sv->f)->f; f2=VAV(fs)->f2; + n=IC(w); p=ARELATIVE(w); + if(DIRECT&AT(w)){RE(z=ssgu(w,self)); if(z)R z;} + GA(z,BOX,n,1,0); zv=n+AAV(z); + RZ(*--zv=q=tail(w)); yt=AT(q); yn=AN(q); yr=AR(q); ys=1+AS(w); + k=yn*bp(yt); v=CAV(w)+k*(n-1); + for(i=1;irank?jt->rank[1]:wr; f=wr-r; jt->rank=0; + wp=PAV(w); e=SPA(wp,e); RZ(ee=over(e,e)); + if(!equ(ee,CALL1(sf,ee,self))){ + RZ(x=denseit(w)); + rv[1]=r; jt->rank=rv; RZ(z=CALL1(sf,x,self)); jt->rank=0; + R 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; DO(wr-f, m+=!b[j++];); + } + wp=PAV(w); e=SPA(wp,e); x=SPA(wp,x); + rv[1]=m; jt->rank=rv; RZ(x=CALL1(sf,x,self)); jt->rank=0; + t=maxtype(AT(e),AT(x)); RZ(e=cvt(t,e)); if(t!=AT(x))RZ(x=cvt(t,x)); + GA(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;C id;I c,cv,f,m,n,r,rr[2],t,wn,wr,*ws,wt,zt;VF ado; + RZ(w); + wt=AT(w); + if(SPARSE&wt)R scansp(w,self,jtsscan); + wn=AN(w); wr=AR(w); r=jt->rank?jt->rank[1]:wr; f=wr-r; ws=AS(w); + m=prod(f,ws); c=m?AN(w)/m:prod(r,f+ws); n=r?ws[f]:1; + y=VAV(self)->f; id=vaid(VAV(y)->f); + if(2>n||!wn){if(id){jt->rank=0; R r?ca(w):reshape(over(shape(w),one),w);}else R suffix(w,self);} + vasfx(id,wt,&ado,&cv); + if(!ado)R ssg(w,self); + if((t=atype(cv))&&t!=wt)RZ(w=cvt(t,w)); + zt=rtype(cv); jt->rank=0; + GA(z,zt,wn,wr,ws); + ado(jt,m,c,n,AV(z),AV(w)); + if(jt->jerr)R jt->jerr==EWOV?(rr[1]=r,jt->rank=rr,sscan(w,self)):0; else R cv&VRI+VRD?cvz(cv,z):z; +} /* f/\."r w main control */ + + +static F2(jtomask){A c,r,x,y;I m,n,p; + RZ(a&&w); + RE(m=i0(a)); p=ABS(m); n=IC(w); + r=sc(0>m?(n+p-1)/p:MAX(0,1+n-m)); c=tally(w); + x=reshape(sc(p), zero); + y=reshape(0>m?c:r,one ); + R reshape(over(r,c),over(x,y)); +} + +static DF2(jtgoutfix){A h,*hv,x,z,*zv;I m,n; + RZ(x=omask(a,w)); + n=IC(x); + h=VAV(self)->h; hv=AAV(h); m=AN(h); + GA(z,BOX,n,1,0); zv=AAV(z); + DO(n, RZ(zv[i]=df1(repeat(from(sc(i),x),w),hv[i%m]));); + R ope(z); +} + +static AS2(jtoutfix, eachl(omask(a,w),w,atop(fs,ds(CPOUND)))) + +static DF2(jtofxinv){A f,fs,z;C c;I t;V*v; + F2RANK(0,RMAX,jtofxinv,self); + fs=VAV(self)->f; f=VAV(fs)->f; v=VAV(f); c=v->id; t=AT(w); + if(!(c==CPLUS||c==CBDOT&&t&INT||(c==CEQ||c==CNE)&&t&B01))R outfix(a,w,self); + z=irs2(df1(w,fs),df2(a,w,bslash(fs)),0L,RMAX,-1L,c==CPLUS?(AF)jtminus:v->f2); + if(jt->jerr==EVNAN){RESETERR; R outfix(a,w,self);}else R z; +} /* a f/\. w where f has an "inverse" */ + +static DF2(jtofxassoc){A f,i,j,p,s,x,z;C id,*zv;I c,cv,d,k,kc,m,r,t;V*v;VF ado; + F2RANK(0,RMAX,jtofxassoc,self); + m=IC(w); RE(k=i0(a)); c=ABS(k); + f=VAV(self)->f; x=VAV(f)->f; v=VAV(x); id=CBDOT==v->id?(C)*AV(v->f):v->id; + if(k==IMIN||m<=c||id==CSTARDOT&&!(B01&AT(w)))R outfix(a,w,self); + if(-1<=k){d=m-c; RZ(i=apv(d,0L, 1L)); RZ(j=apv(d,c,1L));} + else {d=(m-1)/c; RZ(i=apv(d,c-1,c )); RZ(j=apv(d,c,c ));} + RZ(p=from(i,df1(w,bslash(f)))); + RZ(s=from(j,df1(w,bsdot(f)))); + r=AR(p); c=aii(p); t=AT(p); k=bp(t); kc=k*c; + RZ(var(id,p,p,t,t,&ado,&cv)); + ASSERTSYS(ado,"ofxassoc"); + GA(z,t,c*(1+d),r,AS(p)); *AS(z)=1+d; zv=CAV(z); + MC(zv, AV(s), kc); /* {.s */ + if(1jerr==EWOV){RESETERR; R ofxassoc(a,cvt(FL,w),self);}else R z; +} /* a f/\. w where f is an atomic associative fn */ + +static DF1(jtiota1rev){R apv(IC(w),IC(w),-1L);} + +F1(jtbsdot){A f;AF f1=jtsuffix,f2=jtoutfix;C id;V*v; + RZ(w); + if(NOUN&AT(w))R fdef(CBSLASH,VERB, jtgsuffix,jtgoutfix, w,0L,fxeachv(1L,w), VGERL, RMAX,0L,RMAX); + v=VAV(w); + switch(v->id){ + case CPOUND: f1=jtiota1rev; break; + case CSLASH: + f1=jtsscan; + f=v->f; id=ID(f); if(id==CBDOT){f=VAV(f)->f; if(INT&AT(f)&&!AR(f))id=(C)*AV(f);} + switch(id){ + case CPLUS: case CEQ: case CNE: case CBW0110: case CBW1001: + f2=jtofxinv; break; + case CSTAR: case CMAX: case CMIN: case CPLUSDOT: case CSTARDOT: + case CBW0000: case CBW0001: case CBW0011: case CBW0101: case CBW0111: case CBW1111: + f2=jtofxassoc; + }} + R ADERIV(CBSDOT,f1,f2,RMAX,0,RMAX); +} diff --git a/au.c b/au.c new file mode 100644 --- /dev/null +++ b/au.c @@ -0,0 +1,79 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Adverbs: Utilities */ + +#include "j.h" + + +static I jtfdepger(J jt,A w){A*wv;I d=0,k,wd; + wv=AAV(w); wd=(I)w*ARELATIVE(w); + DO(AN(w), k=fdep(fx(WVR(i))); d=MAX(d,k);); + R d; +} + +I jtfdep(J jt,A w){A f,g;I d=0,k;V*v; + RZ(w); + v=VAV(w); + if(v->fdep)R v->fdep; + if(f=v->f) d=VERB&AT(f)?fdep(f):NOUN&AT(f)&&VGERL&v->flag?fdepger(f):0; + if(g=v->g){k=VERB&AT(g)?fdep(g):NOUN&AT(g)&&VGERR&v->flag?fdepger(g):0; d=MAX(d,k);} + if(CFORK==v->id){k=fdep(v->h); d=MAX(d,k);} + R v->fdep=1+d; +} /* function depth: 1 + max depth of components */ + +F1(jtfdepadv){RZ(w); ASSERT(VERB&AT(w),EVDOMAIN); R sc(fdep(w));} + + +DF1(jtdf1){RZ(self); R CALL1(VAV(self)->f1, w,self);} +DF2(jtdf2){RZ(self); R CALL2(VAV(self)->f2,a,w,self);} + +DF1(jtdfs1){A s=jt->sf,z; RZ(self); z=CALL1(VAV(self)->f1, w,jt->sf=self); jt->sf=s; R z;} +DF2(jtdfs2){A s=jt->sf,z; RZ(self); z=CALL2(VAV(self)->f2,a,w,jt->sf=self); jt->sf=s; R z;} + /* for monads and dyads that can possibly involve $: */ + +F1(jtself1){A z;I d=fdep(jt->sf); FDEPINC(d); z=df1( w,jt->sf); FDEPDEC(d); R z;} +F2(jtself2){A z;I d=fdep(jt->sf); FDEPINC(d); z=df2(a,w,jt->sf); FDEPDEC(d); R z;} + +A jtac1(J jt,AF f){R fdef(0,VERB, f,0L, 0L,0L,0L, 0L, RMAX,RMAX,RMAX);} +A jtac2(J jt,AF f){R fdef(0,VERB, 0L,f, 0L,0L,0L, 0L, RMAX,RMAX,RMAX);} + +F1(jtdomainerr1){ASSERT(0,EVDOMAIN);} +F2(jtdomainerr2){ASSERT(0,EVDOMAIN);} + +A jtfdef(J jt,C id,I t,AF f1,AF f2,A fs,A gs,A hs,I flag,I m,I l,I r){A z;V*v; + RE(0); + GA(z,t,1,0,0); v=VAV(z); + v->f1 =f1?f1:jtdomainerr1; /* monad C function */ + v->f2 =f2?f2:jtdomainerr2; /* dyad C function */ + v->f =fs; /* monad */ + v->g =gs; /* dyad */ + v->h =hs; /* fork right tine or other auxiliary stuff */ + v->flag =flag; + v->mr =m; /* monadic rank */ + v->lr =l; /* left rank */ + v->rr =r; /* right rank */ + v->fdep =0; /* function depth */ + v->id =id; /* spelling */ + R z; +} + +B nameless(A w){A f,g,h;C id;V*v; + if(!w||NOUN&AT(w))R 1; + v=VAV(w); + id=v->id; f=v->f; g=v->g; h=v->h; + R !(id==CTILDE&&NAME&AT(f)) && nameless(f) && nameless(g) && (id==CFORK?nameless(h):1); +} + +B jtprimitive(J jt,A w){A x=w;V*v; + RZ(w); + v=VAV(w); + if(CTILDE==v->id&&NOUN&AT(v->f))RZ(x=fix(w)); + R!VAV(x)->f; +} /* 1 iff w is a primitive */ + +B jtboxatop(J jt,A w){A x;C c;V*v; + RZ(w); + x=VAV(w)->f; v=VAV(x); c=v->id; + R COMPOSE(c)&&CBOX==ID(v->f); +} /* 1 iff "last" function in w is <@f */ diff --git a/bin/build_defs b/bin/build_defs new file mode 100755 --- /dev/null +++ b/bin/build_defs @@ -0,0 +1,29 @@ +#!/bin/bash +# compiles and runs c programs built by sym2ijs +# creates netdefs.ijs from netdefs.c +# creates hostdefs.ijs from hostdefs.c + +source bin/jconfig + +if [ $bits == 32 ] +then +suffix=".ijs" +else +suffix="_64.ijs" +fi + +rm -f defs/netdefs.ijs defs/hostdefs.ijs defs/temp +cc $M32 -D$un defs/netdefs.c -o defs/temp +defs/temp >defs/netdefs.ijs +cc $M32 -D$un defs/hostdefs.c -o defs/temp +defs/temp >defs/hostdefs.ijs +rm -f defs/temp + +if [ -e defs/hostdefs.ijs ] && [ -e defs/netdefs.ijs ] +then +cp defs/hostdefs.ijs j/system/defs/hostdefs_$lcun$suffix +cp defs/netdefs.ijs j/system/defs/netdefs_$lcun$suffix +echo success: new netdefs and hostdefs copied to j/system/defs +else +echo failed: build netdefs and/or hostdefs failed +fi diff --git a/bin/build_jconsole b/bin/build_jconsole new file mode 100755 --- /dev/null +++ b/bin/build_jconsole @@ -0,0 +1,12 @@ +#!/bin/bash +source bin/jconfig +make jconsole + +if [ -x jconsole ] +then +cp jconsole j/bin/. +echo success: jconsole created and copied to j/bin +else +echo failed: jconsole NOT created +fi + diff --git a/bin/build_libj b/bin/build_libj new file mode 100755 --- /dev/null +++ b/bin/build_libj @@ -0,0 +1,147 @@ +#!/bin/bash +TARGET=libj +source bin/jconfig + +LIBJ_OBJS="a.o \ +ab.o \ + af.o \ + ai.o \ + am.o \ + am1.o \ + amn.o \ + ao.o \ + ap.o \ + ar.o \ + as.o \ + au.o \ + c.o \ + ca.o \ + cc.o \ + cd.o \ + cf.o \ + cg.o \ + ch.o \ + cip.o \ + cl.o \ + cp.o \ + cpdtsp.o \ + cr.o \ + crs.o \ + ct.o \ + cu.o \ + cv.o \ + cx.o \ + d.o \ + dc.o \ + dss.o \ + dstop.o \ + dsusp.o \ +dtoa.o \ +f.o \ +f2.o \ +i.o \ +io.o \ +j.o \ +jdlllic.o \ +k.o \ +m.o \ +mbx.o \ +p.o \ +pv.o \ +px.o \ +r.o \ +rl.o \ +rt.o \ +s.o \ +sc.o \ +sl.o \ +sn.o \ +t.o \ +u.o \ +v.o \ +v0.o \ +v1.o \ +v2.o \ +va1.o \ +va2.o \ +va2s.o \ +vamultsp.o \ +vb.o \ +vbang.o \ +vbit.o \ +vcant.o \ +vchar.o \ +vcat.o \ +vcatsp.o \ +vcomp.o \ +vcompsc.o \ +vd.o \ +vdx.o \ +ve.o \ +vf.o \ +vfft.o \ +vfrom.o \ +vfromsp.o \ +vg.o \ +vgauss.o \ +vgcomp.o \ +vgranking.o \ +vgsort.o \ +vgsp.o \ +vi.o \ +viix.o \ +visp.o \ +vm.o \ +vo.o \ +vp.o \ +vq.o \ +vrand.o \ +vrep.o \ +vs.o \ +vsb.o \ +vt.o \ +vu.o \ +vx.o \ +vz.o \ +w.o \ +wc.o \ +wn.o \ +ws.o \ +x.o \ +x15.o \ +xa.o \ +xb.o \ +xc.o \ +xcrc.o \ +xd.o \ +xf.o \ +xfmt.o \ +xh.o \ +xi.o \ +xl.o \ +xo.o \ +xs.o \ +xt.o \ +xu.o " + +echo COMP $COMP +echo LINK $SOLINK +export LIBJ_OBJS + +echo takes minutes for a clean build +echo "running: make libj >& make.txt" +make libj >& make.txt + +# ignore incompatible pointer warnings (they are ok) +echo "(strip make.txt to errors and important warnings) > esum.txt" +cat make.txt | grep -Ev "assignment from incompatible pointer type|initialization from incompatible pointer type|-o|In function" > esum.txt + +cat esum.txt + +if [ -x libj.$SOSUFFIX ] +then +cp libj.$SOSUFFIX j/bin/. +echo success: libj.$SOSUFFIX created and copied to j/bin +else +echo failed: libj.$SOSUFFIX NOT created +fi diff --git a/bin/build_tsdll b/bin/build_tsdll new file mode 100755 --- /dev/null +++ b/bin/build_tsdll @@ -0,0 +1,11 @@ +#!/bin/bash +TARGET=libtsdll +source bin/jconfig +make tsdll + +if [ -x libj.$SOSUFFIX ] +then +echo success: libtsdll.$SOSUFFIX created +else +echo failed: libtsdll.$SOSUFFIX NOT created +fi diff --git a/bin/jconfig b/bin/jconfig new file mode 100755 --- /dev/null +++ b/bin/jconfig @@ -0,0 +1,73 @@ +# configuration for build shell scripts - edit to configure + +# bits 32 or 64 +bits=32 + +# readline 0 or 1 to enable jconsole line recall +readline=0 +LIBREADLINE="" + +# readline should be enabled if possible + +# remove # from next 2 lines to enable readline +# readline=1 +# LIBREADLINE=" -lreadline " + +# if link fails install readline or try one of next lines +# LIBREADLINE=" -ledit -lncurses " +# LIBREADLINE=" -ledit64 -lnccurses " + +# be careful with changes after this line + +un=`uname` +lcun=$( echo "$un" | tr -s '[:upper:]' '[:lower:]' ) + +if [ $un != Linux ] && [ $un != Darwin ] +then +echo jconfig: not Linux or Darwin - changes to jconfig and other files required +exit 1 +fi + +if [ $bits != 32 ] && [ $bits != 64 ] +then +echo jconfig: bits must be 32 or 64 +exit 1 +fi + +if [ $readline != 0 ] && [ $readline != 1 ] +then +echo jconfig: readline must be 0 or 1 +exit 1 +fi + +COMP=" -fPIC -O3 -fno-strict-aliasing -DNOASM " + +if [ $un == Linux ] +then +SOLINK=" -shared -W1,soname,libj.so -lm -ldl -o " +SOSUFFIX=so +fi + +if [ $un == Darwin ] +then +SOLINK=" -dynamiclib -lm -ldl -o " +SOSUFFIX=dylib +fi + +if [ $bits == 32 ] +then +COMP=" -m32 $COMP " +SOLINK=" -m32 $SOLINK " +M32=" -m32 " +else +COMP=" -D_UNIX64 $COMP " +M32="" +fi + +if [ $readline == 1 ] +then +COMP="-DREADLINE $COMP " +fi + +SOLINK=" $SOLINK $TARGET.$SOSUFFIX " +export COMP SOLINK M32 LIBREADLINE diff --git a/c.c b/c.c new file mode 100644 --- /dev/null +++ b/c.c @@ -0,0 +1,38 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Conjunctions */ + +#include "j.h" + + +static CS1(obv1, CALL1(f1, w,fs)) +static CS2(obv2, CALL2(f2,a,w,fs)) + +F2(jtobverse){ASSERTVV(a,w); R CDERIV(COBVERSE,obv1,obv2,mr(a),lr(a),rr(a));} + + +static DF1(ad1){DECLFG;A z;I od=jt->db; + RZ(w); + jt->db=0; z=CALL1(f1, w,fs); jt->db=od; + if(EWTHROW==jt->jerr)R 0; + RESETERR; + R z?z:CALL1(g1, w,gs); +} + +static DF2(ad2){DECLFG;A z;I od=jt->db; + RZ(a&&w); + jt->db=0; z=CALL2(f2,a,w,fs); jt->db=od; + if(EWTHROW==jt->jerr)R 0; + RESETERR; + R z?z:CALL2(g2,a,w,gs); +} + +F2(jtadverse){ASSERTVV(a,w); R CDERIV(CADVERSE,ad1,ad2,RMAX,RMAX,RMAX);} + + +static CS1(even1, halve(df1(w,folk(fs,ds(CPLUS ),atop(fs,gs))))) +static CS1(odd1, halve(df1(w,folk(fs,ds(CMINUS),atop(fs,gs))))) + +F2(jteven){ASSERTVV(a,w); R CDERIV(CEVEN,even1,0L, RMAX,0L,0L);} +F2(jtodd ){ASSERTVV(a,w); R CDERIV(CODD, odd1, 0L, RMAX,0L,0L);} diff --git a/ca.c b/ca.c new file mode 100644 --- /dev/null +++ b/ca.c @@ -0,0 +1,247 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Conjunctions: Atop and Ampersand */ + +#include "j.h" + + +static DF1(jtonf1){PROLOG;DECLFG;A z;I flag=sv->flag,m=jt->xmode; + PREF1(jtonf1); + if(primitive(gs))if(flag&VFLR)jt->xmode=XMFLR; else if(flag&VCEIL)jt->xmode=XMCEIL; + if(RAT&AT(w))RZ(w=pcvt(XNUM,w)); + z=CALL1(f1,CALL1(g1,w,gs),fs); + jt->xmode=m; + EPILOG(z); +} + +static DF2(jtuponf2){PROLOG;DECLFG;A z;I flag=sv->flag,m=jt->xmode; + RZ(a&&w); + if(primitive(gs))if(flag&VFLR)jt->xmode=XMFLR; else if(flag&VCEIL)jt->xmode=XMCEIL; + if(RAT&AT(a))RZ(a=pcvt(XNUM,a)); + if(RAT&AT(w))RZ(w=pcvt(XNUM,w)); + z=INT&AT(a)&&INT&AT(w)&&CDIV==ID(gs)?intdiv(a,w):CALL1(f1,CALL2(g2,a,w,gs),fs); + jt->xmode=m; + EPILOG(z); +} + +static X jtxmodpow(J jt,A a,A w,A h){A ox,z; + if(!(XNUM&AT(a)))RZ(a=cvt(XNUM,a)); + if(!(XNUM&AT(w)))RZ(w=cvt(XNUM,w)); + if(!(XNUM&AT(h)))RZ(h=cvt(XNUM,h)); + ox=jt->xmod; jt->xmod=h; + GA(z,XNUM,1,0,0); *XAV(z)=xpow(*XAV(a),*XAV(w)); + jt->xmod=ox; + RNE(z); +} + +#define DMOD 46340 /* <. %: _1+2^31 */ + +#if SY_64 +#define XMOD 3037000499 /* <. %: _1+2^63 */ +#else +#define XMOD 94906265 /* <. %: _1+2^53 */ +static I dmodpow(D x,I n,D m){D z=1; while(n){if(1&n)z=fmod(z*x,m); x=fmod(x*x,m); n>>=1;} R(I)z;} +#endif + +static I imodpow(I x,I n,I m){I z=1; while(n){if(1&n)z=(z*x)%m; x=(x*x)%m; n>>=1;} R z;} + +static DF2(jtmodpow2){A h;B b,c;I at,m,n,wt,x,z; + PREF2(jtmodpow2); + h=VAV(self)->h; + if(RAT&AT(a))RZ(a=pcvt(XNUM,a)) else if(!(AT(a)&INT+XNUM))RZ(a=pcvt(INT,a)); + if(RAT&AT(w))RZ(w=pcvt(XNUM,w)) else if(!(AT(w)&INT+XNUM))RZ(w=pcvt(INT,w)); + at=AT(a); wt=AT(w); + if((AT(h)&XNUM||at&XNUM||wt&XNUM)&&at&XNUM+INT&&wt&INT+XNUM){A z; + z=xmodpow(a,w,h); if(!jt->jerr)R z; RESETERR; R residue(h,expn2(a,w)); + } + n=*AV(w); + if(!(INT&at&&INT&wt&&0<=n))R residue(h,expn2(a,w)); + m=*AV(h); x=*AV(a); + if(!m)R expn2(a,w); + if(XMODm)m=-m; + if(c=0>x)x=-x; x=x%m; if(c)x=m-x; +#if SY_64 + z=imodpow(x,n,m); +#else + z=m>DMOD?dmodpow((D)x,n,(D)m):imodpow(x,n,m); +#endif + R sc(b?z-m:z); +} /* a m&|@^ w ; m guaranteed to be INT or XNUM */ + +static DF1(jtmodpow1){A g=VAV(self)->g; R rank2ex(VAV(g)->f,w,self,0L,0L,jtmodpow2);} + /* m&|@(n&^) w ; m guaranteed to be INT or XNUM */ + +static CS1(on1, CALL1(f1,CALL1(g1,w,gs),fs)) +static CS2(jtupon2,CALL1(f1,CALL2(g2,a,w,gs),fs)) + +static DF2(on2){PROLOG;DECLFG;A ga,gw,z; + PREF2(on2); + gw=CALL1(g1,w,gs); + ga=CALL1(g1,a,gs); + z=CALL2(f2,ga,gw,fs); + EPILOG(z); +} + +static DF2(atcomp){AF f; + RZ(a&&w); + f=atcompf(a,w,self); + R f?f(jt,a,w,self):upon2(a,w,self); +} + +static DF2(atcomp0){A z;AF f;D oldct=jt->ct; + RZ(a&&w); + f=atcompf(a,w,self); + jt->ct=0; z=f?f(jt,a,w,self):upon2(a,w,self); jt->ct=oldct; + R z; +} + +F2(jtatop){A f,g,h=0,x;AF f1=on1,f2=jtupon2;B b=0,j;C c,d,e;I flag=0,m=-1;V*av,*wv; + ASSERTVV(a,w); + av=VAV(a); c=av->id; + wv=VAV(w); d=wv->id; + switch(c){ + case CNOT: if(d==CMATCH){f2=jtnotmatch; flag+=VIRS2;} break; + case CGRADE: if(d==CGRADE){f1=jtranking; flag+=VIRS1;} break; + case CSLASH: if(d==CCOMMA)f1=jtredravel; break; + case CCEIL: f1=jtonf1; f2=jtuponf2; flag=VCEIL; break; + case CFLOOR: f1=jtonf1; f2=jtuponf2; flag=VFLR; break; + case CICAP: if(d==CNE)f1=jtnubind; else if(FIT0(CNE,wv))f1=jtnubind0; break; + case CQUERY: if(d==CDOLLAR||d==CPOUND)f2=jtrollk; break; + case CQRYDOT: if(d==CDOLLAR||d==CPOUND)f2=jtrollkx; break; + case CRAZE: if(d==CCUT&&boxatop(w)){f1=jtrazecut1; f2=jtrazecut2;} break; + case CSLDOT: if(d==CSLASH&&CSLASH==ID(av->f))f2=jtpolymult; break; + case CQQ: if(d==CTHORN&&CEXEC==ID(av->f)&&equ(zero,av->g))f1=jtdigits10; break; + case CEXP: if(d==CCIRCLE)f1=jtexppi; break; + case CAMP: + x=av->f; if(RAT&AT(x))RZ(x=pcvt(XNUM,x)); + if((d==CEXP||d==CAMP&&CEXP==ID(wv->g))&&AT(x)&INT+XNUM&&!AR(x)&&CSTILE==ID(av->g)){ + h=x; flag=VMOD; + if(d==CEXP)f2=jtmodpow2; else f1=jtmodpow1; + }} + if(d==CEBAR||d==CEPS||(b=FIT0(CEPS,wv))){ + f=av->f; g=av->g; e=ID(f); if(b)d=ID(wv->f); + if(c==CICAP)m=7; + else if(c==CSLASH)m=e==CPLUS?4:e==CPLUSDOT?5:e==CSTARDOT?6:-1; + else if(c==CAMP&&(g==zero||g==one)){j=*BAV(g); m=e==CIOTA?j:e==CICO?2+j:-1;} + switch(0<=m?d:-1){ + case CEBAR: f2=b?atcomp0:atcomp; flag=6+8*m; break; + case CEPS: f2=b?atcomp0:atcomp; flag=7+8*m; break; + }} + R fdef(CAT,VERB, f1,f2, a,w,h, flag, (I)wv->mr,(I)wv->lr,(I)wv->rr); +} + +F2(jtatco){A f,g;AF f1=on1,f2=jtupon2;B b=0;C c,d,e;I flag=0,j,m=-1;V*av,*wv; + ASSERTVV(a,w); + av=VAV(a); c=av->id; f=av->f; g=av->g; e=ID(f); + wv=VAV(w); d=wv->id; + switch(c){ + case CNOT: if(d==CMATCH){f2=jtnotmatch; flag+=VIRS2;} break; + case CGRADE: if(d==CGRADE){f1=jtranking; flag+=VIRS1;} break; + case CCEIL: f1=jtonf1; f2=jtuponf2; flag=VCEIL; break; + case CFLOOR: f1=jtonf1; f2=jtuponf2; flag=VFLR; break; + case CQUERY: if(d==CDOLLAR||d==CPOUND)f2=jtrollk; break; + case CQRYDOT: if(d==CDOLLAR||d==CPOUND)f2=jtrollkx; break; + case CICAP: m=7; if(d==CNE)f1=jtnubind; else if(FIT0(CNE,wv))f1=jtnubind0; break; + case CAMP: if(g==zero||g==one){j=*BAV(g); m=e==CIOTA?j:e==CICO?2+j:-1;} break; + case CSLASH: + if(vaid(f)&&vaid(w))f2=jtfslashatg; + if(d==CCOMMA)f1=jtredravel; else m=e==CPLUS?4:e==CPLUSDOT?5:e==CSTARDOT?6:-1; + break; + case CSEMICO: + if(d==CLBRACE)f2=jtrazefrom; + else if(d==CCUT){ + j=i0(wv->g); + if(CBOX==ID(wv->f)&&!j)f2=jtrazecut0; + else if(boxatop(w)&&j&&-2<=j&&j<=2){f1=jtrazecut1; f2=jtrazecut2;} + }} + if(0<=m){ + b=d==CFIT&&equ(zero,wv->g); + switch(b?ID(wv->f):d){ + case CEQ: f2=b?atcomp0:atcomp; flag=0+8*m; break; + case CNE: f2=b?atcomp0:atcomp; flag=1+8*m; break; + case CLT: f2=b?atcomp0:atcomp; flag=2+8*m; break; + case CLE: f2=b?atcomp0:atcomp; flag=3+8*m; break; + case CGE: f2=b?atcomp0:atcomp; flag=4+8*m; break; + case CGT: f2=b?atcomp0:atcomp; flag=5+8*m; break; + case CEBAR: f2=b?atcomp0:atcomp; flag=6+8*m; break; + case CEPS: f2=b?atcomp0:atcomp; flag=7+8*m; break; + }} + R fdef(CATCO,VERB, f1,f2, a,w,0L, flag, RMAX,RMAX,RMAX); +} + +F2(jtampco){AF f1=on1;C c,d;I flag=0;V*wv; + ASSERTVV(a,w); + c=ID(a); wv=VAV(w); d=wv->id; + if (c==CSLASH&&d==CCOMMA) f1=jtredravel; + else if(c==CRAZE&&d==CCUT&&boxatop(w))f1=jtrazecut1; + else if(c==CGRADE&&d==CGRADE) {f1=jtranking; flag+=VIRS1;} + R fdef(CAMPCO,VERB, f1,on2, a,w,0L, flag, RMAX,RMAX,RMAX); +} + +static DF1(withl){DECLFG; R jt->rank?irs2(fs,w,gs,AR(fs),jt->rank[1],g2):CALL2(g2,fs,w,gs);} +static DF1(withr){DECLFG; R jt->rank?irs2(w,gs,fs,jt->rank[1],AR(gs),f2):CALL2(f2,w,gs,fs);} + +static DF1(ixfixedleft ){V*v=VAV(self); R indexofprehashed(v->f,w,v->h);} +static DF1(ixfixedright ){V*v=VAV(self); R indexofprehashed(v->g,w,v->h);} + +static DF1(ixfixedleft0 ){A z;D old=jt->ct;V*v=VAV(self); + jt->ct=0.0; z=indexofprehashed(v->f,w,v->h); jt->ct=old; + R z; +} + +static DF1(ixfixedright0){A z;D old=jt->ct;V*v=VAV(self); + jt->ct=0.0; z=indexofprehashed(v->g,w,v->h); jt->ct=old; + R z; +} + +static DF2(with2){R df1(w,powop(self,a));} + +F2(jtamp){A h=0;AF f1=on1,f2=on2;B b;C c,d=0;D old=jt->ct;I flag=0,mode=-1,p,r;V*u,*v; + RZ(a&&w); + switch(CONJCASE(a,w)){ + default: ASSERTSYS(0,"amp"); + case NN: ASSERT(0,EVDOMAIN); + case NV: + f1=withl; v=VAV(w); c=v->id; + if(AN(a)&&AR(a)){ + if(b=c==CFIT&&equ(zero,v->g))c=ID(v->f); + mode=c==CIOTA?IIDOT:c==CICO?IICO:-1; + } + if(0<=mode){ + if(b){jt->ct=0.0; h=indexofsub(mode,a,mark); jt->ct=old; f1=ixfixedleft0;} + else { h=indexofsub(mode,a,mark); f1=ixfixedleft ;} + }else switch(c){ + case CWORDS: RZ(a=fsmvfya(a)); f1=jtfsmfx; break; + case CIBEAM: if(v->f&&v->g&&128==i0(v->f)&&3==i0(v->g)){RZ(h=crccompile(a)); f1=jtcrcfixedleft;} + } + R fdef(CAMP,VERB, f1,with2, a,w,h, flag, RMAX,RMAX,RMAX); + case VN: + f1=withr; + if(AN(w)&&AR(w)){ + v=VAV(a); c=v->id; p=v->flag%256; if(b=c==CFIT&&equ(zero,v->g))c=ID(v->f); + if(7==p%8)mode=II0EPS+p/8; /* (e.i.0:) etc. */ + else mode=c==CEPS?IEPS:c==CLESS?ILESS:-1; + } + if(0<=mode){ + if(b){jt->ct=0.0; h=indexofsub(mode,w,mark); jt->ct=old; f1=ixfixedright0;} + else { h=indexofsub(mode,w,mark); f1=ixfixedright ;} + } + R fdef(CAMP,VERB, f1,with2, a,w,h, flag, RMAX,RMAX,RMAX); + case VV: + v=VAV(w); c=v->id; r=v->mr; + if(c==CFORK||c==CAMP){ + if(c==CFORK)d=ID(v->h); + if(CIOTA==ID(v->g)&&(!d||d==CLEFT||d==CRIGHT)&&equ(alp,v->f)){ + u=VAV(a); d=u->id; + if(d==CLT||d==CLE||d==CEQ||d==CNE||d==CGE||d==CGT)f2=jtcharfn2; + }}else switch(ID(a)){ + case CGRADE: if(c==CGRADE){f1=jtranking; flag+=VIRS1;} break; + case CSLASH: if(c==CCOMMA)f1=jtredravel; break; + case CCEIL: f1=jtonf1; flag=VCEIL; break; + case CFLOOR: f1=jtonf1; flag=VFLR; break; + case CRAZE: if(c==CCUT&&boxatop(w))f1=jtrazecut1; + } + R fdef(CAMP,VERB, f1,f2, a,w,0L, flag, r,r,r); +}} diff --git a/cc.c b/cc.c new file mode 100644 --- /dev/null +++ b/cc.c @@ -0,0 +1,638 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Conjunctions: Cuts */ + +#include "j.h" + + +static DF1(jtcut01){DECLF;A h,x; + RZ(x=from(box(every(negate(shape(w)),0L,jtiota)),w)); + if(VGERL&sv->flag){h=sv->h; R df1(x,*AAV(h));}else R CALL1(f1,x,fs); +} /* f;.0 w */ + +static F2(jtcut02v){A z;I*av,e,j,k,m,t,wk; + m=AN(w); t=AT(w); wk=bp(t); + av=AV(a); j=av[0]; e=av[1]; k=ABS(e); + ASSERT(!e||-m<=j&&jj){j+=1+m-k; if(0>j){k+=j; j=0;}}else k=MIN(k,m-j); + GA(z,t,k,1,0); + MC(AV(z),CAV(w)+wk*j,wk*k); + R 0>e?reverse(z):z; +} /* a ];.0 vector */ + +static F2(jtcut02m){A z;C*u,*v;I*av,c,d,e0,e1,j0,j1,k0,k1,m0,m1,*s,t,wk; + s=AS(w); m0=s[0]; m1=s[1]; t=AT(w); wk=bp(t); + av=AV(a); + if(4==AN(a)){j0=av[0]; e0=av[2]; k0=ABS(e0); j1=av[1]; e1=av[3]; k1=ABS(e1);} + else {j0=av[0]; e0=av[1]; k0=ABS(e0); j1=0; e1=m1; k1=e1; } + ASSERT(!e0||-m0<=j0&&j0j0){j0+=1+m0-k0; if(0>j0){k0+=j0; j0=0;}}else k0=MIN(k0,m0-j0); + if(0>j1){j1+=1+m1-k1; if(0>j1){k1+=j1; j1=0;}}else k1=MIN(k1,m1-j1); + GA(z,t,k0*k1,2,0); s=AS(z); s[0]=k0; s[1]=k1; + u=CAV(z); c=wk*k1; + if(0>e0){d=-wk*m1; v=CAV(w)+wk*(j0*m1+j1+m1*(k0-1));} + else {d= wk*m1; v=CAV(w)+wk*(j0*m1+j1 );} + DO(k0, MC(u,v,c); u+=c; v+=d;); + R 0>e1?irs1(z,0L,1L,jtreverse):z; +} /* a ];.0 matrix */ + +static DF2(jtcut02){DECLF;A h=0,*hv,q,qq,*qv,y,z,*zv;C id;I*as,c,d,e,hn,i,ii,j,k,m,n,*u,*ws; + RZ(a&&w); + if(VGERL&sv->flag){h=sv->h; hv=AAV(h); hn=AN(h);} + id=h?0:ID(fs); d=h?0:id==CBOX?1:2; + if(1>=AR(a))RZ(a=lamin2(zero,a)); + RZ(a=vib(a)); + if(2==AR(a)&&(id==CLEFT||id==CRIGHT)&&AT(w)&B01+LIT+INT+FL+CMPX) + if (2==AN(a)&&1==AR(w))R cut02v(a,w); + else if(4>=AN(a)&&2==AR(w))R cut02m(a,w); + as=AS(a); m=AR(a)-2; RE(n=prod(m,as)); c=as[1+m]; u=AV(a); + ASSERT(2==as[m]&&c<=AR(w),EVLENGTH); + if(!n){ /* empty result; figure out result type */ + switch(d){ + case 0: y=df1(w,*hv); RESETERR; break; + case 1: y=ace; break; + case 2: y=CALL1(f1,w,fs); RESETERR; break; + } + GA(z,y?AT(y):B01,n,m,as); R z; + } + ws=AS(w); + GA(z,BOX,n,m,as); zv=AAV(z); + GA(q,BOX,c,1,0); qv=AAV(q); + GA(qq,BOX,1,0,0); *AAV(qq)=q; + for(ii=0;iij){j+=1+m-k; if(0>j){k+=j; j=0;}}else k=MIN(k,m-j); + RZ(qv[i]=0>e?apv(k,j+k-1,-1L):0==j&&k==m?ace:apv(k,j,1L)); + } + RZ(y=from(qq,w)); u+=c+c; + switch(d){ + case 0: RZ(*zv++=df1(y,hv[ii%hn])); break; + case 1: RZ(*zv++=y); break; + case 2: RZ(*zv++=CALL1(f1,y,fs)); break; + }} + R 1==d?z:ope(z); +} /* a f;.0 w */ + +DF2(jtrazecut0){A z;C*v,*wv,*zu,*zv;I ar,*as,*av,c,d,i,j,k,m,n,q,wt,zn; + RZ(a&&w); + n=AN(w); wt=AT(w); wv=CAV(w); + ar=AR(a); as=AS(a); m=2==ar?1:*as; + if(!((2==ar||3==ar)&&wt&IS1BYTE&&1==AR(w)))R raze(df2(a,w,cut(ds(CBOX),zero))); + ASSERT(2==as[ar-2]&&1==as[ar-1],EVLENGTH); + RZ(a=vib(a)); av=AV(a); + RZ(z=exta(wt,1L,1L,n/2)); zn=AN(z); zv=CAV(z); zu=zn+zv; + for(i=0;ig); + an=AN(a); av=AAV(a); ad=(I)a*ARELATIVE(a); ws=AS(w); + ASSERT(an<=AR(w),EVLENGTH); + GA(x,BOX,an,1,0); xv=AAV(x); + GA(y,BOX,an,1,0); yv=AAV(y); + for(i=0;i=AR(b),EVRANK); + if(!bn&&m){xv[i]=zero; RZ(yv[i]=sc(m));} + else{ + if(!(B01&AT(b)))RZ(b=cvt(B01,b)); + if(!AR(b)){if(*BAV(b)){RZ(xv[i]=IX(m)); RZ(yv[i]=reshape(sc(m),0f)&&(id1=ID(vf->g),id1==CBEHEAD||id1==CCTAIL)){ \ + GA(z,m?BOX:B01,m,1,0); za=AAV(z); \ + EACHC(d=d?d-1:0; GA(y,t,d*c,r,s); *AS(y)=d; MC(AV(y),id1==CBEHEAD?v1+k:v1,d*k); *za++=y;); \ + R z; \ + } \ + /* note: fall through */ \ + default: \ + if(!m){y=reitem(zero,w); R iota(over(zero,shape(h?df1(y,*hv):CALL1(f1,y,fs))));} \ + GA(z,BOX,m,1,0); za=AAV(z); j=0; \ + switch((wd?2:0)+(h?1:0)){ \ + case 0: EACHC(GA(y,t,d*c,r,s); *AS(y)=d; MC(AV(y),v1,d*k); RZ(*za++=CALL1(f1,y,fs)); ); break; \ + case 1: EACHC(GA(y,t,d*c,r,s); *AS(y)=d; MC(AV(y),v1,d*k); RZ(*za++=df1(y,hv[j])); j=(1+j)%hn;); break; \ + case 2: EACHC(GA(y,t,d*c,r,s); *AS(y)=d; MCREL(AV(y),v1,d); RZ(*za++=CALL1(f1,y,fs)); ); break; \ + case 3: EACHC(GA(y,t,d*c,r,s); *AS(y)=d; MCREL(AV(y),v1,d); RZ(*za++=df1(y,hv[j])); j=(1+j)%hn;); break; \ + } \ + EPILOG(ope(z)); \ + } + +#define EACHCUTSP(stmt) \ + if(pfx)for(i=m;i>=1;--i){q=yu[i-1]-yu[i ]; d=q-neg; v1=wv+k*(b+p); stmt; p+=q;} \ + else for(i=1;i<=m;++i){q=yu[i ]-yu[i-1]; d=q-neg; v1=wv+k*(b+p); stmt; p+=q;} + +static F1(jtcps){A z;P*wp,*zp; + GA(z,AT(w),1,AR(w),AS(w)); + zp=PAV(z); + wp=PAV(w); + SPB(zp,a,SPA(wp,a)); + SPB(zp,e,SPA(wp,e)); + SPB(zp,i,SPA(wp,i)); + R z; +} + +static A jtselx(J jt,A x,I r,I i){A z;I c,k; + c=aii(x); k=c*bp(AT(x)); + GA(z,AT(x),r*c,AR(x),AS(x)); *AS(z)=r; + MC(CAV(z),CAV(x)+i*k,r*k); + R z; +} /* (i+i.r){x */ + +static A jtsely(J jt,A y,I r,I i,I j){A z;I c,*s,*v; + c=*(1+AS(y)); + GA(z,INT,r*c,2,0); s=AS(z); s[0]=r; s[1]=c; + v=AV(z); + ICPY(v,AV(y)+i*c,r*c); + DO(r, *v-=j; v+=c;); + R z; +} /* ((i+i.r){y)-"1 ({:$y){.j */ + +static DF2(jtcut2); + +static DF2(jtcut2sx){PROLOG;DECLF;A h=0,*hv,y,yy;B b,neg,pfx,*u,*v;C id;I d,e,hn,m,n,p,t,yn,*yu,*yv;P*ap;V*vf; + PREF2(jtcut2sx); + n=IC(w); t=AT(w); m=*AV(sv->g); neg=0>m; pfx=m==1||m==-1; b=neg&&pfx; + RZ(a=a==mark?eps(w,take(num[pfx?1:-1],w)):DENSE&AT(a)?sparse1(a):a); + ASSERT(n==*AS(a),EVLENGTH); + ap=PAV(a); + if(!(equ(zero,SPA(ap,e))&&AN(SPA(ap,a))))R cut2(cvt(B01,a),w,self); + vf=VAV(fs); + if(VGERL&sv->flag){h=sv->h; hv=AAV(h); hn=AN(h); id=0;}else id=vf->id; + y=SPA(ap,i); yn=AN(y); yv=AV(y); u=v=BAV(SPA(ap,x)); e=m=0; + GA(yy,INT,1+yn,1,0); yu=AV(yy); *yu++=p=pfx?n:-1; + switch(pfx+(id==CLEFT||id==CRIGHT||id==CCOMMA?2:0)){ + case 0: DO(yn, if(*v){++m; *yu++= yv[v-u]; } ++v;); break; + case 1: v+=yn-1; DO(yn, if(*v){++m; *yu++= yv[v-u]; } --v;); break; + case 2: DO(yn, if(*v){++m; d=p; *yu++=p=yv[v-u]; e=MAX(e,p-d);} ++v;); break; + case 3: v+=yn-1; DO(yn, if(*v){++m; d=p; *yu++=p=yv[v-u]; e=MAX(e,d-p);} --v;); + } + yu=AV(yy); p=pfx?yu[m]:0; + if(t&DENSE){C*wv;I c,k,r,*s,wd; + r=MAX(1,AR(w)); s=AS(w); wv=CAV(w); c=aii(w); k=c*bp(t); wd=(I)w*ARELATIVE(w); + CUTSWITCH(EACHCUTSP) + }else if(id==CPOUND){A z;I i,*zi; + GA(z,INT,m,1,0); zi=AV(z); + if(pfx)for(i=m;i>=1;--i)*zi++=(yu[i-1]-yu[i ])-neg; + else for(i=1;i<=m;++i)*zi++=(yu[i ]-yu[i-1])-neg; + EPILOG(z); + }else{A a,ww,x,y,z,*za;I c,i,j,q,qn,r;P*wp,*wwp; + wp=PAV(w); a=SPA(wp,a); x=SPA(wp,x); y=SPA(wp,i); yv=AV(y); r=*AS(y); c=*(1+AS(y)); + RZ(ww=cps(w)); wwp=PAV(ww); + GA(z,BOX,m,1,0); za=AAV(z); + switch(AN(a)&&*AV(a)?2+pfx:pfx){ + case 0: + p=yu[0]; DO(r, if(p<=yv[c*i]){p=i; break;}); + for(i=1;i<=m;++i){ + j=yu[i]; DO(q=r-p, if(j=1;--i){ + j=yu[i-1]; DO(q=r-p, if(j<=yv[c*(p+i)]){q=i; break;}); qn=q; + if(neg){j=yu[i]; qn=0; DO(r-p, if(j=1;--i){ + q=yu[i-1]-yu[i]; *AS(ww)=q-neg; + SPB(wwp,x,irs2(apv(q-neg,p+neg,1L),x,0L,1L,-1L,jtfrom)); + RZ(*za++=h?df1(ww,hv[(i-1)%hn]):CALL1(f1,ww,fs)); + p+=q; if(1f; + RE(y=df1(zero,iden(VAV(fs)->f))); + if(ztg)),amp(fs,ds(COPE))); R 0;} + if(zt>AT(y))RE(y=cvt(zt,y)); + R CAV(y); +} /* pointer to identity element */ + +#define EACHCUT(stmt) \ + for(i=1;i<=m;++i){ \ + if(pfx&&i==m)q=p; \ + else{u=memchr(v+pfx,sep,p-pfx); u+=!pfx; q=u-v;} \ + d=q-neg; v1=wv+k*(b+n-p); \ + stmt; \ + p-=q; v=u; \ + } +#define EACHCUTG(stmt) \ + for(i=1;i<=m;++i){ \ + if(pfx&&i==m)q=p; \ + else{u=memchr(v+pfx,sep,p-pfx); u+=!pfx; q=u-v;} \ + d=q-neg; v1=wv+k*(b+n-p); \ + old=jt->tbase+jt->ttop; \ + GA(y,wt,d*c,r,s); *AS(y)=d; \ + stmt; \ + if(allbx&&!AR(y)&&BOX&AT(y))*za++=y=*AAV(y); \ + else if(!allbx)*za++=y; \ + else{I ii=i-1; \ + allbx=0; \ + za=AAV(z); DO(ii, RZ(*za++=box(*za));); *za++=y; \ + old=jt->tbase+jt->ttop; \ + } \ + gc(y,old); \ + p-=q; v=u; \ + } + +/* locals in cut2: */ +/* b 1 iff _1 cut */ +/* c atoms in an item of w */ +/* d adjusted length of current cut */ +/* e max width of a cut */ +/* h gerund */ +/* hv gerund */ +/* id function code */ +/* k # bytes in an item of w */ +/* m # of cuts */ +/* n #a and #w */ +/* neg 1 iff _1 or _2 cut */ +/* p remaining length in a */ +/* pfx 1 iff 1 or _1 cut */ +/* q length of current cut */ +/* sep the cut character */ +/* u ptr to a for next cut */ +/* v ptr to a for current cut */ +/* v1 ptr to w for current cut */ +/* wd 1 iff w is relative */ + +static DF2(jtcut2){PROLOG;DECLF;A h=0,*hv,y,z=0,*za;B b,neg,pfx;C id,id1,sep,*u,*v,*v1,*wv,*zc; + I c,cv,e=0,d,hn,i,k,ke,m=0,n,old,p,q,r,*s,wd,wt,*zi,*zs;V*vf;VF ado; + PREF2(jtcut2); + if(SB01&AT(a)||SPARSE&AT(w))R cut2sx(a,w,self); + p=n=IC(w); wt=AT(w); k=*AV(sv->g); neg=0>k; pfx=k==1||k==-1; b=neg&&pfx; + if(a!=mark){ + if(!AN(a)&&n){ + if(VGERL&sv->flag){h=sv->h; ASSERT(AN(h),EVLENGTH); h=*AAV(h); R CALL1(VAV(h)->f1,w,h);} + else R CALL1(f1,w,fs); + } + if(AN(a)&&BOX&AT(a))R cut2bx(a,w,self); + if(!(B01&AT(a)))RZ(a=cvt(B01,a)); + if(!AR(a))RZ(a=reshape(sc(n),a)); + v=CAV(a); sep=C1; + }else if(1>=AR(w)&&wt&IS1BYTE){a=w; v=CAV(a); sep=v[pfx?0:n-1];} + else{RZ(a=n?eps(w,take(num[pfx?1:-1],w)):mtv); v=CAV(a); sep=C1;} + ASSERT(n==IC(a),EVLENGTH); + vf=VAV(fs); + if(VGERL&sv->flag){h=sv->h; hv=AAV(h); hn=AN(h); id=0;}else id=vf->id; + r=MAX(1,AR(w)); s=AS(w); wv=CAV(w); c=aii(w); k=c*bp(wt); wd=(I)w*ARELATIVE(w); + switch(pfx+(id==CLEFT||id==CRIGHT||id==CCOMMA?2:0)){ + case 0: if(AT(a)&B01&&C1==sep)m=bsum(n,v); + else{--v; DO(n, if(sep==*++v) ++m; ); v=CAV(a);} break; + case 1: if(AT(a)&B01&&C1==*v )m=bsum(n,v); + else{u=v+=n; DO(n, if(sep==*--v){++m; u=v;}); p-=u-v; v=u;} break; + case 2: u=--v; DO(n, if(sep==*++v){++m; e=MAX(e,v-u); u=v;}); v=CAV(a); break; + case 3: u=v+=n; DO(n, if(sep==*--v){++m; e=MAX(e,u-v); u=v;}); p-=u-v; v=u; + } + switch(wd?0:id){ + case CPOUND: + GA(z,INT,m,1,0); zi=AV(z); EACHCUT(*zi++=d;); + break; + case CDOLLAR: + GA(z,INT,m,1,0); zi=AV(z); EACHCUT(*zi++=d;); + R irs2(z,vec(INT,MAX(0,r-1),1+s),0L,0L,1L,jtover); + case CHEAD: + GA(z,wt,m*c,r,s); zc=CAV(z); *AS(z)=m; + EACHCUT(if(d)MC(zc,v1,k); else fillv(wt,c,zc); zc+=k;); + break; + case CTAIL: + GA(z,wt,m*c,r,s); zc=CAV(z); *AS(z)=m; + EACHCUT(if(d)MC(zc,v1+k*(d-1),k); else fillv(wt,c,zc); zc+=k;); + break; + case CCOMMA: + case CLEFT: + case CRIGHT: + e-=e&&neg; RE(d=mult(m*c,e)); + GA(z,wt,d,id==CCOMMA?2:1+r,s-1); zc=CAV(z); fillv(wt,d,zc); + zs=AS(z); zs[0]=m; zs[1]=id==CCOMMA?e*c:e; ke=k*e; + EACHCUT(MC(zc,v1,d*k); zc+=ke;); + break; + case CBOX: + GA(z,m?BOX:B01,m,1,0); za=AAV(z); + EACHCUT(GA(y,wt,d*c,r,s); *AS(y)=d; MC(AV(y),v1,d*k); *za++=y;); + break; + case CAT: case CATCO: case CAMP: case CAMPCO: + if(CBOX==ID(vf->f)&&(id1=ID(vf->g),id1==CBEHEAD||id1==CCTAIL)){ + GA(z,m?BOX:B01,m,1,0); za=AAV(z); + EACHCUT(d=d?d-1:0; GA(y,wt,d*c,r,s); *AS(y)=d; MC(AV(y),id1==CBEHEAD?v1+k:v1,d*k); *za++=y;); + } + break; + case CSLASH: + vains(vaid(vf->f),wt,&ado,&cv); + if(ado){C*z0=0,*zc;I t,zk,zt; + zt=rtype(cv); + GA(z,zt,m*c,r,s); *AS(z)=m; + if(!AN(z))R z; + zc=CAV(z); zk=c*bp(zt); + if((t=atype(cv))&&t!=wt){RZ(w=cvt(t,w)); wv=CAV(w);} + EACHCUT(if(d)ado(jt,1L,d*c,d,zc,v1); else{if(!z0){z0=idenv0(a,w,sv,zt,&y); + if(!z0){if(y)R y; else break;}} mvc(zk,zc,zk/c,z0);} zc+=zk;); + if(jt->jerr)R jt->jerr==EWOV?cut2(a,w,self):0; else R cv&VRI+VRD?cvz(cv,z):z; + }} + if(!z){B allbx=1; + if(!m){y=reitem(zero,w); y=h?df1(y,*hv):CALL1(f1,y,fs); RESETERR; R iota(over(zero,shape(y?y:mtv)));} + GA(z,BOX,m,1,0); za=AAV(z); + switch((wd?2:0)+(h?1:0)){ + case 0: EACHCUTG(MC(AV(y),v1,d*k); RZ(y=CALL1(f1,y,fs)); ); break; + case 1: EACHCUTG(MC(AV(y),v1,d*k); RZ(y=df1(y,hv[(i-1)%hn]));); break; + case 2: EACHCUTG(MCREL(AV(y),v1,d); RZ(y=CALL1(f1,y,fs)); ); break; + case 3: EACHCUTG(MCREL(AV(y),v1,d); RZ(y=df1(y,hv[(i-1)%hn]));); + } + if(!allbx)RZ(z=ope(z)); + } + EPILOG(z); +} /* f;.1 f;._1 f;.2 f;._2 monad and dyad */ + +static DF1(jtcut1){R cut2(mark,w,self);} + + +#define PSCASE(id,zt,wt) ((id)+256*(zt)+4096*(wt)) +#define PSLOOP(Tz,Tw,F,v0) \ + {C*u;Tw*wv;Tz s=v0,x,*zv; \ + GA(z,zt,n,1,0); \ + u=m+av; wv=m+(Tw*)AV(w); zv=m+(Tz*)AV(z); \ + switch(pfx+2*(id==CBSLASH)){ \ + case 0: DO(n, x=*--wv; if(*--u)s=v0; *--zv=F; ); break; /* <@(f/\.);.2 */ \ + case 1: DO(n, x=*--wv; *--zv=F; if(*--u)s=v0;); break; /* <@(f/\.);.1 */ \ + case 2: DO(n, x=*wv++; *zv++=F; if(*u++)s=v0;); break; /* <@(f/\ );.2 */ \ + case 3: DO(n, x=*wv++; if(*u++)s=v0; *zv++=F; ); break; /* <@(f/\ );.1 */ \ + }} + +static A jtpartfscan(J jt,A a,A w,I cv,B pfx,C id,C ie){A z=0;B*av;I m,n,zt; + n=AN(w); m=id==CBSDOT?n:0; zt=rtype(cv); av=BAV(a); + switch(PSCASE(ie,zt,AT(w))){ + case PSCASE(CPLUS, INT,B01): PSLOOP(I,B,s+=x, 0 ); break; + case PSCASE(CPLUS, FL, FL ): NAN0; PSLOOP(D,D,s+=x, 0.0 ); NAN1; break; + case PSCASE(CMAX, INT,INT): PSLOOP(I,I,s=MAX(s,x),IMIN); break; + case PSCASE(CMAX, FL, FL ): PSLOOP(D,D,s=MAX(s,x),-inf); break; + case PSCASE(CMIN, INT,INT): PSLOOP(I,I,s=MIN(s,x),IMAX); break; + case PSCASE(CMIN, FL, FL ): PSLOOP(D,D,s=MIN(s,x),inf ); break; + case PSCASE(CMAX, B01,B01): + case PSCASE(CPLUSDOT,B01,B01): PSLOOP(B,B,s|=x, 0 ); break; + case PSCASE(CMIN, B01,B01): + case PSCASE(CSTARDOT,B01,B01): PSLOOP(B,B,s&=x, 1 ); break; + case PSCASE(CNE, B01,B01): PSLOOP(B,B,s^=x, 0 ); break; + case PSCASE(CEQ, B01,B01): PSLOOP(B,B,s=s==x, 1 ); break; + } + R z; +} /* [: ; <@(ie/\);.k on vector w */ + +DF2(jtrazecut2){A fs,gs,x,y,z=0;B b,neg,pfx;C id,ie=0,sep,*u,*v,*wv,*zv;I c,cv=0,d,k,m=0,n,p,q,r,*s,wt; + V*fv,*sv,*vv;VF ado=0; + RZ(a&&w); + sv=VAV(self); gs=CFORK==sv->id?sv->h:sv->g; vv=VAV(gs); y=vv->f; fs=VAV(y)->g; + p=n=IC(w); wt=AT(w); k=*AV(vv->g); neg=0>k; pfx=k==1||k==-1; b=neg&&pfx; + fv=VAV(fs); id=fv->id; + if((id==CBSLASH||id==CBSDOT)&&(vv=VAV(fv->f),CSLASH==vv->id)){ + ie=vaid(vv->f); + if(id==CBSLASH)vapfx(ie,wt,&ado,&cv); /* [: ; <@(f/\ );.n */ + else vasfx(ie,wt,&ado,&cv); /* [: ; <@(f/\.);.n */ + } + if(SPARSE&AT(w))R raze(cut2(a,w,gs)); + if(a!=mark){ + if(!(AN(a)&&1==AR(a)&&AT(a)&B01+SB01))R raze(cut2(a,w,gs)); + if(AT(a)&SB01)RZ(a=cvt(B01,a)); + v=CAV(a); sep=C1; + }else if(1>=AR(w)&&wt&IS1BYTE){a=w; v=CAV(a); sep=v[pfx?0:n-1];} + else{RZ(a=n?eps(w,take(num[pfx?1:-1],w)):mtv); v=CAV(a); sep=C1;} + ASSERT(n==IC(a),EVLENGTH); + r=MAX(1,AR(w)); s=AS(w); wv=CAV(w); c=aii(w); k=c*bp(wt); + if(pfx){u=v+n; while(u>v&&sep!=*v)++v; p=u-v;} + if(ado){I t,zk,zt; /* atomic function f/\ or f/\. */ + if((t=atype(cv))&&t!=wt){RZ(w=cvt(t,w)); wv=CAV(w);} + zt=rtype(cv); zk=c*bp(zt); + if(1==r&&!neg&&B01&AT(a)&&p==n&&v[pfx?0:n-1]){RE(z=partfscan(a,w,cv,pfx,id,ie)); if(z)R z;} + GA(z,zt,AN(w),r,s); zv=CAV(z); + while(p){ + if(u=memchr(v+pfx,sep,p-pfx))u+=!pfx; else{if(!pfx)break; u=v+p;} + q=u-v; + if(d=q-neg){ + ado(jt,1L,c*d,d,zv,wv+k*(b+n-p)); + if(jt->jerr)R jt->jerr==EWOV?razecut2(a,w,self):0; + m+=d; zv+=d*zk; + } + p-=q; v=u; + }}else{B b1=0;I old,wc=c,yk,ym,yr,*ys,yt; /* general f */ + RZ(x=gah(r,w)); ICPY(AS(x),s,r); + while(p){ + if(u=memchr(v+pfx,sep,p-pfx))u+=!pfx; else{if(!pfx)break; u=v+p;} + q=u-v; d=q-neg; + *AS(x)=d; AN(x)=wc*d; AK(x)=(wv+k*(b+n-p))-(C*)x; + old=jt->tbase+jt->ttop; + RZ(y=df1(x,fs)); ym=IC(y); + if(!z){yt=AT(y); yr=AR(y); ys=AS(y); c=aii(y); yk=c*bp(yt); GA(z,yt,n*c,MAX(1,yr),ys); *AS(z)=n; zv=CAV(z);} + if(!(yt==AT(y)&&yr==AR(y)&&(1>=yr||!ICMP(1+AS(y),1+ys,yr-1)))){z=0; break;} + while(IC(z)<=m+ym){RZ(z=ext(0,z)); zv=CAV(z); b1=0;} + memcpy(zv+m*yk,CAV(y),ym*yk); + if(b1)gc(yt&DIRECT?0:y,old); + b1=1; m+=ym; p-=q; v=u; + } + if(!b1&&ie)GA(z,wt,AN(w),r,s); + } + if(z){*AS(z)=m; AN(z)=m*c; R cv&VRI+VRD?cvz(cv,z):z;} + else R raze(cut2(B01&AT(a)?a:eq(scc(sep),a),w,gs)); +} /* ;@(<@f);.n or ([: ; <@f;.n) , monad and dyad */ + +DF1(jtrazecut1){R razecut2(mark,w,self);} + + +static A jttesos(J jt,A a,A w,I n){A p;I*av,c,k,m,*pv,s,*ws; + RZ(a&&w); + c=*(1+AS(a)); av=AV(a); ws=AS(w); + GA(p,INT,c,1,0); pv=AV(p); + if(3==n)DO(c, m=av[i]; s=ws[i]; pv[i]=m?(s+m-1)/m:1&&s;) + else DO(c, m=av[i]; k=av[c+i]; s=ws[i]-ABS(k); pv[i]=0>s?0:m?(k||s%m)+s/m:1;); + R p; +} /* tesselation result outer shape */ + +static F2(jttesa){A x;I*av,c,d,k,p=IMAX,r,*s,t,*u,*v; + RZ(a&&w); + t=AT(a); + RZ(a=vib(a)); + r=AR(a); s=AS(a); c=r?s[r-1]:1; av=AV(a); d=AR(w); + ASSERT(d>=c&&(2>r||2==*s),EVLENGTH); + if(2<=r)DO(c, ASSERT(0<=av[i],EVDOMAIN);); + if(2==r&&c==d&&t&INT)R a; + GA(x,INT,2*d,2,0); s=AS(x); s[0]=2; s[1]=d; + u=AV(x); v=u+d; s=AS(w); + if(2==r)DO(c, *u++=av[i]; k=av[i+c]; *v++=k==p?s[i]:k==-p?-s[i]:k;); + if(2> r)DO(c, *u++=1; k=av[i]; *v++=k==p?s[i]:k==-p?-s[i]:k;); + s+=c; DO(d-c, *u++=0; *v++=*s++;); + R x; +} /* tesselation standardized left argument */ + +static A jttesmatu(J jt,A a,A w,A self,A p,B e){DECLF;A x,y,z,z0;C*u,*v,*v0,*wv,*yv,*zv; + I*av,i,k,m,mc,mi,mj,mr,nc,nr,old,*pv,r,s,*s1,sc,sj,sr,t,tc,tr,*ws,yc,yr,zk,zn,zr,*zs,zt; + ws=AS(w); t=AT(w); k=bp(t); r=k*ws[1]; + av=AV(a); pv=AV(p); wv=CAV(w); + nr=pv[0]; sr=av[2]; mr=av[0]; mi=r*mr; tr=ws[0]; + nc=pv[1]; sc=av[3]; mc=av[1]; mj=k*mc; sj=k*sc; + RZ(nr&&nc&&nr>=sr&&nc>=sc); + GA(y,t,sr*sc,2,2+av); yv=CAV(y); + u=yv; v=wv; DO(sr, MC(u,v,sj); u+=sj; v+=r;); + RZ(z0=CALL1(f1,y,fs)); zt=AT(z0); + RZ(zt&B01+LIT+INT+FL+CMPX); + zn=AN(z0); zr=AR(z0); zs=AS(z0); zk=zn*bp(zt); m=zr*SZI; + GA(z,zt,zn*nr*nc,2+zr,0); s1=AS(z); ICPY(s1,pv,2); ICPY(2+s1,zs,zr); zv=CAV(z); + old=jt->tbase+jt->ttop; + if(e) for(i=0;ig; n=*AV(gs); + RZ(p=tesos(a,w,n)); + if(DENSE&AT(w)&&2==AR(w)&&0<=av[2]&&0<=av[3]){ + RE(z=tesmatu(a,w,self,p,(B)(0>n))); + if(!z)z=tesmat(a,w,self,p,(B)(0>n)); + if(z&&!AN(z)){ + y=df1(w,VAV(self)->f); RESETERR; + t=y?AT(y):B01; + if(t!=AT(z))GA(z,t,0L,AR(z),AS(z)); + } + R z; + } + R cut02(irs2(cant1(tymes(head(a),cant1(abase2(p,iota(p))))), tail(a),0L,1L,1L,jtlamin2),w,self); +} + +static DF1(jttess1){A s;I m,r,*v; + RZ(w); + r=AR(w); RZ(s=shape(w)); v=AV(s); + m=IMAX; DO(r, if(m>v[i])m=v[i];); DO(r, v[i]=m;); + R tess2(s,w,self); +} + + +F2(jtcut){A h=0;I flag=0,k; + RZ(a&&w); + ASSERT(NOUN&AT(w),EVDOMAIN); + RZ(w=vi(w)); + RE(k=i0(w)); + if(NOUN&AT(a)){flag=VGERL; RZ(h=fxeachv(1L,a)); ASSERT(3!=k&&-3!=k,EVNONCE);} + switch(k){ + case 0: R fdef(CCUT,VERB, jtcut01,jtcut02, a,w,h, flag, RMAX,2L,RMAX); + case 1: case -1: + case 2: case -2: R fdef(CCUT,VERB, jtcut1, jtcut2, a,w,h, flag, RMAX,1L,RMAX); + case 3: case -3: R fdef(CCUT,VERB, jttess1,jttess2, a,w,h, flag, RMAX,2L,RMAX); + default: ASSERT(0,EVDOMAIN); +}} diff --git a/cd.c b/cd.c new file mode 100644 --- /dev/null +++ b/cd.c @@ -0,0 +1,568 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Conjunctions: Differentiation and Integration */ + +#include "j.h" + + +static B jtiscons(J jt,A w){A x;V*v; + RZ(w); + v=VAV(w); x=v->f; + R CQQ==v->id&&NOUN&AT(x)&&!AR(x); +} + +static C ispoly1[]={CLEFT,CRIGHT,CLE,CGE,CNOT,CMINUS,CPLUSCO,CHALVE,CCIRCLE,CJDOT,0}; + +static I jtispoly(J jt,A w){A e,f,g,h,x,y;B nf,ng,vf,vg;C c,id;I k,m,n,t;V*v; + RZ(w); + v=VAV(w); id=v->id; + if(id==CFCONS||iscons(w))R 1; + if(strchr(ispoly1,id))R 2; + if(id==CSTARCO)R 3; + f=v->f; nf=f&&NOUN&AT(f); vf=!nf; + g=v->g; ng=g&&NOUN&AT(g); vg=!ng; x=nf?f:g; t=x?AT(x):0; h=nf?g:f; c=h?ID(h):0; + if(id==CFORK){ + RZ(vf&&vg); + m=ispoly(f); n=ispoly(v->h); + switch(m&&n?ID(g):0){ + case CPLUS: R MAX(m,n); + case CSTAR: R m+n-1; + }} + if(vf&&vg&&(id==CAT||id==CATCO||id==CAMP||id==CAMPCO)){m=ispoly(f); n=ispoly(g); if(m&&n)R 1+(m-1)*(n-1);} + RZ(id==CAMP&&(t&NUMERIC||c==CPOLY)); + if(nf&&1>=AR(x)&&c==CPOLY){ + RZ(t&BOX+NUMERIC); + k=IC(x); + if(t&NUMERIC)R k; + y=*(AAV(x)+k-1); RZ(2>=AR(y)); + if(1>=AR(y))R 1+IC(y); + RZ(2==*(1+AS(y))); + RZ(e=irs1(y,0L,1L,jttail)); + RZ(equ(e,floor1(e))&&all1(le(zero,e))); + RZ(y=aslash(CMAX,cvt(INT,e))); + R 1+*AV(y); + } + if(nf==ng||AR(x))R 0; + if(c==CPLUS||c==CMINUS||c==CSTAR||c==CDIV&&ng)R 2; + RZ(x=pcvt(INT,x)); + if(!(INT&AT(x)))R 0; + k=*AV(x); + R 0<=k&&(c==CBANG&&nf||c==CEXP&&ng)?1+k:0; +} /* 1 + degree of polynomial (0 if not poly) */ + +static F1(jtfpolyc){A b;B*bv;I m,n; + RZ(b=ne(w,zero)); bv=BAV(b); + m=n=AN(w); DO(n, if(bv[--m])break;); ++m; + if(mn?1:1+n; RZ(f); R fpolyc(df1(IX(m),tdot(f)));} + +static F1(jtfnegate){V*v; RZ(w); v=VAV(w); R CAT==v->id&&CMINUS==ID(v->f)?v->g:atop(ds(CMINUS),w);} + +static F2(jtfplus){ + RZ(a&&w); + if(iscons(a)&&equ(VAV(a)->f,zero))R w; + if(iscons(w)&&equ(VAV(w)->f,zero))R a; + R folk(a,ds(CPLUS),w); +} + +static F2(jtfminus){ + RZ(a&&w); + if(iscons(a)&&equ(VAV(a)->f,zero))R fnegate(w); + if(iscons(w)&&equ(VAV(w)->f,zero))R a; + R folk(a,ds(CMINUS),w); +} + +static F2(jtftymes){A x,y;B b,c;I k; + RZ(a&&w); + b=iscons(a); x=VAV(a)->f; + c=iscons(w); y=VAV(w)->f; + if(CFORK==ID(w)&&NOUN&AT(y))R ftymes(a,folk(qq(y,ainf),VAV(w)->g,VAV(w)->h)); + if(b&&AT(x)&B01+INT){k=i0(x); if(-1<=k&&k<=1)R !k?a:0f),zero),VAV(w)->h); + R c?folk(w,ds(CSTAR),a):folk(a,ds(CSTAR),w); +} + +static F1(jtdpoly){A c,e,x;I n,t; + RZ(w); + n=AN(w); t=AT(w); + ASSERT(!n||t&NUMERIC+BOX,EVDOMAIN); + if(!n||t&NUMERIC)R 2>=n?qq(2==n?tail(w):cvt(n?t:B01,zero),zero):fpolyc(behead(tymes(w,IX(n)))); + x=AAV0(w); + if(1=AR(x))R dpoly(poly1(w)); + ASSERT(2==AR(x)&&2==*(1+AS(x)),EVDOMAIN); + c=irs1(x,0L,1L,jthead); + e=irs1(x,0L,1L,jttail); + R amp(box(stitch(tymes(c,e),minus(e,one))),ds(CPOLY)); +} + +static F1(jtipoly){A b,c,e,p=0,q=0,x;I n,t; + RZ(w); + n=AN(w); t=AT(w); + ASSERT(!n||t&NUMERIC+BOX,EVDOMAIN); + if(!n||t&NUMERIC)R fpolyc(over(zero,divide(w,apv(n,1L,1L)))); + x=AAV0(w); + if(1=AR(x))R ipoly(poly1(w)); + ASSERT(2==AR(x)&&2==*(1+AS(x)),EVDOMAIN); + RZ(c=irs1(x,0L,1L,jthead)); + RZ(e=plus(one,irs1(x,0L,1L,jttail))); + RZ(b=ne(e,zero)); + if(!all0(b))RZ(p=amp(box(repeat(b,stitch(divide(c,e),e))),ds(CPOLY))); + if(!all1(b))RZ(q=evc(not(b),c,"(+/x#y)&*@^.")); + R p&&q?folk(p,ds(CPLUS),q):p?p:q; +} + +static F1(jticube){R atco(eval("* =/~@(i.@$)"),w);} + +static F1(jtdiffamp0){A f,g,h,x,y;B nf,ng;C id;V*v; + RZ(w); + v=VAV(w); + f=v->f; nf=1&&NOUN&AT(f); + g=v->g; ng=1&&NOUN&AT(g); + h=nf?g:f; id=ID(h); x=nf?f:g; + RZ(!AR(x)||id==CPOLY); + switch(id){ + case CPLUS: R qq(one,zero); + case CSTAR: R qq(x,zero); + case CMINUS: R qq(num[nf?-1:1],zero); + case CDIV: R nf?eva(x,"(-x)&%@*:"):qq(recip(x),zero); + case CPOLY: if(nf)R dpoly(x); break; + case CBANG: if(nf&&!AR(x))R dpoly(df1(iota(increm(x)),tdot(w))); break; + case CROOT: if(nf&&!AR(x))R atop(amp(recip(x),ds(CSTAR)),amp(ds(CEXP),decrem(recip(x)))); break; + case CLOG: R eva(logar1(x),nf?"(%x)&%":"(-x)&%@(* *:@^.)"); + case CEXP: + if(nf)R evc(x,w,"(^.x)&*@y"); + RZ(y=pcvt(INT,x)); + if(INT&AT(y))switch(*AV(y)){ + case 0: R qq(zero,zero); + case 1: R qq(one,zero); + case 2: R ds(CPLUSCO); + } + R eva(x,"x&*@(^&(x-1))"); + case CCIRCLE: + if(nf){ + RZ(x=vi(x)); + switch(*AV(x)){ + case 0: R folk(ds(CMINUS),ds(CDIV),w); + case 1: R amp(num[2],h); + case 2: R atop(ds(CMINUS),amp(one,h)); + case 3: R atop(atop(ds(CDIV),ds(CSTARCO)),amp(num[2],h)); + case 5: R amp(num[6],h); + case 6: R amp(num[5],h); + case 7: R atop(atop(ds(CDIV),ds(CSTARCO)),amp(num[6],h)); + }}} + R 0; +} + +static F1(jtdiff0){A df,dg,dh,f,g,h,x,y,z;B b,nf,ng,vf,vg;C id;I m,p,q;V*v; + RZ(w); + v=VAV(w); id=v->id; + f=v->f; nf=f&&NOUN&AT(f); vf=f&&!nf; + g=v->g; ng=g&&NOUN&AT(g); vg=g&&!ng; + if(id==CAMP&&nf!=ng)R diffamp0(w); + switch(id){ + case CLE: + case CGE: + case CLEFT: + case CRIGHT: R qq(one,zero); + case CPLUSCO: R qq(num[2],zero); + case CNOT: + case CMINUS: R qq(num[-1],zero); + case CFCONS: R qq(zero,zero); + case CSTARCO: R ds(CPLUSCO); + case CHALVE: R qq(connum(3L,"1r2"),zero); + case CCIRCLE: R qq(pie,zero); + case CDIV: R eval("- @%@*:"); + case CSQRT: R eval("-:@%@%:"); + case CEXP: R w; + case CLOG: R ds(CDIV); + case CJDOT: R qq(a0j1,zero); + case CRDOT: R atop(ds(CJDOT),w); + case CDDOT: if(vf&&ng)R ddot(f,increm(g)); break; + case CPOWOP: + if(vf&&ng&&!AR(g))switch(p=i0(g)){ + case -1: R diff0(inv(f)); + case 0: RE(0); R qq(one,zero); + case 1: R diff0(f); + default: + if(0>p){RZ(f=inv(f)); p=-p;} + if(q=ispoly(f)){RE(m=i0(vib(expn2(sc(q-1),g)))); R dpoly(df1(IX(1+m),tdot(w)));} + R diff0(atop(powop(f,sc(p-1)),f)); + } + break; + case CQQ: + if(!AR(f)&&NUMERIC&AT(f)&&ng&&equ(g,zero))R qq(zero,zero); + if(vf&&ng)R qq(diff0(f),g); + break; + case CAT: + case CATCO: + case CAMP: + case CAMPCO: + if(vf&&vg){ + p=ispoly(f); q=ispoly(g); + if(p&&q)R dpoly(df1(IX(1+(p-1)*(q-1)),tdot(w))); + RZ(dg=diff0(g)); RZ(df=diff0(f)); v=VAV(df); x=v->f; + if(CQQ!=v->id)R ftymes(dg,atop(df,g)); + switch(CQQ==v->id&&AT(x)&B01+INT?i0(x):9){ + case 0: R df; + case 1: R dg; + case 2: R atop(ds(CPLUSCO),dg); + case -1: R fnegate(dg); + default: R ftymes(df,dg); + }} + break; + case CTILDE: + if(vf)switch(ID(f)){ + case CPLUS: R qq(num[2],zero); + case CSTAR: R ds(CPLUSCO); + case CMINUS: + case CLOG: + case CDIV: R qq(zero,zero); + case CEXP: R eva(w,"x * >:@^."); + } + break; + case CFORK: + h=v->h; + if(NOUN&AT(f))R diff0(folk(qq(f,zero),g,h)); + if(CCAP==ID(f))R diff0(atco(g,h)); + p=ispoly(f); df=diff0(f); + q=ispoly(h); dh=diff0(h); b=p&&q; + switch(ID(g)){ + case CPLUS: z=fplus (df,dh); R b?fpoly(MAX(p,q)-1,z):z; + case CMINUS: z=fminus(df,dh); R b?fpoly(MAX(p,q)-1,z):z; + case CSTAR: z=fplus(ftymes(df,h),ftymes(f,dh)); R b?fpoly(p+q,z):z; + case CCOMMA: R folk(df,g,dh); + case CDIV: x=fminus(ftymes(df,h),ftymes(f,dh)); + y=atop(ds(CSTARCO),h); + R folk(b?fpoly(p+q-1-(p==q),x):x,ds(CDIV),q?fpoly(q+q,y):y); + case CEXP: if(1==q){A k; + RZ(k=df1(zero,h)); + if(equ(k,zero))R qq(zero,zero); + if(equ(k,one))R df; + if(equ(k,num[2]))R ftymes(df,ftymes(h,f)); + R ftymes(df,ftymes(h,folk(f,g,qq(decrem(k),zero)))); + } + }} + R 0; +} + +static F1(jtintgamp0){A f,g,h,x,y;B nf,ng;C id;V*v; + RZ(w); + v=VAV(w); + f=v->f; nf=1&&NOUN&AT(f); + g=v->g; ng=1&&NOUN&AT(g); + h=nf?g:f; id=ID(h); x=nf?f:g; + RZ(!AR(x)||id==CPOLY); + switch(id){ + case CPLUS: R ipoly(over(x,one)); + case CSTAR: R ipoly(over(zero,x)); + case CMINUS: R nf?ipoly(over(x,num[-1])):ipoly(over(negate(x),one)); + case CDIV: R nf?eva(x,"x&*@^."):ipoly(over(zero,recip(x))); + case CPOLY: if(nf)R ipoly(x); break; + case CBANG: if(nf&&AT(x))R ipoly(df1(iota(increm(x)),tdot(w))); break; + case CEXP: + if(ng&&!AR(x)){ + if(equ(x,num[-1]))R ds(CLOG); + RZ(y=pcvt(INT,x)); + R INT&AT(y)?ipoly(take(sc(-1-i0(y)),one)):atop(amp(ds(CDIV),increm(y)),amp(ds(CEXP),increm(y))); + } + case CCIRCLE: + if(nf){ + RZ(x=vi(x)); + switch(*AV(x)){ + case 1: R atop(ds(CMINUS),amp(num[2],h)); + case 2: R amp(one,h); + case 3: R eval("-@^.@(2&o.)"); + case 5: R amp(num[6],h); + case 6: R amp(num[5],h); + case 7: R atop(ds(CLOG),amp(num[6],h)); + }}} + R 0; +} + +static F1(jtintg0); + +static F2(jtintgatop){A df,f=a,g=w,q,x,y;I m,n;V*v; + RZ(a&&w); + m=ispoly(f); + n=ispoly(g); + if(m&&n)R ipoly(df1(IX(1+(m-1)*(n-1)),tdot(atop(a,w)))); + if(2==m){ + RZ(q=v2(0L,1L)); + RZ(x=df1(q,tdot(f))); + RZ(y=equ(one, tail(x))?intg0(g):atop(fpolyc(tymes(q,x)),intg0(g))); + R equ(zero,head(x))?y :folk(y,ds(CPLUS),amp(head(x),ds(CSTAR))); + } + if(1==n||2==n){ + df=atop(intg0(f),g); + if(1==n)R df; + RZ(x=df1(one,tdot(g))); + R equ(x,one)?df:atop(amp(ds(CDIV),x),df); + } + v=VAV(g); + if(m&&equ(take(sc(-m),one),df1(IX(m),tdot(f)))){ /* ^&m @ g */ + if(CLOG==v->id)R 1==m?ds(CRIGHT):2==m?intg0(g):eva(sc(m-1),"(] * ^&x@^.) - x&* @(^&(x-1)@^. d. _1)"); + if(CAMP==v->id&&CCIRCLE==ID(v->g)&&(y=v->f,!AR(y)&&equ(y,floor1(y)))){ + if(2>=m)R 1==m?ds(CRIGHT):intgamp0(g); + switch(i0(y)){ + case 1: R eva(sc(m-1),"%&(-x )@(^&(x-1)@(1&o.) * 2&o.) + ((x-1)%x)&*@(^&(x-2)@(1&o.) d. _1)"); + case 2: R eva(sc(m-1),"%&x @(^&(x-1)@(2&o.) * 1&o.) + ((x-1)%x)&*@(^&(x-2)@(2&o.) d. _1)"); + case 3: R eva(sc(m-1),"%&(x-1)@(^&(x-1)@(3&o.) ) - ^&(x-2)@(3&o.) d. _1 "); + case 7: R eva(sc(m-1),"%&(1-x)@(^&(x-1)@(7&o.) ) + ^&(x-2)@(7&o.) d. _1 "); + }}} + R 0; +} /* integral of a @ w */ + +static F2(jtintgtymes){A f=a,g=w; + RZ(a&&w); + R 0; +} /* integral of a * w */ + +static F1(jtintg0){A df,dh,f,g,h;B nf,ng,vf,vg;C id;I m,n,p,q;V*fv,*gv,*v; + RZ(w); + id=ID(w); v=VAV(w); + f=v->f; nf=f&&NOUN&AT(f); if(vf=f&&!nf)fv=VAV(f); + g=v->g; ng=g&&NOUN&AT(g); if(vg=g&&!ng)gv=VAV(g); + if(id==CAMP&&nf!=ng)R intgamp0(w); + switch(id){ + case CLE: R ipoly(v2(-1L, 1L)); + case CGE: R ipoly(v2( 1L, 1L)); + case CLEFT: + case CRIGHT: R ipoly(v2( 0L, 1L)); + case CNOT: R ipoly(v2( 1L,-1L)); + case CMINUS: R ipoly(v2( 0L,-1L)); + case CPLUSCO: R ds(CSTARCO); + case CFCONS: R amp(v->h,ds(CSTAR)); + case CSTARCO: R ipoly(over(v2(0L,0L),one)); + case CHALVE: R ipoly(over(zero,scf((D)0.5))); + case CCIRCLE: R ipoly(over(zero,scf(PI ))); + case CDIV: R ds(CLOG); + case CSQRT: R eval("%: * (0 2%3)&p."); + case CEXP: R w; + case CLOG: R eval("(]*^.) - ]"); + case CJDOT: R ipoly(over(zero,a0j1)); + case CRDOT: R eval("-@j.@r."); + case CDDOT: if(vf&&ng)R ddot(f,decrem(g)); break; + case CPOWOP: + if(vf&&ng&&!AR(g))switch(p=i0(g)){ + case -1: R intg0(inv(f)); + case 0: RE(0); R ipoly(v2(0L,1L)); + case 1: R intg0(f); + default: + if(0>p){RZ(f=inv(f)); p=-p;} + if(q=ispoly(f)){RE(m=i0(vib(expn2(sc(q-1),g)))); R ipoly(df1(IX(1+m),tdot(w)));} + R intg0(atop(powop(f,sc(p-1)),f)); + } + break; + case CQQ: + if(!AR(f)&&NUMERIC&AT(f)&&ng&&equ(g,zero))R amp(f,ds(CSTAR)); + if(vf&&ng)R qq(intg0(f),g); + break; + case CAT: + case CATCO: + case CAMP: + case CAMPCO: + if(vf&&vg)R intgatop(f,g); + break; + case CTILDE: + if(vf)switch(ID(f)){ + case CPLUS: R ipoly(v2(0L,2L)); + case CSTAR: R ipoly(over(v2(0L,0L),one)); + case CMINUS: R FCONS(zero); + case CLOG: + case CDIV: R ds(CRIGHT); + } + break; + case CFORK: + h=v->h; + if(NOUN&AT(f))R intg0(folk(qq(f,zero),g,h)); + dh=intg0(h); n=ispoly(h); + df=intg0(f); m=ispoly(f); + switch(ID(g)){ + case CPLUS: R m&&n ? (p=MAX(m,n),ipoly(df1(IX(p),tdot(w)))) : fplus(df,dh); + case CMINUS: R m&&n ? (p=MAX(m,n),ipoly(df1(IX(p),tdot(w)))) : fminus(df,dh); + case CSTAR: if(m&&n){p=2+(m-1)*(n-1); R ipoly(df1(IX(p),tdot(w)));} + R intgtymes(f,h); + }} + R 0; +} + +static DF1(jtddot1){V*v=VAV(self); R df1(w,ddot(fix(v->f),v->g));} + +F2(jtddot){A x,*xv,y,z;AF f;I j,n,p,q,r,*wv; + RZ(a&&w); + ASSERT(NOUN&AT(w),EVDOMAIN); + RZ(w=vi(w)); r=AR(w); n=AN(w); wv=AV(w); + if(NOUN&AT(a)){ASSERT(0,EVNONCE);} + if(!nameless(a)||1mr||v->lr||v->rr?qq(a,zero):a;} + f=0<=p?jtdiff0:jtintg0; y=a; DO(ABS(p), ASSERT(y=CALL1(f,y,0L),EVDOMAIN);); R y; + } + q+=p-1; p=0>p?p:0; q=0p){y=a; j=-p; DO(-p, ASSERT(y=intg0(y),EVDOMAIN); xv[--j]=y;);} + if(0f; nf=1&&NOUN&AT(f); + g=v->g; ng=1&&NOUN&AT(g); + h=nf?g:f; x=nf?f:g; + switch(ID(h)){ + case CROT: + case CCANT: + case CLBRACE: + case CATOMIC: + case CCYCLE: + if(nf)R atop(hook(eval("=/"),w),eval("i.@$")); + break; + case CPOLY: + if(nf&&1>=AR(x))R dpoly(NUMERIC&AT(x)?x:poly1(x)); + break; + case CBANG: + if(!AR(x)&&(x=pcvt(INT,x),INT&AT(x)))R dpoly(df1(IX(1+*AV(x)),tdot(w))); + break; + case CFIT: + if(nf&&1>=AR(x)&&(y=VAV(h)->f,CPOLY==ID(y)))R dpoly(df1(IX(IC(x)),tdot(w))); + } + R 0; +} + +static F1(jtdiff){A df,dh,f,g,h,z;B nf,ng,vf,vg;C id;I r;V*v; + RZ(w); + ASSERT(VERB&AT(w),EVDOMAIN); + v=VAV(w); id=v->id; r=v->mr; + f=v->f; nf=f&&NOUN&AT(f); vf=f&&!nf; + g=v->g; ng=g&&NOUN&AT(g); vg=g&&!ng; + if(nf&&id==CFORK)R diff(folk(qq(f,ainf),g,v->h)); + if(z=diff0(w))R id==CQQ&&ng&&equ(g,zero)?z:icube(z); + if(id==CAMP&&nf!=ng)R diffamp(w); + switch(id){ + case CREV: R eval("(|.=/])@(i.@$)"); + case CCANT: R eval("(|:=/])@(i.@$)"); + case CHGEOM: R hgdiff(w); + case CSLASH: + switch(ID(f)){ + case CPLUS: R eval("({. =/ */@}.@$ | ])@(i.@$)"); + } + break; + /* ----- commented out because it is incorrect + case CBSLASH: + case CBSDOT: + if(CSLASH==ID(f)&&(ff=VAV(f)->f,ff&&VERB&AT(ff))){ + b=id==CBSDOT; + switch(ID(ff)){ + case CPLUS: R eval(b ? "<:/~@(i.@$)" : ">:/~@(i.@$)"); + }} + break; + ----- */ + case CFCONS: + R atop(amp(ds(CDOLLAR),zero),ds(CDOLLAR)); + case CQQ: + if(NUMERIC&AT(f)&&ng){ + z=atop(amp(ds(CDOLLAR),zero),ds(CDOLLAR)); + R RMAXh; dh=diff(h); + switch(ID(g)){ + case CPLUS: R fplus(df,dh); + case CMINUS: R fminus(df,dh); + case CSTAR: R fplus(ftymes(df,h),ftymes(f,dh)); + case CDIV: R folk(fminus(ftymes(df,h),ftymes(f,dh)), ds(CDIV), atop(ds(CSTARCO),h)); + }} + R 0; +} + +static F1(jtintg){ASSERT(0,EVNONCE);} + +static A jtdtab(J jt,A a,I d){A h;V*v; + RZ(a); + if(CDCAP==ID(a)&&(v=VAV(a),NOUN&AT(v->f)&&d==i0(v->g))){h=VAV(a)->h; R*(1+AAV(h));} + switch(SGN(d)){ + default: ASSERTSYS(0,"dtab"); + case -1: R dtab(intg(a),d+1); + case 0: R a; + case 1: R dtab(diff(a),d-1); +}} + + +static DF2(jtsslope){A fs,f0,p,y,z,*zv;I m,n,r,t;V*sv=VAV(self); + PREF2(jtsslope); + fs=sv->f; m=*AV(sv->g); + RZ(fs=1f)); gs=v->g; n=AN(gs); gv=AV(gs); + if(!(AT(w)&FL+CMPX))RZ(w=cvt(FL,w)); + RZ(e=scf((D)1e-7)); + RZ(t=sc(0L)); tv=AV(t); + RZ(s=ca(self)); v=VAV(s); v->g=t; v->lr=v->mr; + GA(z,BOX,n,AR(gs),AS(gs)); zv=AAV(z); + DO(n, *tv=d=gv[i]; zv[i]=(ff=dtab(fs,d))?df1(w,ff):sslope(tymes(e,w),w,s);); + RE(0); R ope(z); +} + +F2(jtdcap){A z;I r,*v; + RZ(a&&w); + ASSERT(NOUN&AT(w),EVDOMAIN); + RZ(w=vi(w)); v=AV(w); DO(AN(w), ASSERT(0<=v[i],EVNONCE);); + if(NOUN&AT(a))R vger2(CDCAP,a,w); + r=mr(a); + R !AR(w)&&nameless(a)&&(z=dtab(a,*v))?z:CDERIV(CDCAP,jtderiv1,0L,r,0L,r); +} + +F2(jtdcapco){I r,*v; + ASSERTVN(a,w); + RZ(w=vi(w)); v=AV(w); DO(AN(w), ASSERT(0<=v[i],EVNONCE);); + r=mr(a); + R CDERIV(CDCAPCO,0L,jtsslope,0L,r,r); +} diff --git a/cf.c b/cf.c new file mode 100644 --- /dev/null +++ b/cf.c @@ -0,0 +1,199 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Conjunctions: Forks */ + +#include "j.h" + +#define TC1(t) (t&NOUN?0:t&VERB?3:t&CONJ?2:1) +#define BD(ft,gt) (4*TC1(ft)+TC1(gt)) +#define TDECL V*sv=VAV(self);A fs=sv->f,gs=sv->g,hs=sv->h + +#define FOLK1 {A fx,hx; hx=CALL1(h1, w,hs); fx=CALL1(f1, w,fs); z=CALL2(g2,fx,hx,gs);} +#define FOLK2 {A fx,hx; hx=CALL2(h2,a,w,hs); fx=CALL2(f2,a,w,fs); z=CALL2(g2,fx,hx,gs);} +#define CAP1 {z=CALL1(g1,CALL1(h1, w,hs),gs);} +#define CAP2 {z=CALL1(g1,CALL2(h2,a,w,hs),gs);} + +static DF1(jtcork1){DECLFGH;PROLOG;A z; CAP1; EPILOG(z);} +static DF2(jtcork2){DECLFGH;PROLOG;A z; CAP2; EPILOG(z);} +static DF1(jtfolk1){DECLFGH;PROLOG;A z; FOLK1; EPILOG(z);} +static DF2(jtfolk2){DECLFGH;PROLOG;A z; FOLK2; EPILOG(z);} + +static B jtcap(J jt,A x){V*v; + while(v=VAV(x),CTILDE==v->id&&NAME&AT(v->f)&&(x=symbrd(v->f))); + R CCAP==v->id; +} + +static DF1(jtcorx1){DECLFGH;PROLOG;A z; if(cap(fs))RZ(z=df1( w,folk(ds(CCAP),gs,hs))) else FOLK1; EPILOG(z);} +static DF2(jtcorx2){DECLFGH;PROLOG;A z; if(cap(fs))RZ(z=df2(a,w,folk(ds(CCAP),gs,hs))) else FOLK2; EPILOG(z);} + /* f g h where f may be [: */ + +static DF1(jtnvv1){DECLFGH;PROLOG; EPILOG(CALL2(g2,fs,CALL1(h1, w,hs),gs));} +static DF2(jtnvv2){DECLFGH;PROLOG; EPILOG(CALL2(g2,fs,CALL2(h2,a,w,hs),gs));} + +static DF2(jtfolkcomp){DECLFGH;PROLOG;A z;AF f; + RZ(a&&w); + if(f=atcompf(a,w,self))z=f(jt,a,w,self); else if(cap(fs))CAP2 else FOLK2; + EPILOG(z); +} + +static DF2(jtfolkcomp0){DECLFGH;PROLOG;A z;AF f;D oldct=jt->ct; + RZ(a&&w); + jt->ct=0; + if(f=atcompf(a,w,self))z=f(jt,a,w,self); else if(cap(fs))CAP2 else FOLK2; + jt->ct=oldct; + EPILOG(z); +} + +static DF1(jtcharmapa){V*v=VAV(self); R charmap(w,VAV(v->h)->f,v->f);} +static DF1(jtcharmapb){V*v=VAV(self); R charmap(w,VAV(v->f)->f,VAV(v->h)->f);} + +A jtfolk(J jt,A f,A g,A h){A p,q,x,y;AF f1=jtfolk1,f2=jtfolk2;B b;C c,fi,gi,hi;I flag=0,j,m=-1;V*fv,*gv,*hv,*v; + RZ(f&&g&&h); + gv=VAV(g); gi=gv->id; + hv=VAV(h); hi=hv->id; + if(NOUN&AT(f)){ /* y {~ x i. ] */ + f1=jtnvv1; + if(LIT&AT(f)&&1==AR(f)&&gi==CTILDE&&CFROM==ID(gv->f)&&hi==CFORK){ + x=hv->f; + if(LIT&AT(x)&&1==AR(x)&&CIOTA==ID(hv->g)&&CRIGHT==ID(hv->h))f1=jtcharmapa; + } + R fdef(CFORK,VERB, f1,jtnvv2, f,g,h, flag, RMAX,RMAX,RMAX); + } + fv=VAV(f); fi=fv->id; + switch(fi){ + case CCAP: f1=jtcork1; f2=jtcork2; break; /* [: g h */ + case CTILDE: if(NAME&AT(fv->f)){f1=jtcorx1; f2=jtcorx2;} break; /* f g h */ + case CSLASH: if(gi==CDIV&&hi==CPOUND&&CPLUS==ID(fv->f))f1=jtmean; break; /* +/%# */ + case CAMP: /* x&i. { y"_ */ + case CFORK: /* (x i. ]) { y"_ */ + if(hi==CQQ&&(y=hv->f,LIT&AT(y)&&1==AR(y))&&equ(ainf,hv->g)&& + (x=fv->f,LIT&AT(x)&&1==AR(x))&&CIOTA==ID(fv->g)&& + (fi==CAMP||CRIGHT==ID(fv->h)))f1=jtcharmapb; break; + case CAT: /* <"1@[ { ] */ + if(gi==CLBRACE&&hi==CRIGHT){ + p=fv->f; q=fv->g; + if(CLEFT==ID(q)&&CQQ==ID(p)&&(v=VAV(p),x=v->f,CLT==ID(x)&&equ(one,v->g)))f2=jtsfrom; + }} + switch(fi==CCAP?gi:hi){ + case CQUERY: if(hi==CDOLLAR||hi==CPOUND)f2=jtrollk; break; + case CQRYDOT: if(hi==CDOLLAR||hi==CPOUND)f2=jtrollkx; break; + case CICAP: m=7; if(fi==CCAP){if(hi==CNE)f1=jtnubind; else if(FIT0(CNE,hv))f1=jtnubind0;} break; + case CSLASH: c=ID(gv->f); m=c==CPLUS?4:c==CPLUSDOT?5:c==CSTARDOT?6:-1; + if(fi==CCAP&&vaid(gv->f)&&vaid(h))f2=jtfslashatg; + break; + case CFCONS: if(hi==CFCONS){x=hv->h; j=*BAV(x); m=B01&AT(x)?(gi==CIOTA?j:gi==CICO?2+j:-1):-1;} break; + case CRAZE: if(hi==CLBRACE)f2=jtrazefrom; + else if(hi==CCUT){ + j=i0(hv->g); + if(CBOX==ID(hv->f)&&!j)f2=jtrazecut0; + else if(boxatop(h)&&j&&-2<=j&&j<=2){f1=jtrazecut1; f2=jtrazecut2;} + }} + if(0<=m){ + v=4<=m?hv:fv; b=CFIT==v->id&&equ(zero,v->g); + switch(b?ID(v->f):v->id){ + case CEQ: f2=b?jtfolkcomp0:jtfolkcomp; flag=0+8*m; break; + case CNE: f2=b?jtfolkcomp0:jtfolkcomp; flag=1+8*m; break; + case CLT: f2=b?jtfolkcomp0:jtfolkcomp; flag=2+8*m; break; + case CLE: f2=b?jtfolkcomp0:jtfolkcomp; flag=3+8*m; break; + case CGE: f2=b?jtfolkcomp0:jtfolkcomp; flag=4+8*m; break; + case CGT: f2=b?jtfolkcomp0:jtfolkcomp; flag=5+8*m; break; + case CEBAR: f2=b?jtfolkcomp0:jtfolkcomp; flag=6+8*m; break; + case CEPS: f2=b?jtfolkcomp0:jtfolkcomp; flag=7+8*m; break; + }} + R fdef(CFORK,VERB, f1,f2, f,g,h, flag, RMAX,RMAX,RMAX); +} + + +static DF1(taa){TDECL;A t=df1(w,fs); ASSERT(!t||AT(t)&NOUN+VERB,EVSYNTAX); R df1(t,gs);} +static DF1(tvc){TDECL; R df2(fs,w,gs);} /* also nc */ +static DF1(tcv){TDECL; R df2(w,gs,fs);} /* also cn */ + + +static CS1(jthook1, CALL2(f2,w,CALL1(g1,w,gs),fs)) +static CS2(jthook2, CALL2(f2,a,CALL1(g1,w,gs),fs)) + +static DF1(jthkiota){DECLFG;A a,e;I n;P*p; + RZ(w); + n=IC(w); + if(SB01&AT(w)&&1==AR(w)){ + p=PAV(w); a=SPA(p,a); e=SPA(p,e); + R *BAV(e)||equ(mtv,a) ? repeat(w,IX(n)) : repeat(SPA(p,x),ravel(SPA(p,i))); + } + R B01&AT(w)&&1>=AR(w) ? ifb(n,BAV(w)) : repeat(w,IX(n)); +} /* special code for (# i.@#) */ + +static DF1(jthkodom){DECLFG;B b=0;I n,*v; + RZ(w); + if(INT&AT(w)&&1==AR(w)){n=AN(w); v=AV(w); DO(n, if(b=0>v[i])break;); if(!b)R odom(2L,n,v);} + R CALL2(f2,w,CALL1(g1,w,gs),fs); +} /* special code for (#: i.@(* /)) */ + +static DF2(jthkeps){ + RZ(a&&w); + if(AT(a)==AT(w)&&AT(a)&IS1BYTE&&1==AN(a)){A z; + GA(z,B01,1,AR(a),AS(a)); + *BAV(z)=1&&memchr(CAV(w),*CAV(a),AN(w)); + R z; + } + R eps(a,gah(1L,w)); +} /* special code for (e.,) */ + +static DF2(jthkfrom){R from(a,gah(1L,w));} /* special code for ({ ,) */ +static DF2(jthktake){R take(a,gah(1L,w));} /* special code for ({.,) */ +static DF2(jthkdrop){R drop(a,gah(1L,w));} /* special code for (}.,) */ + +static DF1(jthkindexofmaxmin){D*du,*dv;I*iu,*iv,n,t,*wv,z=0;V*sv; + RZ(w&&self); + n=AN(w); t=AT(w); + if(!(1==AR(w)&&t&INT+FL))R hook1(w,self); + sv=VAV(self); wv=AV(w); + if(n)switch((t&FL?4:0)+(CICO==ID(sv->f)?2:0)+(CMAX==ID(VAV(sv->g)->f))){ + case 0: iu=iv= wv; DO(n, if(*iv<*iu)iu=iv; ++iv;); z=iu- wv; break; + case 1: iu=iv= wv; DO(n, if(*iv>*iu)iu=iv; ++iv;); z=iu- wv; break; + case 2: iu=iv= wv+n-1; DO(n, if(*iv<*iu)iu=iv; --iv;); z=iu- wv; break; + case 3: iu=iv= wv+n-1; DO(n, if(*iv>*iu)iu=iv; --iv;); z=iu- wv; break; + case 4: du=dv=(D*)wv; DO(n, if(*dv<*du)du=dv; ++dv;); z=du-(D*)wv; break; + case 5: du=dv=(D*)wv; DO(n, if(*dv>*du)du=dv; ++dv;); z=du-(D*)wv; break; + case 6: du=dv=(D*)wv+n-1; DO(n, if(*dv<*du)du=dv; --dv;); z=du-(D*)wv; break; + case 7: du=dv=(D*)wv+n-1; DO(n, if(*dv>*du)du=dv; --dv;); z=du-(D*)wv; + } + R sc(z); +} /* special code for (i.<./) (i.>./) (i:<./) (i:>./) */ + + +F2(jthook){AF f1=0,f2=0;C c,d,e,id;I flag=0;V*u,*v; + RZ(a&&w); + switch(BD(AT(a),AT(w))){ + default: ASSERT(0,EVSYNTAX); + case BD(VERB,VERB): + u=VAV(a); c=u->id; f1=jthook1; f2=jthook2; + v=VAV(w); d=v->id; e=ID(v->f); + if(d==CCOMMA)switch(c){ + case CDOLLAR: f2=jtreshape; flag+=VIRS2; break; + case CFROM: f2=jthkfrom; break; + case CTAKE: f2=jthktake; break; + case CDROP: f2=jthkdrop; break; + case CEPS: f2=jthkeps; + }else switch(c){ + case CSLDOT: if(COMPOSE(d)&&e==CIOTA&&CPOUND==ID(v->g)&&CBOX==ID(u->f))f1=jtgroup; break; + case CPOUND: if(COMPOSE(d)&&e==CIOTA&&CPOUND==ID(v->g))f1=jthkiota; break; + case CABASE: if(COMPOSE(d)&&e==CIOTA&&CSLASH==ID(v->g)&&CSTAR==ID(VAV(v->g)->f))f1=jthkodom; break; + case CIOTA: + case CICO: if(d==CSLASH&&(e==CMAX||e==CMIN))f1=jthkindexofmaxmin; break; + case CFROM: if(d==CGRADE)f2=jtordstati; else if(d==CTILDE&&e==CGRADE)f2=jtordstat; + } + R fdef(CHOOK, VERB, f1,f2, a,w,0L, flag, RMAX,RMAX,RMAX); + case BD(ADV, ADV ): f1=taa; break; + case BD(NOUN,CONJ): + case BD(VERB,CONJ): + f1=tvc; id=ID(w); + if(BOX&AT(a)&&(id==CATDOT||id==CGRAVE||id==CGRCO))flag=VGERL; + break; + case BD(CONJ,NOUN): + case BD(CONJ,VERB): + f1=tcv; id=ID(a); + if(BOX&AT(w)&&(id==CGRAVE||id==CPOWOP&&1=AR(w),EVRANK); + ASSERT(n,EVLENGTH); + ASSERT(BOX&AT(w),EVDOMAIN); + GA(z,BOX,n,AR(w),AS(w)); zv=AAV(z); + DO(n, RZ(zv[i]=x=fx(WVR(i))); ASSERT(VERB&AT(x),EVDOMAIN);); + R z; +} + +F1(jtfxeach){R every(w,0L,jtfx);} + +static DF1(jtcon1){A h,*hv,*x,z;V*sv; + PREF1(jtcon1); + sv=VAV(self); h=sv->h; hv=AAV(h); + GA(z,BOX,AN(h),AR(h),AS(h)); x=AAV(z); + DO(AN(h), RZ(*x++=CALL1(VAV(*hv)->f1, w,*hv)); ++hv;); + R ope(z); +} + +static DF2(jtcon2){A h,*hv,*x,z;V*sv; + PREF2(jtcon2); + sv=VAV(self); h=sv->h; hv=AAV(h); + GA(z,BOX,AN(h),AR(h),AS(h)); x=AAV(z); + DO(AN(h), RZ(*x++=CALL2(VAV(*hv)->f2,a,w,*hv)); ++hv;); + R ope(z); +} + +static DF1(jtinsert){A f,hs,*hv,z;AF*hf;I j,k,m,n,old; + RZ(w); + n=IC(w); j=n-1; hs=VAV(self)->h; m=AN(hs); hv=AAV(hs); + if(!n)R df1(w,iden(*hv)); + GA(f,INT,m,1,0); hf=(AF*)AV(f); DO(m, hf[i]=VAV(hv[i])->f2;); + RZ(z=from(num[-1],w)); + old=jt->tbase+jt->ttop; + DO(n-1, k=--j%m; RZ(z=CALL2(hf[k],from(sc(j),w),z,hv[k])); gc(z,old);) + R z; +} + +F2(jtevger){A hs;I k; + RZ(a&&w); + RE(k=i0(w)); + if(k==GTRAIN)R exg(a); + RZ(hs=fxeachv(RMAX,a)); + switch(k){ + case GAPPEND: + R fdef(CGRCO,VERB, jtcon1,jtcon2, a,w,hs, VGERL, RMAX,RMAX,RMAX); + case GINSERT: + ASSERT(1>=AR(a),EVRANK); + R fdef(CGRCO,VERB, jtinsert,0L, a,w,hs, VGERL, RMAX,0L,0L); + default: + ASSERT(0,EVDOMAIN); +}} + +F2(jttie){RZ(a&&w); R over(VERB&AT(a)?arep(a):a,VERB&AT(w)?arep(w):w);} + + +static B jtatomic(J jt,C m,A w){A f,g;B ax,ay,vf,vg;C c,id;V*v; + static C atomic12[]={CMIN, CLE, CMAX, CGE, CPLUS, CPLUSCO, CSTAR, CSTARCO, CMINUS, CDIV, CROOT, + CEXP, CLOG, CSTILE, CBANG, CLEFT, CRIGHT, CJDOT, CCIRCLE, CRDOT, CHGEOM, CFCONS, 0}; + static C atomic1[]={CNOT, CHALVE, 0}; + static C atomic2[]={CEQ, CLT, CGT, CPLUSDOT, CSTARDOT, CNE, 0}; + RZ(w&&VERB&AT(w)); + v=VAV(w); id=v->id; + if(strchr(atomic12,id)||strchr(1==m?atomic1:atomic2,id))R 1; + f=v->f; vf=f&&VERB&AT(f); ax=f&&NOUN&AT(f)&&!AR(f); + g=v->g; vg=g&&VERB&AT(g); ay=g&&NOUN&AT(g)&&!AR(g); + switch(id){ + case CAT: + case CATCO: R atomic(1,f)&&atomic(m,g); + case CUNDER: + case CUNDCO: R atomic(m,f)&&atomic(1,g); + case CAMPCO: R atomic(m,f)&&atomic(1,g); + case CQQ: R ax||atomic(m,f); + case CFORK: R (CCAP==ID(f)?atomic(1,g):atomic(m,f)&&atomic(2,g))&&atomic(m,v->h); + case CHOOK: R atomic(2,f)&&atomic(1,g); + case CTILDE: R NAME&AT(f)?atomic(m,fix(f)):atomic(2,f); + case CFIT: R atomic(m,f); + case CAMP: + if(vf&&vg)R atomic(m,f)&&atomic(1,g); + if(ax&&atomic(2,g)||ay&&atomic(2,f))R 1; + if(vg&&1==AR(f)){c=ID(g); R c==CPOLY||c==CBASE;} + } + R 0; +} /* 1 iff verb w is atomic; 1=m monad 2=m dyad */ + +static A jtgjoin(J jt,C c,A a,A w){A f; + RZ(a&&w); + ASSERT(1>=AR(a)&&1>=AR(w),EVRANK); + ASSERT((!AN(a)||BOX&AT(a))&&(!AN(w)||BOX&AT(w)),EVDOMAIN); + RZ(f=qq(atop(ds(CBOX),ds(CCOMMA)),zero)); + R df2(box(spellout(c)),df2(a,w,f),f); +} + +static DF1(jtcase1a){A g,h,*hv,k,t,u,w0=w,x,y,*yv,z;B b;I r,*xv;V*sv; + RZ(w); + r=AR(w); + if(1g; + if(atomic(1,g))RZ(k=df1(w,g)) + else{RZ(k=df1(w,qq(g,zero))); ASSERT(AR(k)==AR(w)&&AN(k)==AN(w),EVRANK);} + if(B01&AT(k)){ + h=sv->h; ASSERT(2<=AN(h),EVINDEX); hv=AAV(h); + RZ(x=df1(t=repeat(not(k),w),hv[0])); if(!AR(x))RZ(x=reshape(tally(t),x)); + RZ(y=df1(t=repeat(k, w),hv[1])); if(!AR(y))RZ(y=reshape(tally(t),y)); + RZ(z=!AN(x)?y:!AN(y)?x:from(grade1(grade1(k)),over(x,y))); + }else{ + RZ(u=nub(k)); + RZ(y=df2(k,w,sldot(gjoin(CATCO,box(scc(CBOX)),from(u,sv->f))))); yv=AAV(y); + b=0; DO(AN(y), if(b=!AR(yv[i]))break;); + if(b){ + RZ(x=df2(k,w,sldot(ds(CPOUND)))); xv=AV(x); + DO(AN(y), if(!AR(yv[i]))RZ(yv[i]=reshape(sc(xv[i]),yv[i]));); + } + RZ(z=from(grade1(grade1(k)),raze(grade2(y,u)))); + } + if(1h; + RZ(u=from(df1(w,sv->g),h)); + ASSERT(!AR(u),EVRANK); + R df1(w,*AAV(u)); +} + +static DF1(jtcase1){A h,*hv;B b;I r,wr;V*sv; + RZ(w); + sv=VAV(self); + wr=AR(w); r=jt->rank?jt->rank[1]:wr; r=MIN(r,sv->mr); jt->rank=0; + if(b=!r&&wr&&AN(w)){h=sv->h; hv=AAV(h); DO(AN(h), if(!atomic(1,hv[i])){b=0; break;});} + R b?case1a(w,self):rank1ex(w,self,r,jtcase1b); +} + +static DF2(jtcase2){A u;V*sv; + PREF2(jtcase2); + sv=VAV(self); + RZ(u=from(df2(a,w,sv->g),sv->h)); + ASSERT(!AR(u),EVRANK); + R df2(a,w,*AAV(u)); +} + +static F2(jtgerfrom){A*av,*v,z;I ad,n; + RZ(a&&w); /* 1==AR(w)&&BOX&AT(w) */ + ASSERT(1>=AR(a),EVRANK); + if(NUMERIC&AT(a))R from(a,w); + else{ + ASSERT(BOX&AT(a),EVDOMAIN); + n=AN(a); av=AAV(a); ad=(I)a*ARELATIVE(a); + GA(z,BOX,n,1,0); v=AAV(z); + DO(n, RZ(*v++=gerfrom(AVR(i),w));); + R z; +}} + +F2(jtagenda){ + RZ(a&&w) + if(NOUN&AT(w))R exg(gerfrom(w,a)); + R fdef(CATDOT,VERB, jtcase1,jtcase2, a,w,fxeachv(1L,a), VGERL, mr(w),lr(w),rr(w)); +} + + +static DF1(jtgcl1){DECLFG;A ff,*hv=AAV(sv->h);I d; + d=fdep(hv[1]); FDEPINC(d); ff=df2(df1(w,hv[1]),gs,ds(sv->id)); FDEPDEC(d); + R df1(df1(w,hv[2]),ff); +} + +static DF1(jtgcr1){DECLFG;A ff,*hv=AAV(sv->h);I d; + d=fdep(hv[1]); FDEPINC(d); ff=df2(fs,df1(w,hv[1]),ds(sv->id)); FDEPDEC(d); + R df1(df1(w,hv[2]),ff); +} + +static DF2(jtgcl2){DECLFG;A ff,*hv=AAV(sv->h);I d; + d=fdep(hv[1]); FDEPINC(d); ff=df2(df2(a,w,hv[1]),gs,ds(sv->id)); FDEPDEC(d); + R df2(df2(a,w,hv[0]),df2(a,w,hv[2]),ff); +} + +static DF2(jtgcr2){DECLFG;A ff,*hv=AAV(sv->h);I d; + d=fdep(hv[1]); FDEPINC(d); ff=df2(fs,df2(a,w,hv[1]),ds(sv->id)); FDEPDEC(d); + R df2(df2(a,w,hv[0]),df2(a,w,hv[2]),ff); +} + +A jtgconj(J jt,A a,A w,C id){A hs,y;B na;I n; + RZ(a&&w); + ASSERT(VERB&AT(a)&&BOX&AT(w)||BOX&AT(a)&&VERB&AT(w),EVDOMAIN); + na=1&&BOX&AT(a); y=na?a:w; n=AN(y); + ASSERT(1>=AR(y),EVRANK); + ASSERT(2==n||3==n,EVLENGTH); + ASSERT(BOX&AT(y),EVDOMAIN); + RZ(hs=fxeach(3==n?y:link(scc(CLEFT),y))); + R fdef(id,VERB, na?jtgcl1:jtgcr1,na?jtgcl2:jtgcr2, a,w,hs, na?VGERL:VGERR, RMAX,RMAX,RMAX); +} + +static DF1(jtgav1){DECLF;A ff,*hv=AAV(sv->h);I d; + d=fdep(hv[1]); FDEPINC(d); ff=df1(df1(w,hv[1]),ds(sv->id)); FDEPDEC(d); + R df1(df1(w,hv[2]),ff); +} + +static DF2(jtgav2){DECLF;A ff,*hv=AAV(sv->h);I d; + d=fdep(hv[1]); FDEPINC(d); ff=df1(df2(a,w,hv[1]),ds(sv->id)); FDEPDEC(d); + R df2(df2(a,w,hv[0]),df2(a,w,hv[2]),ff); +} + +A jtgadv(J jt,A w,C id){A hs;I n; + RZ(w); + ASSERT(BOX&AT(w),EVDOMAIN); + n=AN(w); + ASSERT(1>=AR(w),EVRANK); + ASSERT(n&&n<=3,EVLENGTH); + ASSERT(BOX&AT(w),EVDOMAIN); + RZ(hs=fxeach(3==n?w:behead(reshape(num[4],w)))); + R fdef(id,VERB, jtgav1,jtgav2, w,0L,hs, VGERL, RMAX,RMAX,RMAX); +} + + +static DF1(jtgf1){A h=VAV(self)->h; R df1( w,*AAV(h));} +static DF2(jtgf2){A h=VAV(self)->h; R df2(a,w,*AAV(h));} + +A jtvger2(J jt,C id,A a,A w){A h,*hv,x;V*v; + RZ(x=a?a:w); + ASSERT(2==AN(x),EVLENGTH); + RZ(h=fxeachv(1L,x)); hv=AAV(h); v=VAV(*hv); + R fdef(id,VERB, jtgf1,jtgf2, x,a?w:0L, h, VGERL, (I)v->mr,(I)v->lr,(I)v->rr); +} /* verify and define 2-element gerund */ diff --git a/ch.c b/ch.c new file mode 100644 --- /dev/null +++ b/ch.c @@ -0,0 +1,119 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Conjunctions: Hypergeometric Series */ + +#include "j.h" + + +static A jthparm(J jt,A j,A f,A h){A z; + if(!(VERB&AT(f)))R shift1(aslash(CSTAR,atab(CPLUS,h,j))); + RZ(z=CALL1(VAV(f)->f1,j,f)); + ASSERT(1>=AR(z),EVRANK); + ASSERT(!AR(z)||AN(j)==AN(z),EVLENGTH); + R z; +} + +static A jthgv(J jt,B b,I n,A w,A self){A c,d,e,h,*hv,j,y;V*sv=VAV(self); + RZ(j=IX(n)); h=sv->h; hv=AAV(h); + c=hparm(j,sv->f,hv[0]); + d=hparm(j,sv->g,hv[1]); + e=shift1(divide(w,apv(n,1L,1L))); + switch((VERB&AT(sv->f)?2:0)+(VERB&AT(sv->g)?1:0)){ + case 0: y=ascan(CSTAR,divide(tymes(c,e),d)); break; + case 1: y=divide(ascan(CSTAR,tymes(c,e)),d); break; + case 2: y=divide(tymes(c,ascan(CSTAR,e)),ascan(CSTAR,d)); break; + case 3: y=divide(tymes(c,ascan(CSTAR,e)),d); + } + R b?over(zero,ascan(CPLUS,y)):aslash(CPLUS,y); +} /* verb or complex cases */ + +static A jthgd(J jt,B b,I n,A w,A p,A q){A c,d,e,z;D r,s,t,*u,*v,x,*zv;I j,pn,qn; + RZ(c=cvt(FL,p)); u=DAV(c); pn=AN(c); + RZ(d=cvt(FL,q)); v=DAV(d); qn=AN(d); + RZ(e=cvt(FL,w)); x=*DAV(e); r=s=1; t=0; z=0; + if(b&&2000>n){GA(z,FL,1+n,1,0); zv=DAV(z); *zv++=0; *zv++=1;} + NAN0; + for(j=1;jh; hv=AAV(h); + b=VERB&(AT(sv->f)|AT(sv->g))||CMPX&(AT(w)|AT(hv[0])|AT(hv[1])); + if(!b)z=hgd((B)(1n)z=hgv((B)(1=AR(a),EVRANK);} + if(q){d=w; ASSERT(!AN(w)||wt&NUMERIC,EVDOMAIN); ASSERT(1>=AR(w),EVRANK);} + RZ(h=cancel(c,d)); + R fdef(CHGEOM,VERB, jthgeom1,jthgeom2, a,w,h, 0L, 0L,0L,0L); +} /* a H. w */ + +F1(jthgdiff){A*hv,p,q,x,y;V*v=VAV(w); + ASSERTNN(v->f,v->g); + hv=AAV(v->h); + x=hv[0]; x=1==AN(x)?head(x):x; + y=hv[1]; y=1==AN(y)?head(y):y; + p=divide(aslash(CSTAR,x),aslash(CSTAR,y)); + q=hgeom(increm(x),increm(y)); + R equ(p,one)?q:folk(qq(p,zero),ds(CSTAR),q); +} /* a H. w D. 1 */ + +DF1(jthgcoeff){PROLOG;A c,d,h,*hv,y,z;B b;I j,n,pn,qn,*v;V*sv=VAV(self); + RZ(w=vi(w)); v=AV(w); + n=0; DO(AN(w), j=v[i]; ASSERT(0<=j,EVDOMAIN); if(nh; hv=AAV(h); + b=VERB&(AT(sv->f)|AT(sv->g))||CMPX&(AT(w)|AT(hv[0])|AT(hv[1])); + if(!b){D r=1.0,*u,*v,*yv; + RZ(c=cvt(FL,hv[0])); u=DAV(c); pn=AN(c); + RZ(d=cvt(FL,hv[1])); v=DAV(d); qn=AN(d); + GA(y,FL,n,1,0); yv=DAV(y); + DO(n, DO(pn, r*=u[i]; ++u[i];); DO(qn, r/=v[i]; ++v[i];); yv[i]=r;); + }else{A j; + RZ(j=IX(n)); + c=hparm(j,sv->f,hv[0]); + d=hparm(j,sv->g,hv[1]); + switch((VERB&AT(sv->f)?2:0)+(VERB&AT(sv->g)?1:0)){ + case 0: y=ascan(CSTAR,divide(c,d)); break; + case 1: y=divide(ascan(CSTAR,c),d); break; + case 2: y=divide(c,ascan(CSTAR,d)); break; + case 3: y=divide(c,d); + }} + RZ(z=from(w,over(one,y))); + EPILOG(z); +} /* coefficients indexed by w excluding !j */ diff --git a/cip.c b/cip.c new file mode 100644 --- /dev/null +++ b/cip.c @@ -0,0 +1,270 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Conjunctions: Inner Product */ + +#include "j.h" +#include "vasm.h" + + +static A jtipprep(J jt,A a,A w,I zt,I*pm,I*pn,I*pp){A z=mark;I*as,ar,ar1,m,mn,n,p,*ws,wr,wr1; + ar=AR(a); as=AS(a); ar1=ar?ar-1:0; RE(*pm=m=prod(ar1, as)); + wr=AR(w); ws=AS(w); wr1=wr?wr-1:0; RE(*pn=n=prod(wr1,1+ws)); RE(mn=mult(m,n)); + *pp=p=ar?*(as+ar1):wr?*ws:1; + ASSERT(!(ar&&wr)||p==*ws,EVLENGTH); + GA(z,zt,mn,ar1+wr1,0); + ICPY(AS(z), as,ar1); + ICPY(AS(z)+ar1,1+ws,wr1); + R z; +} /* argument validation & result for an inner product */ + +#define IINC(x,y) {b=0>x; x+=y; BOV(b==0>y&&b!=0>x);} +#define DINC(x,y) {x+=y;} +#define ZINC(x,y) {(x).re+=(y).re; (x).im+=(y).im;} + +#define PDTBY(Tz,Tw,INC) \ + {Tw*v,*wv;Tz c,*x,zero,*zv; \ + v=wv=(Tw*)AV(w); zv=(Tz*)AV(z); memset(&zero,C0,sizeof(Tz)); \ + if(1==n)DO(m, v=wv; c=zero; DO(p, if(*u++)INC(c,*v); ++v;); *zv++=c;) \ + else DO(m, v=wv; memset(zv,C0,zk); DO(p, x=zv; if(*u++)DO(n, INC(*x,*v); ++x; ++v;) else v+=n;); zv+=n; ); \ + } + +#define PDTXB(Tz,Ta,INC,INIT) \ + {Ta*u;Tz c,*x,zero,*zv; \ + u= (Ta*)AV(a); zv=(Tz*)AV(z); memset(&zero,C0,sizeof(Tz)); \ + if(1==n)DO(m, v=wv; c=zero; DO(p, if(*v++)INC(c,*u); ++u; ); *zv++=c;) \ + else DO(m, v=wv; memset(zv,C0,zk); DO(p, x=zv; INIT; DO(n, if(*v++)INC(*x,c); ++x;);); zv+=n; ); \ + } + +static F2(jtpdtby){A z;B b,*u,*v,*wv;C er=0;I at,m,n,p,t,wt,zk; + at=AT(a); wt=AT(w); t=at&B01?wt:at; + RZ(z=ipprep(a,w,t,&m,&n,&p)); zk=n*bp(t); u=BAV(a); v=wv=BAV(w); + NAN0; + switch(t){ + default: ASSERT(0,EVDOMAIN); + case CMPX: if(at&B01)PDTBY(Z,Z,ZINC) else PDTXB(Z,Z,ZINC,c=*u++ ); break; + case FL: if(at&B01)PDTBY(D,D,DINC) else PDTXB(D,D,DINC,c=*u++ ); break; + case INT: if(at&B01)PDTBY(I,I,IINC) else PDTXB(I,I,IINC,c=*u++ ); + if(er==EWOV){ + RZ(z=ipprep(a,w,FL,&m,&n,&p)); zk=n*sizeof(D); u=BAV(a); v=wv=BAV(w); + if(at&B01)PDTBY(D,I,IINC) else PDTXB(D,I,IINC,c=(D)*u++); + }} + NAN1; + R z; +} /* x +/ .* y where x or y (but not both) is Boolean */ + +#define BBLOCK(nn) \ + d=ti; DO(nw, *d++=0;); \ + DO(nn, if(*u++){vi=(UI*)v; d=ti; DO(nw, *d+++=*vi++;);} v+=n;); \ + x=zv; c=tc; DO(n, *x+++=*c++;); + +#if defined(NOASM) && SY_64 +/* +*** from asm64noovf.c +C asminnerprodx(I m,I*z,I u,I*y) +{ + I i=-1,t; +l1: + ++i; + if(i==m) return 0; + t= u FTIMES y[i]; + ov(t) + t= t FPLUS z[i]; + ov(t) + z[i]=t; + goto l1; +} +*/ + +C asminnerprodx(I m,I*z,I u,I*y) +{ + I i=-1,t,p;DI tdi; +l1: + ++i; + if(i==m) return 0; + tdi = u * (DI)y[i]; + t=(I)tdi; + if (tdit; + t= t + z[i]; + if (p==0>z[i]&&p!=0>t) R EWOV; + z[i]=t; + goto l1; +} +#endif + +F2(jtpdt){PROLOG;A z;I ar,at,i,m,n,p,p1,t,wr,wt; + RZ(a&&w); + ar=AR(a); at=AN(a)?AT(a):B01; + wr=AR(w); wt=AN(w)?AT(w):B01; + if((at|wt)&SPARSE)R pdtsp(a,w); + if((at|wt)&XNUM+RAT)R df2(a,w,atop(slash(ds(CPLUS)),qq(ds(CSTAR),v2(1L,AR(w))))); + if(ar&&wr&&AN(a)&&AN(w)&&at!=wt&&B01&at+wt)R pdtby(a,w); + t=coerce2(&a,&w,B01); + ASSERT(t&NUMERIC,EVDOMAIN); + RZ(z=ipprep(a,w,t&B01?INT:t&INT&&!SY_64?FL:t,&m,&n,&p)); + if(!p){memset(AV(z),C0,AN(z)*bp(AT(z))); R z;} + if(!ar!=!wr){if(ar)RZ(w=reshape(sc(p),w)) else RZ(a=reshape(sc(p),a));} + p1=p-1; + switch(t){ + case B01: + if(0==n%SZI||!SY_ALIGN){A tt;B*u,*v,*wv;I nw,q,r,*x,*zv;UC*c,*tc;UI*d,*ti,*vi; + q=p/255; r=p%255; nw=(n+SZI-1)/SZI; + GA(tt,INT,nw,1,0); ti=(UI*)AV(tt); tc=(UC*)ti; + u=BAV(a); v=wv=BAV(w); zv=AV(z); + for(i=0;ire =ZRE(c,*v); x->im =ZIM(c,*v); ++x; ++v;); + DO(p1, x=zv; c=*u++; DO(n, x->re+=ZRE(c,*v); x->im+=ZIM(c,*v); ++x; ++v;);); + }}} + EPILOG(z); +} + +#define IPBX(F) \ + for(i=0;if; gs=sv->g; + if(B01&AT(a)&&AN(a)&&AN(w)&&CSLASH==ID(fs)&&(d=vaid(gs))&& + (c=vaid(VAV(fs)->f),c==CSTARDOT||c==CPLUSDOT||c==CNE))R ipbx(a,w,c,d); + r=lr(gs); + R df2(a,w,atop(fs,qq(gs,v2(r==RMAX?r:1+r,RMAX)))); +} + + +F1(jtminors){A d; + RZ(d=apv(3L,-1L,1L)); *AV(d)=0; + R drop(d,df2(one,w,bsdot(ds(CLEFT)))); +} + +static DF1(jtdet){DECLFG;A h=sv->h;I c,r,*s; + RZ(w); + r=AR(w); s=AS(w); + if(h&&1r?1:s[1]; + R !c ? df1(mtv,slash(gs)) : 1==c ? CALL1(f1,ravel(w),fs) : h && c==*s ? gaussdet(w) : detxm(w,self); +} + +DF1(jtdetxm){R dotprod(irs1(w,0L,1L,jthead),det(minors(w),self),self);} + /* determinant via expansion by minors. w is matrix with >1 columns */ + +F2(jtdot){A f,h=0;AF f2=jtdotprod;C c,d; + ASSERTVV(a,w); + if(CSLASH==ID(a)){ + f=VAV(a)->f; c=ID(f); d=ID(w); + if(d==CSTAR){ + if(c==CPLUS )f2=jtpdt; + if(c==CMINUS)RZ(h=eval("[: -/\"1 {.\"2 * |.\"1@:({:\"2)")); + }} + R fdef(CDOT,VERB, jtdet,f2, a,w,h, 0L, 2L,RMAX,RMAX); +} diff --git a/cip_t.h b/cip_t.h new file mode 100644 --- /dev/null +++ b/cip_t.h @@ -0,0 +1,41 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Template for ipbx (boolean inner products) */ + +/* requires F(x,y) *x++g=*y++ where g is one of | & ^ */ + +if(c==CPLUSDOT&&(c0==IPBX1||c1==IPBX1)||c==CSTARDOT&&(c0==IPBX0||c1==IPBX0)){ + e=c==CPLUSDOT?c1==IPBX1:c1==IPBX0; + for(i=0;ilmon>=level(w)){fs=VAV(self)->f; R CALL1(VAV(fs)->f1,w,fs);} else R every(w,self,jtlev1); +} + +static A jtlev2(J jt,A a,A w,A self){A fs; + RZ(a&&w&&self); + switch((jt->lleft>=level(a)?2:0)+(jt->lright>=level(w))){ + case 0: R every2(a, w, self,jtlev2); + case 1: R every2(a, box(w),self,jtlev2); + case 2: R every2(box(a),w, self,jtlev2); + default: fs=VAV(self)->f; R CALL2(VAV(fs)->f2,a,w,fs); +}} + +static I jtefflev(J jt,I j,A h,A x){I n,t; n=*(j+AV(h)); R n>=0?n:(t=level(x),MAX(0,n+t));} + +static DF1(jtlcapco1){A z;I m;V*v=VAV(self); + RZ(w); + m=jt->lmon; jt->lmon=efflev(0L,v->h,w); + z=lev1(w,self); + jt->lmon=m; + R z; +} + +static DF2(jtlcapco2){A z;I l,r;V*v=VAV(self); + RZ(a&&w); + l=jt->lleft; jt->lleft =efflev(1L,v->h,a); + r=jt->lright; jt->lright=efflev(2L,v->h,w); + z=lev2(a,w,self); + jt->lleft =l; + jt->lright=r; + R z; +} + + +static F1(jtscfn){ + RZ(w); + if(jt->scn==AN(jt->sca)){RZ(jt->sca=ext(1,jt->sca)); jt->scv=AV(jt->sca);} + jt->scv[jt->scn++]=(I)w; + R zero; +} + +static A jtlevs1(J jt,A w,A self){A fs; + RZ(w&&self); + if(jt->lmon>=level(w)){fs=VAV(self)->f; R scfn(CALL1(VAV(fs)->f1,w,fs));}else R every(w,self,jtlevs1); +} + +static A jtlevs2(J jt,A a,A w,A self){A fs; + RZ(a&&w&&self); + switch((jt->lleft>=level(a)?2:0)+(jt->lright>=level(w))){ + case 0: R every2(a, w, self,jtlevs2); + case 1: R every2(a, box(w),self,jtlevs2); + case 2: R every2(box(a),w, self,jtlevs2); + default: fs=VAV(self)->f; R scfn(CALL2(VAV(fs)->f2,a,w,fs)); +}} + +static DF1(jtscapco1){A x,z=0;I m;V*v=VAV(self); + RZ(w); + m=jt->lmon; jt->lmon=efflev(0L,v->h,w); + GA(x,INT,100,1,0); jt->scv=AV(x); jt->sca=x; jt->scn=0; + ra(jt->sca); + x=levs1(w,self); + jt->lmon=m; + if(x)z=ope(vec(BOX,jt->scn,jt->scv)); + fa(jt->sca); + R z; +} + +static DF2(jtscapco2){A x,z=0;I l,r;V*v=VAV(self); + RZ(a&&w); + l=jt->lleft; jt->lleft =efflev(1L,v->h,a); + r=jt->lright; jt->lright=efflev(2L,v->h,w); + GA(x,INT,100,1,0); jt->scv=AV(x); jt->sca=x; jt->scn=0; + ra(jt->sca); + x=levs2(a,w,self); + jt->lleft =l; + jt->lright=r; + if(x)z=ope(vec(BOX,jt->scn,jt->scv)); + fa(jt->sca); + R z; +} + + +static A jtlsub(J jt,C id,A a,A w){A h,t;B b=id==CLCAPCO;I*hv,n,*v; + RZ(a&&w); + ASSERT(VERB&AT(a)&&NOUN&AT(w),EVDOMAIN); + n=AN(w); + ASSERT(1>=AR(w),EVRANK); + ASSERT(0c)c+=an; ASSERT(0<=c&&cc)c+=an; ASSERT(0<=c&&cf; + R AT(w)&B01+INT?tclosure(VAV(fs)->g,w):powseqlim(w,fs); +} /* {&x^:(<_) w */ + +static DF2(jtindexseqlim2){ + RZ(a&&w); + R 1==AR(a)&&AT(a)&INT&&AT(w)&B01+INT?tclosure(a,w):powseqlim(w,amp(ds(CFROM),a)); +} /* a {~^:(<_) w */ + +static DF1(jtpowseq){A fs,gs,x;I n=IMAX;V*sv; + RZ(w); + sv=VAV(self); fs=sv->f; gs=sv->g; + ASSERT(!AR(gs),EVRANK); + ASSERT(BOX&AT(gs),EVDOMAIN); + x=*AAV(gs); if(!AR(x))RE(n=i0(vib(x))); + if(0>n){RZ(fs=inv(fs)); n=-n;} + if(n==IMAX||1==AR(x)&&!AN(x))R powseqlim(w,fs); + R df1(w,powop(fs,IX(n))); +} /* f^:(h)){ + case 0: R ca(w); + case 1: fs=sv->f; R CALL1(VAV(fs)->f1,w,fs); + default: + fs=sv->f; f1=VAV(fs)->f1; + z=w; + old=jt->tbase+jt->ttop; + DO(n, RZ(z=CALL1(f1,z,fs)); gc(z,old);); + R z; +}} /* single positive finite exponent */ + +static DF1(jtply1){PROLOG;DECLFG;A b,hs,j,x,*xv,y,z;B*bv,q;I i,k,m,n,*nv,old,p=0; + hs=sv->h; m=AN(hs); + RZ(x=ravel(hs)); RZ(y=from(j=grade1(x),x)); nv=AV(y); + GA(x,BOX,m,1,0); xv=AAV(x); + while(pnv[p])p++; + if(ptbase+jt->ttop; + for(i=1;i<=n;++i){ + RZ(z=CALL1(f1,y=z,fs)); + if(q&&equ(y,z)){DO(m-k, xv[k]=z; ++k;); break;} + while(kf1; + RZ(z=ca(w)); + n=nv[0]; k=p-1; + RZ(b=eq(scf(-inf),from(j,ravel(gs)))); bv=BAV(b); q=bv[k]; + old=jt->tbase+jt->ttop; + for(i=-1;i>=n;--i){ + RZ(z=CALL1(f1,y=z,fs)); + if(q&&equ(y,z)){DO(1+k, xv[k]=z; --k;); break;} + while(0<=k&&i==nv[k]){xv[k]=z; --k; q=0<=k?bv[k]:0;} + if(!(i%10))gc3(x,z,0L,old); + }} + z=ope(reshape(shape(hs),from(grade1(j),x))); EPILOG(z); +} + +#define DIST(i,x) if(i==e){v=CAV(x); \ + while(kh; m=AN(hs); nv=AV(hs); + RZ(j=grade1(ravel(hs))); jv=AV(j); e=nv[*jv]; + if(!e&&!nv[jv[m-1]])R reshape(over(shape(hs),shape(w)),w); + RZ(y=y1=CALL1(f1,w,fs)); t=AT(y); r=AR(y); + if(0>e||t==BOX)R ply1(w,self); + if(!e){ + if(HOMO(t,AT(w)))RZ(w=pcvt(t,w)); + if(!(t==AT(w)&&AN(y)==AN(w)&&(r==AR(w)||1>=r&&1>=AR(w))))R ply1(w,self); + } + k=AR(hs); RE(zn=mult(m,AN(y))); + GA(z,AT(y),zn,k+AR(y),0); zv=CAV(z); + s=AS(z); ICPY(s,AS(hs),k); ICPY(k+s,AS(y),r); + n=nv[jv[m-1]]; c=AN(y)*bp(t); s=AS(y); + k=0; DIST(0,w); DIST(1,y); + for(i=2;i<=n;++i){ + RZ(y=CALL1(f1,y,fs)); + if(t!=AT(y)||r!=AR(y)||ICMP(AS(y),s,r))R ply1(w,self); + DIST(i,y); + } + R z; +} /* f^:n w, non-negative finite n, well-behaved f */ + +static DF1(jtinv1){DECLFG;A z; RZ(w); FDEPINC(1); z=df1(w,inv(fs)); FDEPDEC(1); R z;} +static DF2(jtinv2){DECLFG;A z; RZ(a&&w); FDEPINC(1); z=df1(w,inv(amp(a,fs))); FDEPDEC(1); R z;} + +static CS2(jtply2, df1(w,powop(amp(a,fs),gs))) + +static DF1(jtpowg1){A h=VAV(self)->h; R df1( w,*AAV(h));} +static DF2(jtpowg2){A h=VAV(self)->h; R df2(a,w,*AAV(h));} + +static CS1(jtpowv1, df1( w,powop(fs, CALL1(g1, w,gs)))) +static CS2(jtpowv2, df2(a,w,powop(fs, CALL2(g2,a,w,gs)))) +static CS2(jtpowv2a, df1( w,powop(VAV(fs)->f,CALL2(g2,a,w,gs)))) + +F2(jtpowop){A hs;B b,r;I m,n;V*v; + RZ(a&&w); + switch(CONJCASE(a,w)){ + default: ASSERTSYS(0,"powop"); + case NV: ASSERT(0,EVDOMAIN); + case NN: ASSERT(-1==i0(w),EVDOMAIN); R vger2(CPOWOP,a,w); + case VV: + v=VAV(a); b=(v->id==CAT||v->id==CATCO)&&ID(v->g)==CRIGHT; + R CDERIV(CPOWOP,jtpowv1,b?jtpowv2a:jtpowv2,RMAX,RMAX,RMAX); + case VN: + if(BOX&AT(w)){A x,y;AF f1,f2; + if(ARELATIVE(w))RZ(w=car(w)); + if(!AR(w)&&(x=*AAV(w),!AR(x)&&NUMERIC&AT(x)||1==AR(x)&&!AN(x))){ + f1=jtpowseq; f2=jtply2; v=VAV(a); + if((!AN(x)||FL&AT(x)&&inf==*DAV(x))&& + CAMP==v->id&&(CFROM==ID(v->f)&&(y=v->g,INT&AT(y)&&1==AR(y))))f1=jtindexseqlim1; + if(CTILDE==v->id&&CFROM==ID(v->f))f2=jtindexseqlim2; + R CDERIV(CPOWOP,f1,f2,RMAX,RMAX,RMAX); + } + R gconj(a,w,CPOWOP); + } + RZ(hs=vib(w)); + b=0; m=AN(hs); n=m?*AV(hs):0; r=0*v&&v*u&&uk){*v++=i; k=j;}); + *v++=q; AN(x)=*AS(x)=k=v-*nv; *m=k-1; + } + R 1; +} + +/* ii - row index in result */ +/* zjn - # temp result values to be harvested */ +/* zj - temp result column indices */ +/* zyv - ptr to temp result values */ +/* n - # result values so far */ +/* zi - ptr to result index array */ +/* zx - ptr to result value array */ +static B jtmmharvest(J jt,I ii,I zjn,A zj,D*zyv,I*n,A*zi,A*zx){A x;D*zxv,*zxv0;I j,m,p,*v,*ziv; + m=MIN(*AS(*zi),*AS(*zx)); + while(m<*n+zjn){RZ(*zi=ext(0,*zi)); RZ(*zx=ext(0,*zx)); m=MIN(*AS(*zi),*AS(*zx));} + m=AN(zj); AN(zj)=*AS(zj)=zjn; RZ(x=grade2(zj,zj)); AN(zj)=*AS(zj)=m; + p=-1; v=AV(x); ziv=AV(*zi)+(*n<<1); zxv=zxv0=DAV(*zx)+*n; + DO(zjn, if(p<(j=*v++)){p=j; *ziv++=ii; *ziv++=j; *zxv++=zyv[j]; zyv[j]=0;}); + *n+=zxv-zxv0; + R 1; +} /* collect accumulated values for row ii */ + +static F2(jtpdtspmm){A z,zi,zj,zx,zy;D*axv,c,d,*dv,*wxv,*zyv; + I*aiv,*aivm,i,ii,j,k,k0,m,n=0,old,p,q,*v,wm,*wiv,*wnv,*zjv,*zjv0;P*zp; + RZ(a&&w); + RZ(mmprep(PAV(a),&m,&aiv,0L ,0L ,&axv)); aivm=m+aiv; + RZ(mmprep(PAV(w),&m,&wiv,&wm,&wnv,&wxv)); + GA(zy,FL,*(1+AS(w)),1,0); zyv=DAV(zy); memset(zyv,C0,AN(zy)*sizeof(D)); + old=jt->tbase+jt->ttop; + RZ(zj=exta(INT,1L,1L,1000L)); zjv0=AV(zj); + RZ(zi=exta(INT,2L,2L,1000L)); + RZ(zx=exta(FL, 1L,1L,1000L)); + NAN0; + if(wm&&aiv>1]<<1]; if(j==ii)break; if(j=aivm||i<(p=*aiv++)){ /* done with row i in a, emit row i in z */ + RZ(mmharvest(i,zjv-zjv0,zj,zyv,&n,&zi,&zx)); + gc3(zj,zi,zx,old); + zjv=zjv0; k=-1; i=p; + }}} + NAN1; + *AS(zx)=AN(zx)=*AS(zi)=n; AN(zi)=n<<1; + GA(z,SFL,1,2,AS(a)); *(1+AS(z))=*(1+AS(w)); + zp=PAV(z); SPB(zp,a,IX(2)); SPB(zp,e,scf(0.0)); SPB(zp,i,zi); SPB(zp,x,zx); + R z; +} + + +F2(jtpdtsp){A x;B ab=0,wb=0;P*p; + RZ(a&&w); + ASSERT(!AR(a)||!AR(w)||*(AS(a)+AR(a)-1)==*AS(w),EVLENGTH); + if(AT(a)&FL+SFL&&AT(w)&FL+SFL){ + if(SPARSE&AT(a)){p=PAV(a); x=SPA(p,a); ab=AR(a)==AN(x)&&equ(zero,SPA(p,e));} + if(SPARSE&AT(w)){p=PAV(w); x=SPA(p,a); wb=AR(w)==AN(x)&&equ(zero,SPA(p,e));} + } + if(ab&&1==AR(a)&&wb&&1==AR(w))R pdtspvv(a,w); + if(ab&&2==AR(a)&& 1==AR(w))R pdtspmv(a,w); + if( 1==AR(a)&&wb&&2==AR(w))R pdtspvm(a,w); + if(ab&&2==AR(a)&&wb&&2==AR(w))R pdtspmm(a,w); + R df2(a,w,atop(slash(ds(CPLUS)),qq(ds(CSTAR),v2(1L,AR(w))))); +} diff --git a/cr.c b/cr.c new file mode 100644 --- /dev/null +++ b/cr.c @@ -0,0 +1,171 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Conjunctions: Rank Associates */ + +#include "j.h" + +#define DR(r) (0>r?RMAX:r) + + +I mr(A w){R VAV(w)->mr;} +I lr(A w){R VAV(w)->lr;} +I rr(A w){R VAV(w)->rr;} + +I efr(I ar,I r){R 0>r?MAX(0,r+ar):MIN(r,ar);} + +#define NEWYA {GA(ya,at,acn,acr,as+af); uu=CAV(ya);} +#define NEWYW {GA(yw,wt,wcn,wcr,ws+wf); vv=CAV(yw);} +#define MOVEYA {MC(uu,u+=ak,ak); if(ab)RZ(ya=relocate((I)a-(I)ya,ya));} +#define MOVEYW {MC(vv,v+=wk,wk); if(wb)RZ(yw=relocate((I)w-(I)yw,yw));} + +A jtrank1ex(J jt,A w,A fs,I mr,AF f1){PROLOG;A y,y0,yw,z;B wb;C*v,*vv; + I k,mn,n=1,p,*s,wcn,wcr,wf,wk,wr,*ws,wt,yn,yr,*ys,yt; + RZ(w); + wt=AT(w); + if(wt&SPARSE)R sprank1(w,fs,mr,f1); + wr=AR(w); ws=AS(w); wcr=efr(wr,mr); wf=wr-wcr; wb=ARELATIVE(w); + if(!wf)R CALL1(f1,w,fs); + RE(wcn=prod(wcr,wf+ws)); wk=wcn*bp(wt); v=CAV(w)-wk; NEWYW; + p=wf; s=ws; RE(mn=prod(wf,ws)); + if(AN(w))MOVEYW else RZ(yw=reshape(vec(INT,wcr,ws+wf),filler(w))); +#define VALENCE 1 +#define TEMPLATE 0 +#include "cr_t.h" +} + +A jtrank2ex(J jt,A a,A w,A fs,I lr,I rr,AF f2){PROLOG;A y,y0,ya,yw,z;B ab,b,wb; + C*u,*uu,*v,*vv;I acn,acr,af,ak,ar,*as,at,k,mn,n=1,p,q,*s,wcn,wcr,wf,wk,wr,*ws,wt,yn,yr,*ys,yt; + RZ(a&&w); + at=AT(a); wt=AT(w); + if(at&SPARSE||wt&SPARSE)R sprank2(a,w,fs,lr,rr,f2); + ar=AR(a); as=AS(a); acr=efr(ar,lr); af=ar-acr; ab=ARELATIVE(a); + wr=AR(w); ws=AS(w); wcr=efr(wr,rr); wf=wr-wcr; wb=ARELATIVE(w); + if(!af&&!wf)R CALL2(f2,a,w,fs); + RE(acn=prod(acr,as+af)); ak=acn*bp(at); u=CAV(a)-ak; NEWYA; + RE(wcn=prod(wcr,ws+wf)); wk=wcn*bp(wt); v=CAV(w)-wk; NEWYW; + b=af<=wf; p=b?wf:af; q=b?af:wf; s=b?ws:as; RE(mn=prod(p,s)); RE(n=prod(p-q,s+q)); + ASSERT(!ICMP(as,ws,q),EVLENGTH); + if(AN(a))MOVEYA else RZ(ya=reshape(vec(INT,acr,as+af),filler(a))); + if(AN(w))MOVEYW else RZ(yw=reshape(vec(INT,wcr,ws+wf),filler(w))); +#define VALENCE 2 +#define TEMPLATE 0 +#include "cr_t.h" +} + + +/* Integrated Rank Support */ +/* f knows how to compute f"r */ +/* jt->rank points to a 2-element vector of */ +/* (left, right (monadic)) ranks */ +/* 0=jt->rank means f is not being called from rank */ +/* jt->rank is guaranteed positive */ +/* jt->rank is guaranteed <: argument ranks */ +/* frame agreement is verified before invoking f */ +/* frames either match, or one is empty */ +/* (i.e. prefix agreement invokes general case) */ + +A jtirs1(J jt,A w,A fs,I m,AF f1){A z;I*old=jt->rank,rv[2],wr; + RZ(w); + wr=AR(w); rv[1]=m=efr(wr,m); + if(m>=wr)R CALL1(f1,w,fs); + rv[0]=0; + jt->rank=rv; z=CALL1(f1,w,fs); jt->rank=old; + R z; +} + +A jtirs2(J jt,A a,A w,A fs,I l,I r,AF f2){A z;I af,ar,*old=jt->rank,rv[2],wf,wr; + RZ(a&&w); + ar=AR(a); rv[0]=l=efr(ar,l); af=ar-l; + wr=AR(w); rv[1]=r=efr(wr,r); wf=wr-r; + if(!(af||wf))R CALL2(f2,a,w,fs); + ASSERT(!ICMP(AS(a),AS(w),MIN(af,wf)),EVLENGTH); + /* if(af&&wf&&af!=wf)R rank2ex(a,w,fs,l,r,f2); */ + jt->rank=rv; z=CALL2(f2,a,w,fs); jt->rank=old; + R z; +} + + +static DF1(cons1a){R VAV(self)->f;} + +static DF2(cons2a){R VAV(self)->f;} + +static DF1(cons1){V*sv=VAV(self); + RZ(w); + R rank1ex(w,self,efr(AR(w),*AV(sv->h)),cons1a); +} + +static DF2(cons2){V*sv=VAV(self);I*v=AV(sv->h); + RZ(a&&w); + R rank2ex(a,w,self,efr(AR(a),v[1]),efr(AR(w),v[2]),cons2a); +} + +static DF1(rank1i){DECLF;A h=sv->h;I*v=AV(h); R irs1(w,fs,*v,f1);} + +static DF2(rank2i){DECLF;A h=sv->h;I*v=AV(h); R irs2(a,w,fs,v[1],v[2],f2);} + +static DF1(rank1){DECLF;A h=sv->h;I m,*v=AV(h),wr; + RZ(w); + wr=AR(w); m=efr(wr,v[0]); + R mh;I ar,l,r,*v=AV(h),wr; + RZ(a&&w); + ar=AR(a); l=efr(ar,v[1]); + wr=AR(w); r=efr(wr,v[2]); + R l f"r monad */ + static C ir1[]={CCOMMA,CLAMIN,CLEFT,CRIGHT,CCANT,CROT,CTAKE,CDROP,CGRADE,CDGRADE, + CBOX,CNE,CTAIL,CCTAIL,CSLASH,CBSLASH,CBSDOT,CCOMDOT,CPCO,CATDOT,0}; + static C ir2[]={CCOMMA,CLAMIN,CLEFT,CRIGHT,CCANT,CROT,CTAKE,CDROP,CGRADE,CDGRADE, + CDOLLAR,CPOUND,CIOTA,CICO,CEPS,CLBRACE,CMATCH, + CEQ,CLT,CMIN,CLE,CGT,CMAX,CGE,CPLUS,CPLUSDOT,CPLUSCO,CSTAR,CSTARDOT,CSTARCO, + CMINUS,CDIV,CEXP,CNE,CSTILE,CBANG,CCIRCLE,0}; + if(NOUN&AT(a)){*f1=cons1; *f2=cons2; *flag=0; R;} + v=VAV(a); c=v->id; + if(strchr(ir1,c))m+=VIRS1; + if(strchr(ir2,c))m+=VIRS2; + if(!(m&VIRS1)&&v->flag&VIRS1&&c!=CQQ)m+=VIRS1; + if(!(m&VIRS2)&&v->flag&VIRS2&&c!=CQQ)m+=VIRS2; + if(!m){ + p=0; if(f=v->f)p=VERB&AT(f)&&strchr(ir2,d=ID(f)); + q=0; if(g=v->g)q=VERB&AT(g)&&strchr(ir2,e=ID(g)); + switch(c){ + case CFIT: if(p&&d!=CEXP)m+=VIRS2; if(d==CNE)m+=VIRS1; break; + case CTILDE: if(p)m+=VIRS1+VIRS2; break; + case CAMP: if(p&&NOUN&AT(g)||q&&NOUN&AT(f))m+=VIRS1; break; + case CFORK: if(v->f1==(AF)jtmean)m+=VIRS1; + }} + *f1=strchr(at1,c) ? v->f1 : m&VIRS1 ? rank1i : rank1; + *f2= m&VIRS2 ? rank2i : rank2; + *flag=m; +} + +F2(jtqq){A h,t;AF f1,f2;D*d;I flag,*hv,n,r[3],*v; + RZ(a&&w); + GA(h,INT,3,1,0); hv=AV(h); + if(VERB&AT(w)){ + GA(t,FL,3,1,0); d=DAV(t); + n=r[0]=hv[0]=mr(w); d[0]=n<=-RMAX?-inf:RMAX<=n?inf:n; + n=r[1]=hv[1]=lr(w); d[1]=n<=-RMAX?-inf:RMAX<=n?inf:n; + n=r[2]=hv[2]=rr(w); d[2]=n<=-RMAX?-inf:RMAX<=n?inf:n; + w=t; + }else{ + n=AN(w); + ASSERT(1>=AR(w),EVRANK); + ASSERT(0db; jt->db=0; y=RCALL; jt->db=d; + if(jt->jerr){y=zero; RESETERR;} + } + yt=AT(y); yr=AR(y); ys=AS(y); yn=AN(y); k=yn*bp(yt); + if(!mn||yt&DIRECT&&RFLAG){I zn; + RARGX; RE(zn=mult(mn,yn)); + GA(z,yt,zn,p+yr,0L); ICPY(AS(z),s,p); ICPY(p+AS(z),ys,yr); + if(mn){zv=CAV(z); MC(zv,AV(y),k);} + old=jt->tbase+jt->ttop; + for(j=1;jwf?m:1); + GA(z, BOX,j, 1,0); zv=AAV(z); + GA(zi,INT,j*g,2,0); v=AS(zi); v[0]=j; v[1]=g; iv=AV(zi); + RE(aj=ak=spradv(an,ab,af,acr,0L,ap,&aa)); + RE(wj=wk=spradv(wn,wb,wf,wcr,0L,wp,&ww)); j=s=k=0; u=ii; y=0; v=0; + if(af==wf)while(av||wv){ + if(av&&wv)DO(f, if(s=av[i]-wv[i])break;) else s=av?-1:1; + if (0==s){RZ(zv[j++]=CALL2(f2,aa,ww,fs)); ICPY(iv,av,f); iv+=g;} + else if(0> s){RZ(zv[j++]=CALL2(f2,aa,we,fs)); ICPY(iv,av,f); iv+=g;} + else if(0< s){RZ(zv[j++]=CALL2(f2,ae,ww,fs)); ICPY(iv,wv,f); iv+=g;} + if(0>=s){if(aj==an)av=0; else{av+=ak*ac; RE(ak=spradv(an,ab,af,acr,aj,ap,&aa)); aj+=ak;}} + if(0<=s){if(wj==wn)wv=0; else{wv+=wk*wc; RE(wk=spradv(wn,wb,wf,wcr,wj,wp,&ww)); wj+=wk;}} + }else while(av||wv){ + if(av&&wv&&f)DO(f, if(s=av[i]-wv[i])break;) else s=!f?0:av?-1:1; + if(b&&0s){RZ(zv[j++]=CALL2(f2,b?ae:aa,b?ww:we,fs)); ICPY(iv,b?wv:av,g); iv+=g; k=m;} + else if(s){ + DO(m, RZ(zv[j++]=y=y?ca(y):CALL2(f2,b?aa:ae,b?we:ww,fs)); ICPY(iv,b?av:wv,f); ICPY(iv+f,u,d); iv+=g; u+=d;); + u=ii; y=0; v=0; + }else{ + while(ICMP(f+(b?wv:av),u,d)){ + RZ(zv[j++]=y=y?ca(y):CALL2(f2,b?aa:ae,b?we:ww,fs)); + ICPY(iv,wv,f); ICPY(iv+f,u,d); iv+=g; u+=d; ++k; + } + RZ(zv[j++]=CALL2(f2,aa,ww,fs)); ICPY(iv,b?wv:av,g); iv+=g; u+=d; ++k; + } + if ( b&&0<=s)if(wj==wn)wv=v=0; else{v=wv; wv+=wk*wc; RE(wk=spradv(wn,wb,wf,wcr,wj,wp,&ww)); wj+=wk;} + else if(!b&&0>=s)if(aj==an)av=v=0; else{v=av; av+=ak*ac; RE(ak=spradv(an,ab,af,acr,aj,ap,&aa)); aj+=ak;} + if(b&&(!s&&!wv||v&&ICMP(v,wv,f))||!b&&(!s&&!av||v&&ICMP(v,av,f))){ + DO(m-k, RZ(zv[j++]=y=y?ca(y):CALL2(f2,b?aa:ae,b?we:ww,fs)); ICPY(iv,b?av:wv,f); ICPY(iv+f,u,d); iv+=g; u+=d;); + u=ii; y=0; k=0; + } + if ( b&&0>=s&&(!v||ICMP(v,wv,f)))if(aj==an)av=0; else{av+=ak*ac; RE(ak=spradv(an,ab,af,acr,aj,ap,&aa)); aj+=ak;} + else if(!b&&0<=s&&(!v||ICMP(v,av,f)))if(wj==wn)wv=0; else{wv+=wk*wc; RE(wk=spradv(wn,wb,wf,wcr,wj,wp,&ww)); wj+=wk;} + } + AN(z)=*AS(z)=*AS(zi)=j; AN(zi)=j*g; + EPILOG(sprz(ope(z),zi,CALL2(f2,ae,we,fs),g,g==af?as:ws)); +} /* a f"r w on sparse arrays */ + +A jtva2s(J jt,A a,A w,C id,VF ado,I cv,I t,I zt,I lr,I rr){PROLOG;A aa,ae,we,ww,y,zi,z,*zv;B*ab,b,*wb;I ac,acr,af,aj,ak,am,an, + ar,*as,at,*av,d,f,g,*ii,*iv,j,k,m,s,*u,*v,wc,wcr,wf,wj,wk,wm,wn,wr,*ws,wt,*wv;P*ap,*wp; + RZ(a&&w); + ar=AR(a); as=AS(a); acr=efr(ar,lr); af=ar-acr; + wr=AR(w); ws=AS(w); wcr=efr(wr,rr); wf=wr-wcr; + if(!af&&!wf){ado(jt,a,w); R 0;} + DO(af, ASSERT(as[i],EVNONCE);); + DO(wf, ASSERT(ws[i],EVNONCE);); + if(!ar){ado(jt,a,w); R 0;} + if(!wr){ado(jt,a,w); R 0;} + f=MIN(af,wf); g=MAX(af,wf); m=1; + if(fwf?m:1); + GA(z, BOX,j, 1,0); zv=AAV(z); + GA(zi,INT,j*g,2,0); v=AS(zi); v[0]=j; v[1]=g; iv=AV(zi); + RE(aj=ak=spradv(an,ab,af,acr,0L,ap,&aa)); + RE(wj=wk=spradv(wn,wb,wf,wcr,0L,wp,&ww)); j=s=k=0; u=ii; y=0; v=0; + if(af==wf)while(av||wv){ + if(av&&wv)DO(f, if(s=av[i]-wv[i])break;) else s=av?-1:1; + if (0==s){ado(jt,aa,ww); RZ(zv[j++]); ICPY(iv,av,f); iv+=g;} + else if(0> s){ado(jt,aa,we); RZ(zv[j++]); ICPY(iv,av,f); iv+=g;} + else if(0< s){ado(jt,ae,ww); RZ(zv[j++]); ICPY(iv,wv,f); iv+=g;} + if(0>=s){if(aj==an)av=0; else{av+=ak*ac; RE(ak=spradv(an,ab,af,acr,aj,ap,&aa)); aj+=ak;}} + if(0<=s){if(wj==wn)wv=0; else{wv+=wk*wc; RE(wk=spradv(wn,wb,wf,wcr,wj,wp,&ww)); wj+=wk;}} + }else while(av||wv){ + if(av&&wv&&f)DO(f, if(s=av[i]-wv[i])break;) else s=!f?0:av?-1:1; + if(b&&0s){ado(jt,b?ae:aa,b?ww:we); RZ(zv[j++]); ICPY(iv,b?wv:av,g); iv+=g; k=m;} + else if(s){ + DO(m, ado(jt,b?aa:ae,b?we:ww); RZ(zv[j++]=y=y?ca(y):0); ICPY(iv,b?av:wv,f); ICPY(iv+f,u,d); iv+=g; u+=d;); + u=ii; y=0; v=0; + }else{ + while(ICMP(f+(b?wv:av),u,d)){ + ado(jt,b?aa:ae,b?we:ww); RZ(zv[j++]=y=y?ca(y):0); + ICPY(iv,wv,f); ICPY(iv+f,u,d); iv+=g; u+=d; ++k; + } + ado(jt,aa,ww); RZ(zv[j++]); ICPY(iv,b?wv:av,g); iv+=g; u+=d; ++k; + } + if ( b&&0<=s)if(wj==wn)wv=v=0; else{v=wv; wv+=wk*wc; RE(wk=spradv(wn,wb,wf,wcr,wj,wp,&ww)); wj+=wk;} + else if(!b&&0>=s)if(aj==an)av=v=0; else{v=av; av+=ak*ac; RE(ak=spradv(an,ab,af,acr,aj,ap,&aa)); aj+=ak;} + if(b&&(!s&&!wv||v&&ICMP(v,wv,f))||!b&&(!s&&!av||v&&ICMP(v,av,f))){ + DO(m-k, ado(jt,b?aa:ae,b?we:ww); RZ(zv[j++]=y=y?ca(y):0); ICPY(iv,b?av:wv,f); ICPY(iv+f,u,d); iv+=g; u+=d;); + u=ii; y=0; k=0; + } + if ( b&&0>=s&&(!v||ICMP(v,wv,f)))if(aj==an)av=0; else{av+=ak*ac; RE(ak=spradv(an,ab,af,acr,aj,ap,&aa)); aj+=ak;} + else if(!b&&0<=s&&(!v||ICMP(v,av,f)))if(wj==wn)wv=0; else{wv+=wk*wc; RE(wk=spradv(wn,wb,wf,wcr,wj,wp,&ww)); wj+=wk;} + } + AN(z)=*AS(z)=*AS(zi)=j; AN(zi)=j*g; + R 0; + /* EPILOG(sprz(ope(z),zi,CALL2(f2,ae,we,fs),g,g==af?as:ws)); */ +} /* a f"r w on sparse arrays for atomic f */ diff --git a/ct.c b/ct.c new file mode 100644 --- /dev/null +++ b/ct.c @@ -0,0 +1,267 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Conjunctions: Taylor's Series */ + +#include "j.h" + + +static F1(jttayatop); + +static F1(jtcoeff){V*v; + RZ(w); + v=VAV(w); + R VTAYFINITE&v->flag ? curtail(VAV(v->f)->g) : mtv; +} /* coefficents c in {&c@(n&<.), or empty */ + +static F1(jttpoly){A z; + RZ(w); + RZ(z=atop(amp(ds(CLBRACE),over(AT(w)&CMPX?w:xco1(w),zero)),amp(tally(w),ds(CMIN)))); + VAV(z)->flag=VTAYFINITE; + R z; +} + +static F1(jtfacit){A c;V*u,*v; + RZ(c=coeff(w)); + if(AN(c))R tpoly(tymes(c,fact(AT(c)&XNUM+RAT?xco1(IX(IC(c))):IX(IC(c))))); + v=VAV(w); + if(CFORK==v->id)switch(ID(v->g)){ + case CDIV: + if(CBANG==ID(v->h))R v->f; + break; + case CSTAR: + if(CFORK==ID(v->h)&&(u=VAV(v->h),CDIV==ID(u->g)&&CBANG==ID(u->h)))R folk(v->f,v->g,u->f); + RZ(c=atop(ds(CDIV),ds(CBANG))); + if(equ(c,v->f))R v->h; + if(equ(c,v->h))R v->f; + } + R folk(ds(CBANG),ds(CSTAR),w); +} + +static A jttayamp(J jt,A w,B nf,A x,A h){A y;B ng=!nf;I j,n;V*v=VAV(h); + ASSERT(AR(x)<=(nf?v->lr:v->rr),EVRANK); + switch(v->id){ + case CPLUS: R tpoly(over(x,one)); + case CMINUS: R tpoly(nf?over(x,num[-1]):over(negate(x),one)); + case CSTAR: R tpoly(over(zero,x)); + case CDIV: ASSERT(ng,EVDOMAIN); R tpoly(over(zero,recip(x))); + case CJDOT: R tpoly(nf?over(x,a0j1):over(jdot1(x),one)); + case CPOLY: ASSERT(nf,EVDOMAIN); R tpoly(BOX&AT(x)?poly1(x):x); + case CHGEOM: ASSERT(nf,EVDOMAIN); RE(j=i0(x)); ASSERT(0<=j,EVDOMAIN); + y=IX(j); + R tpoly(divide(hgcoeff(y,h),fact(y))); + case CBANG: ASSERT(nf,EVDOMAIN); RE(j=i0(x)); ASSERT(0<=j,EVDOMAIN); + R tpoly(divide(poly1(box(iota(x))),fact(x))); + case CEXP: if(nf)R eva(x,"(^.x)&^ % !"); + RE(n=i0(x)); + R 0<=n?tpoly(over(reshape(x,zero),one)):atop(ds(CDIV),amp(h,sc(-n))); + case CFIT: ASSERT(nf&&CPOLY==ID(v->f),EVDOMAIN); + y=over(x,IX(IC(x))); + R tpoly(mdiv(df2(x,y,h),atab(CEXP,y,IX(IC(x))))); + case CCIRCLE: + switch(i0(x)){ + case 1: R eval("{&0 1 0 _1@(4&|) % !"); + case -3: R eval("{&0 1 0 _1@(4&|) % ]"); + case 2: R eval("{&1 0 _1 0@(4&|) % !"); + case 5: R eval("2&| % !"); + case -7: R eval("2&| % ]"); + case 6: R eval("2&|@>: % !"); + case -1: R eval("(2&| % ]) * ([: */ (1&+ % 2&+)@(i.@<.&.-:))\"0"); + case -5: R eval("({&0 1 0 _1@(4&|) % ]) * ([: */ (1&+ % 2&+)@(i.@<.&.-:))\"0"); + }} + ASSERT(0,EVDOMAIN); +} + +static A jttcoamp(J jt,A w,B nf,A x,A h){I j;V*v=VAV(h); + ASSERT(AR(x)<=v->mr,EVRANK); + switch(v->id){ + case CEXP: + if(nf)R amp(logar1(x),ds(CEXP)); break; + case CHGEOM: + ASSERT(nf,EVDOMAIN); RE(j=i0(x)); ASSERT(0<=j,EVDOMAIN); + R tpoly(hgcoeff(IX(j),h)); + } + R facit(tayamp(w,nf,x,h)); +} + +static F2(jttayinv){A y;I m,*v; + RZ(a&&w); + RZ(y=vip(w)); v=AV(y); + m=0; DO(AN(w), m=MAX(m,v[i]);); ++m; + RZ(y=IX(m)); if(AT(w)&XNUM+RAT)RZ(y=xco1(y)); + R rinv(ev2(apv(m,0L,-1L),df1(y,tdot(a)),"|.!.0\"0 1")); +} + +static DF1(jttayrecip){A f=VAV(self)->f; R from(w,head(tayinv(VAV(f)->g,w)));} + /* %@f t. w */ + +static DF1(jttaydiv){A c,f,ft,h,ht,y;I j,m,*u;V*v; + y=VAV(self)->f; v=VAV(y); + RZ(y=vip(w)); u=AV(y); + m=0; DO(AN(w), m=MAX(m,u[i]);); ++m; + RZ(y=IX(m)); if(AT(w)&XNUM+RAT)RZ(y=xco1(y)); + RZ(f=df1(y,ft=tdot(v->f))); + RZ(h=df1(y,ht=tdot(v->h))); + RZ(c=indexof(ne(zero,h),one)); + if(j=*AV(c)){ + ASSERT(all1(eq(zero,take(c,f))),EVDOMAIN); + RZ(y=apv(j,m,1L)); if(AT(w)&XNUM+RAT)RZ(y=xco1(y)); + RZ(f=over(drop(c,f),df1(y,ft))); + RZ(h=over(drop(c,h),df1(y,ht))); + } + R from(w,pdt(f,rinv(ev2(apv(m,0L,-1L),h,"|.!.0\"0 1")))); +} /* (f % h) t. w */ + +static DF1(jttaysqrt){A f;I m,*v; + f=VAV(self)->f; + RZ(w=vip(w)); v=AV(w); + m=0; DO(AN(w), m=MAX(m,v[i]);); ++m; + ASSERT(0,EVNONCE); + /* R from(w,df2(sc(m),df1(IX(m),tdot(VAV(f)->g)),taysqrt0)); */ +} /* %:@f t. w */ + +static F1(jttayfolk){A c,d,f,ft,g,h,ht,pp;B b;V*v=VAV(w); + h=v->h; ht=tdot(h); RZ(d=coeff(ht)); + f=v->f; if(NOUN&AT(f))R tayfolk(folk(qq(f,ainf),v->g,h)); ft=tdot(f); RZ(c=coeff(ft)); + b=AN(c)&&AN(d); g=v->g; pp=eval("[: +//. */"); + switch(ID(g)){ + case CPLUS: + case CMINUS: R b ? tpoly(df1(lamin2(c,d),slash(g))) : folk(ft,g,ht); + case CSTAR: R b ? tpoly(df2(c,d,pp)) : eva(folk(ft,pp,ht),"{ x@(i.@>:@(>./)@,)"); + case CDIV: R ADERIV(CTDOT,jttaydiv,0L,RMAX,RMAX,RMAX); + case CTILDE: g=VAV(g)->f; ASSERT(VERB&AT(f),EVDOMAIN); R tayfolk(folk(h,g,f)); + case CEXP: ASSERT(1==AN(d),EVDOMAIN); R tdot(atop(amp(g,head(d)),f)); + default: ASSERT(0,EVDOMAIN); +}} + +static F1(jttaysum){I n;V*v=VAV(w); + switch(ID(w)){ + case CLEFT: case CRIGHT: + R tpoly(eval("0 _1r2 1r2")); + case CAMP: case CAMPCO: + if(CEXP==ID(v->f)){ + RE(n=i0(v->g)); + ASSERT(0<=n,EVDOMAIN); + + }} + ASSERT(0,EVDOMAIN); +} + +static F1(jttayatop){A c,d,e,f,ft,g,gt,h;I k,m,n;V*v=VAV(w); + f=v->f; g=v->g; + switch(ID(f)){ + case CDIV: R ADERIV(CTDOT,jttayrecip,0L,RMAX,RMAX,RMAX); + case CSQRT: R ADERIV(CTDOT,jttaysqrt, 0L,RMAX,RMAX,RMAX); + case CAMP: + c=VAV(f)->f; d=VAV(f)->g; + if(CEXP==ID(c)&&INT&AT(d)&&!AR(d)){ + k=*AV(d); + if(0>k)R tayatop(atop(ds(CDIV),-1==k?g:atop(amp(c,sc(-k)),g))); + }} + if(CIOTA==ID(g)){B b;C c; + c=ID(f); ft=VAV(f)->f; gt=VAV(f)->g; + if(c==CSLASH&&CPLUS==ID(ft))R taysum(ds(CLEFT)); + b=CSLASH==ID(ft)&&(h=VAV(ft)->f,CPLUS==ID(h)); + if(b&&(c==CAMPCO||c==CATCO||(c==CAMP||c==CAT)&&1mr))R taysum(gt); + ASSERT(0,EVDOMAIN); + } + ft=tdot(f); RZ(c=coeff(ft)); m=AN(c); + gt=tdot(g); RZ(d=coeff(gt)); n=AN(d); + if(n&&all1(eq(zero,curtail(d)))){ + e=tail(d); + if(!equ(one,e))ft=folk(amp(e,ds(CEXP)),ds(CSTAR),ft); + if(2:@(>./)@,)"); +} + +static AS1(jttdot1, df1(w,tdot(fix(fs)))) +static AS1(jttco1, df1(w,tco (fix(fs)))) +static CS1(jttcap1, df1(w,tcap(fix(fs),gs))) + +static DF1(jttcoh1){R hgcoeff(w,VAV(self)->f);} + +F1(jttdot){A f,g,h;B nf,ng;C id;V*v; + RZ(w); + if(NOUN&AT(w))R vger2(CTDOT,0L,w); + if(!nameless(w))R ADERIV(CTDOT,jttdot1,0L,RMAX,RMAX,RMAX); + v=VAV(w); id=v->id; + f=v->f; nf=f&&NOUN&AT(f); + g=v->g; ng=g&&NOUN&AT(g); + h=v->h; + if(id==CAMP&&nf!=ng)R tayamp(w,nf,nf?f:g,nf?g:f); + switch(id){ + case CEXP: R eval("%@!"); + case CLEFT: + case CRIGHT: R tpoly(v2( 0L, 1L)); + case CGE: R tpoly(v2( 1L, 1L)); + case CLE: R tpoly(v2(-1L, 1L)); + case CNOT: R tpoly(v2( 1L,-1L)); + case CMINUS: R tpoly(v2( 0L,-1L)); + case CPLUSCO: R tpoly(v2( 0L, 2L)); + case CSTARCO: R tpoly(eval("0 0 1")); + case CHALVE: R tpoly(eval("0 0.5")); + case CJDOT: R tpoly(eval("0 0j1")); + case CCIRCLE: R tpoly(eval("0 1p1")); + case CFORK: R tayfolk(w); + case CHOOK: R tayfolk(folk(ds(CRIGHT),f,g)); + case CHGEOM: R folk(ds(CBANG),swap(ds(CDIV)),tco(w)); + case CUNDER: R tdot(atop(inv(g),atop(f,g))); + case CQQ: if(nf){ASSERT(!AR(f),EVRANK); R tpoly(f);} else R tdot(f); + case CEVEN: if(CMINUS==ID(g))R eva(f,"0&=@(2&|) * x t."); break; + case CODD: if(CMINUS==ID(g))R eva(f," 2&| * x t."); break; + case CTDOT: if(nf)R*(1+AAV(h)); break; + case CDDOT: R tdot(ddot(f,g)); + case CAMP: case CAMPCO: case CAT: case CATCO: + R tayatop(w); + case CPOWOP: + if(!nf&&ng&&!AR(g)){A c,d,ft,h;I m,n; + RE(n=i0(g)); + switch(SGN(n)){ + case -1: RZ(h=inv(f)); ASSERT(CPOWOP!=ID(h),EVDOMAIN); R tdot(powop(h,sc(-n))); + case 0: R tpoly(v2(0L,1L)); + case 1: + ft=tdot(f); RZ(c=d=coeff(ft)); m=AN(c); + ASSERT(m,EVDOMAIN); + RZ(h=eval("4 : '+/x*y([:+//.*/)^:(i.#x) 1'")); + DO(n-1, RZ(d=df2(c,d,h));); + R tpoly(d); + }}} + ASSERT(id==CFCONS,EVDOMAIN); + R tpoly(h); +} + +F1(jttco){A f,g;B nf,ng;C id;V*v; + RZ(w); + ASSERT(VERB&AT(w),EVDOMAIN); + if(!nameless(w))R ADERIV(CTCO,jttco1,0L,RMAX,RMAX,RMAX); + v=VAV(w); id=v->id; + f=v->f; nf=f&&NOUN&AT(f); + g=v->g; ng=g&&NOUN&AT(g); + if(id==CAMP&&nf!=ng)R tcoamp(w,nf,nf?f:g,nf?g:f); + switch(id){ + case CEXP: R eval("$&1&$"); + case CHGEOM: R ADERIV(CTCO,jttcoh1,0L,RMAX,RMAX,RMAX); + case CQQ: if(!nf)R tco(f); + } + R facit(tdot(w)); +} + +F2(jttcap){A c,p,s,t;I n; + ASSERTVN(a,w); + ASSERT(!AR(w),EVRANK); + RZ(t=vib(w)); n=*AV(t); + ASSERT(0<=n,EVDOMAIN); + if(!nameless(a))R CDERIV(CTCAP,jttcap1,0L,RMAX,RMAX,RMAX); + RZ(p=tdot(a)); + if(nf2);} +DF2(jteachr){RZ(a&&w&&self); R rank2ex(a,w,self,RMAX,-1L, VAV(self)->f2);} + +static DF1(jtunder1){DECLFG; R df1( w,atop(inv(gs),amp(fs,gs)));} +static DF2(jtunder2){DECLFG; R df2(a,w,atop(inv(gs),amp(fs,gs)));} + +static DF1(jtundco1){DECLFG; R df1( w,atop(inv(gs),ampco(fs,gs)));} +static DF2(jtundco2){DECLFG; R df2(a,w,atop(inv(gs),ampco(fs,gs)));} + + +static DF1(jtunderai1){DECLF;A x,y,z;B b;I j,n,*u,*v;UC f[256],*wv,*zv; + RZ(w); + if(b=LIT&AT(w)&&256jerr)RESETERR; + } + if(!b)R from(df1(indexof(alp,w),fs),alp); + n=AN(w); + GA(z,LIT,n,AR(w),AS(w)); zv=UAV(z); wv=UAV(w); + if(!bitwisecharamp(f,n,wv,zv))DO(n, *zv++=f[*wv++];); + R z; +} /* f&.(a.&i.) w */ + +F2(jtunder){A x;AF f1,f2;B b,b1;C c;I m,r;V*u,*v; + ASSERTVV(a,w); + c=0; f1=jtunder1; f2=jtunder2; r=mr(w); v=VAV(w); + switch(v->id){ + case COPE: f1=jteach1; f2=jteach2; break; + case CFORK: c=ID(v->h); /* fall thru */ + case CAMP: + u=VAV(a); + if(b1=CSLASH==u->id){x=u->f; u=VAV(x);} + b=CBDOT==u->id&&(x=u->f,!AR(x)&&INT&AT(x)&&(m=*AV(x),16<=m&&m<32)); + if(CIOTA==ID(v->g)&&(!c||c==CLEFT||c==CRIGHT)&&equ(alp,v->f)){ + f1=b&& b1?jtbitwiseinsertchar:jtunderai1; + f2=b&&!b1?jtbitwisechar:u->id==CMAX||u->id==CMIN?jtcharfn2:jtunder2; + }} + R CDERIV(CUNDER,f1,f2,r,r,r); +} + +F2(jtundco){ + ASSERTVV(a,w); + R CDERIV(CUNDCO,jtundco1,jtundco2,RMAX,RMAX,RMAX); +} diff --git a/cv.c b/cv.c new file mode 100644 --- /dev/null +++ b/cv.c @@ -0,0 +1,84 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Conjunctions: Variants (!.) */ + +#include "j.h" + + +static DF1(jtfitct1){DECLFG;A z;D old=jt->ct; jt->ct=*DAV(gs); z=CALL1(f1, w,fs); jt->ct=old; R z;} +static DF2(jtfitct2){DECLFG;A z;D old=jt->ct; jt->ct=*DAV(gs); z=CALL2(f2,a,w,fs); jt->ct=old; R z;} + +static F2(jtfitct){D d;V*sv; + RZ(a&&w); + ASSERT(!AR(w),EVRANK); + sv=VAV(a); + RZ(w=cvt(FL,w)); d=*DAV(w); ASSERT(0<=d&&d<5.82076609134675e-11,EVDOMAIN); + R CDERIV(CFIT,jtfitct1,jtfitct2,sv->mr,sv->lr,sv->rr); +} + +static DF1(jtfitfill1){DECLFG;A z; jt->fill=gs; z=CALL1(f1, w,fs); jt->fill=0; R z;} +static DF2(jtfitfill2){DECLFG;A z; jt->fill=gs; z=CALL2(f2,a,w,fs); jt->fill=0; R z;} + +static DF1(jtfitpp1){DECLFG;A z;C d[8],*s=3+jt->pp; + MC(d,s,8L); + sprintf(s,FMTI"g",*AV(gs)); + z=CALL1(f1,w,fs); MC(s,d,8L); + R z; +} + +static DF2(jtfitexp2){ + F2RANK(0,0,jtfitexp2,self); + ASSERT(0<=i0(w)&&!jt->jerr,EVDOMAIN); + R aslash(CSTAR,plus(a,df2(iota(w),VAV(self)->g,slash(ds(CSTAR))))); +} /* a ^!.s w */ + +static DF2(jtfitpoly2){ + F2RANK(1,0,jtfitpoly2,self); + R aslash(CPLUS,tymes(a,ascan(CSTAR,shift1(plus(w,df2(IX(IC(a)),VAV(self)->g,slash(ds(CSTAR)))))))); +} /* a p.!.s w */ + +static DF1(jtfitf1){V*sv=VAV(self); R df1( w,fit(fix(sv->f),sv->g));} +static DF2(jtfitf2){V*sv=VAV(self); R df2(a,w,fit(fix(sv->f),sv->g));} + +F2(jtfit){A f;C c;I k,l,m,r;V*sv; + ASSERTVN(a,w); + sv=VAV(a); m=sv->mr; l=sv->lr; r=sv->rr; + switch(sv->id){ + case CLE: case CLT: case CGE: case CGT: case CNE: case CEQ: + case CMATCH: case CEPS: case CIOTA: case CICO: case CNUB: case CSTAR: + case CFLOOR: case CCEIL: case CSTILE: case CPLUSDOT: case CSTARDOT: case CABASE: + case CNOT: case CXCO: case CSLDOT: case CSPARSE: case CEBAR: + R fitct(a,w); + case CEXP: + ASSERT(AT(w)&NUMERIC,EVDOMAIN); + R CDERIV(CFIT,0L,jtfitexp2, m,l,r); + case CPOLY: + ASSERT(AT(w)&NUMERIC,EVDOMAIN); + R CDERIV(CFIT,0L,jtfitpoly2,m,l,r); + case CPOWOP: + if(VERB&AT(sv->g)||!equ(num[-1],sv->g))R fitct(a,w); + f=sv->f; c=ID(f); + if(c==CPOUND){ASSERT(!AR(w),EVRANK); R CDERIV(CFIT,0,jtfitfill2,m,l,r);} + ASSERT(c==CAMP,EVDOMAIN); + f=VAV(f)->g; ASSERT(CPOUND==ID(f),EVDOMAIN); + case CPOUND: case CTAKE: case CTAIL: case CCOMMA: case CCOMDOT: case CLAMIN: case CRAZE: + ASSERT(!AR(w),EVRANK); /* fall thru */ + case CROT: case CDOLLAR: + ASSERT(1>=AR(w),EVRANK); + ASSERT(!AR(w)||!AN(w),EVLENGTH); + R CDERIV(CFIT,jtfitfill1,jtfitfill2,m,l,r); + case CTHORN: + RE(w=sc(k=i0(w))); + ASSERT(0f2,m,l,r); + case CCYCLE: + RE(k=i0(w)); ASSERT(2==k,EVDOMAIN); RZ(w=sc(k)); + R CDERIV(CFIT,jtpparity,0L,m,RMAX,RMAX); + case CTILDE: + ASSERT(NOUN&AT(sv->f),EVDOMAIN); + R CDERIV(CFIT,jtfitf1,jtfitf2,m,l,r); + default: + ASSERT(0,EVDOMAIN); +}} diff --git a/cx.c b/cx.c new file mode 100644 --- /dev/null +++ b/cx.c @@ -0,0 +1,311 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Conjunctions: Explicit Definition : and Associates */ + +/* Usage of the f,g,h fields of : defined verbs: */ +/* f character matrix of left argument to : */ +/* g character matrix of right argument to : */ +/* h 4-element vector of boxes */ +/* 0 vector of boxed tokens for f */ +/* 1 vector of triples of control information */ +/* 2 vector of boxed tokens for g */ +/* 3 vector of triples of control information */ + +#include "j.h" +#include "d.h" +#include "p.h" +#include "w.h" + +#define BASSERT(b,e) {if(!(b)){jsignal(e); i=-1; z=0; continue;}} +#define BGA(v,t,n,r,s) BZ(v=ga(t,(I)(n),(I)(r),(I*)(s))) +#define BZ(e) if(!(e)){i=-1; z=0; continue;} + +#define LINE(sv) {A x; \ + h=sv->h; hv=AAV(sv->h); hi=a&&w?HN:0; \ + line=AAV(hv[hi]); x=hv[1+hi]; n=AN(x); cw=(CW*)AV(x);} + +typedef struct{A t,x,line;C*iv,*xv;I j,k,n;} CDATA; +/* for_xyz. t do. control data */ +/* line 'for_xyz.' */ +/* t iteration array */ +/* n #t */ +/* k length of name xyz */ +/* x text xyz_index */ +/* xv ptr to text xyz_index */ +/* iv ptr to text xyz */ +/* j iteration index */ + +#define WCD (sizeof(CDATA)/sizeof(I)) + +typedef struct{I d,t,e;} TD; +#define WTD (sizeof(TD)/sizeof(I)) +#define NTD 17 /* maximum nesting for try/catch */ + + +static B jtforinit(J jt,CDATA*cv,A t){A x;C*s,*v;I k; + ASSERT(t,EVCTRL); + cv->t=ra(t); /* iteration array */ + cv->n=IC(t); /* # of items in t */ + cv->j=-1; /* iteration index */ + cv->x=0; + cv->k=k=AN(cv->line)-5; /* length of item name */ + if(0n){ /* for_xyz. */ + s=4+CAV(cv->line); RZ(cv->x=x=ra(str(6+k,s))); + cv->xv=v=CAV(x); MC(k+v,"_index",6L); /* index name */ + cv->iv=s; /* item name */ + } + R 1; +} /* for. do. end. initializations */ + +static B jtunstackcv(J jt,CDATA*cv){ + if(cv->x){ex(link(cv->x,str(cv->k,cv->iv))); fa(cv->x);} + fa(cv->t); + memset(cv,C0,WCD*SZI); + R 1; +} + +static void jttryinit(J jt,TD*v,I i,CW*cw){I j=i,t=0; + v->d=v->t=0; + while(t!=CEND){ + j=(j+cw)->go; + switch(t=(j+cw)->type){ + case CCATCHD: v->d=j; break; + case CCATCHT: v->t=j; break; + case CEND: v->e=j; break; +}}} /* processing on hitting try. */ + +static DF2(jtxdefn){PROLOG;A cd,cl,cn,h,*hv,*line,loc=jt->local,t,td,u,v,z;B b,lk,named,ox=jt->xdefn;CDATA*cv; + CW*ci,*cw;DC d=0;I hi,i=0,j,m,n,od=jt->db,old,r=0,st,tdi=0;TD*tdv;V*sv;X y; + RE(0); + z=mtm; cd=t=u=v=0; sv=VAV(self); st=AT(self); + lk=jt->glock||VLOCK&sv->flag; named=VNAMED&sv->flag?1:0; cn=jt->curname; cl=jt->curlocn; + d=named&&jt->db&&DCCALL==jt->sitop->dctype?jt->sitop:0; /* stack entry for dbunquote for this fn */ + if(VXOP&sv->flag){u=sv->f; v=sv->h; sv=VAV(sv->g);} + if(st&ADV+CONJ){u=a; v=w;} + LINE(sv); ASSERT(n,EVDOMAIN); + RZ(jt->local=stcreate(2,1L,0L,0L)); + if(sv->flag&VTRY1+VTRY2){GA(td,INT,NTD*WTD,2,0); *AS(td)=NTD; *(1+AS(td))=WTD; tdv=(TD*)AV(td);} + /* do not use error exit after this point; use BASSERT, BGA, BZ */ + FDEPINC(1); jt->xdefn=1; + IS(xnam,a); if(u){IS(unam,u); if(NOUN&AT(u))IS(mnam,u);} + IS(ynam,w); if(v){IS(vnam,v); if(NOUN&AT(v))IS(nnam,v);} + if(jt->dotnames){ + IS(xdot,a); if(u){IS(udot,u); if(NOUN&AT(u))IS(mdot,u);} + IS(ydot,w); if(v){IS(vdot,v); if(NOUN&AT(v))IS(ndot,v);} + } + if(jt->db&&jt->sitop&&DCCALL==jt->sitop->dctype&&self==jt->sitop->dcf){ + jt->sitop->dcloc=jt->local; jt->sitop->dcc=hv[1+hi]; jt->sitop->dci=(I)&i; + } + old=jt->tbase+jt->ttop; + while(0<=i&&ipmctr&&C1==jt->pmrec&&named)pmrecord(cn,cl,i,a?VAL2:VAL1); + if(jt->redefined&&jt->sitop&&jt->redefined==jt->sitop->dcn&&DCCALL==jt->sitop->dctype&&self!=jt->sitop->dcf){ + self=jt->sitop->dcf; sv=VAV(self); LINE(sv); jt->sitop->dcc=hv[1+hi]; + jt->redefined=0; + if(i>=n)break; + } + ci=i+cw; + switch(ci->type){ + case CTRY: + BASSERT(tdidb)jt->db=(tdv+tdi)->d?jt->dbuser:DBTRY; + ++tdi; ++i; + break; + case CCATCH: case CCATCHD: case CCATCHT: + if(tdi){--tdi; i=1+(tdv+tdi)->e; jt->db=od;}else i=ci->go; break; + case CTHROW: + BASSERT(0,EWTHROW); + case CBBLOCK: + tpop(old); z=parsex(vec(BOX,ci->n,line+ci->i),lk,ci,d); + if(z||DB1==jt->db||DBERRCAP==jt->db||!jt->jerr)++i; + else if(EWTHROW==jt->jerr){if(tdi&&(j=(tdv+tdi-1)->t)){i=1+j; RESETERR;}else BASSERT(0,EWTHROW);} + else{i=ci->go; if(idb=od;}}} + break; + case CASSERT: + if(!jt->assert){++i; break;} + case CTBLOCK: + gc(z,old); t=parsex(vec(BOX,ci->n,line+ci->i),lk,ci,d); + if(t||DB1==jt->db||DBERRCAP==jt->db||!jt->jerr)++i; + else if(EWTHROW==jt->jerr){if(tdi&&(j=(tdv+tdi-1)->t)){i=1+j; RESETERR;}else BASSERT(0,EWTHROW);} + else{i=ci->go; if(idb=od;}}} + break; + case CFOR: + case CSELECT: + if(!r) + if(cd){m=AN(cd)/WCD; BZ(cd=ext(1,cd)); cv=(CDATA*)AV(cd)+m-1; r=AN(cd)/WCD-m;} + else {r=9; BGA(cd,INT,r*WCD,1,0); cv=(CDATA*)AV(cd)-1; ra(cd);} + ++cv; --r; + cv->t=cv->x=0; cv->line=line[ci->i]; ++i; + break; + case CDOF: + if(!cv->t){BZ(forinit(cv,t)); t=0;} + ++cv->j; + if(cv->jn){ + if(cv->x){A x; + symbis(nfs(6+cv->k,cv->xv),x=sc(cv->j), jt->local); + symbis(nfs( cv->k,cv->iv),from(x,cv->t),jt->local); + } + ++i; continue; + } + case CBREAKF: + case CENDSEL: + rat(z); unstackcv(cv); --cv; ++r; + i=ci->go; + break; + case CRETURN: + if(cd){rat(z); DO(AN(cd)/WCD-r, unstackcv(cv); --cv; ++r;);} + i=ci->go; + break; + case CCASE: + case CFCASE: + if(!cv->t){BASSERT(t&&NOUN&AT(t),EVCTRL); BZ(cv->t=ra(boxopen(t))); t=0;} + i=ci->go; + break; + case CDOSEL: + BASSERT(!t||NOUN&AT(t),EVCTRL); + i=t&&all0(eps(cv->t,boxopen(t)))?ci->go:1+i; + t=0; + break; + case CDO: + ++i; b=1; + if(t){ + if(SPARSE&AT(t))BZ(t=denseit(t)); + BASSERT(NOUN&AT(t),EVCTRL); + switch(AN(t)?AT(t):0){ + case RAT: + case XNUM: y=*XAV(t); b=*AV(y)||1go; + }} + FDEPDEC(1); + z=jt->jerr?0:z?ra(z):mtm; + fa(cd); + symfreeh(jt->local,0L); jt->local=loc; jt->asgn=0; jt->xdefn=ox; + tpop(_ttop); + if(z)ASSERT(st&ADV+CONJ||AT(z)&NOUN,EVSYNTAX); + tpush(z); + R z; +} + + +static DF1(xv1){R df1( w,VAV(self)->f);} +static DF2(xv2){R df2(a,w,VAV(self)->g);} + +static DF1(xn1 ){R xdefn(0L,w, self);} +static DF1(xadv){R xdefn(w, 0L,self);} + + +static F1(jtxopcall){R jt->db&&DCCALL==jt->sitop->dctype?jt->sitop->dca:mark;} + +static DF1(xop1){A ff,x; + RZ(ff=fdef(CCOLON,VERB, xn1,jtxdefn, w,self,0L, VXOP|VAV(self)->flag, RMAX,RMAX,RMAX)); + RZ(x=xopcall(one)); + R x==mark?ff:namerefop(x,ff); +} + +static DF2(xop2){A ff,x; + RZ(ff=fdef(CCOLON,VERB, xn1,jtxdefn, a,self,w, VXOP|VAV(self)->flag, RMAX,RMAX,RMAX)); + RZ(x=xopcall(one)); + R x==mark?ff:namerefop(x,ff); +} + + +static B jtxop(J jt,A h){A p,x,y;B b,*pv;I*xv; + GA(x,INT,jt->dotnames?12:6,1,0); xv=AV(x); + xv[0]=(I)mnam; xv[1]=(I)nnam; xv[2]=(I)unam; xv[3]=(I)vnam; xv[ 4]=(I)xnam; xv[ 5]=(I)ynam; + if(jt->dotnames){xv[6]=(I)mdot; xv[7]=(I)ndot; xv[8]=(I)udot; xv[9]=(I)vdot; xv[10]=(I)xdot; xv[11]=(I)ydot;} + RZ(y=raze(from(v2(0L,HN),h))); AT(y)=INT; + RZ(p=eps(x,y)); pv=BAV(p); + b=(pv[0]||pv[1]||pv[2]||pv[3])&&(pv[4]||pv[5]); + if(!b&&jt->dotnames)b=(pv[6]||pv[7]||pv[8]||pv[9])&&(pv[10]||pv[11]); + R b; +} /* whether h denotes an explicit derived function */ + +static F1(jtcolon0){A l,z;C*p,*q,*s;I m,n; + n=0; RZ(z=exta(LIT,1L,1L,300L)); s=CAV(z); + while(1){ + RE(l=jgets("\001")); + if(!l)break; + m=AN(l); p=q=CAV(l); + if(m){while(' '==*p)++p; if(')'==*p){while(' '==*++p); if(p>=m+q)break;}} + while(AN(z)<=n+m){RZ(z=ext(0,z)); s=CAV(z);} + MC(s+n,q,m); n+=m; *(s+n)=CLF; ++n; + } + R str(n,s); +} /* enter nl terminated lines; ) on a line by itself to exit */ + +static F1(jtlineit){ + R 1=AR(w),EVRANK); + RZ(w=lineit(w)); + x=p=r=CAV(w); /* p: monad start; r: dyad start */ + q=s=p+AN(w); /* q: monad end; s: dyad end */ + while(x=AR(w),EVRANK); + wv=AAV(w); wd=(I)w*ARELATIVE(w); + GA(y,BOX,AN(w),AR(w),AS(w)); yv=AAV(y); + DO(AN(w), RZ(yv[i]=vs(WVR(i)));); + RZ(t=indexof(y,link(chr[':'],str(1L,":")))); v=AV(t); j=MIN(*v,*(1+v)); + *m=take(sc(j ),y); + *d=drop(sc(j+1),y); + R 1; +} /* boxed sentences into monad/dyad */ + +F2(jtcolon){A d,h,*hv,m;B b;C*s;I flag=0,n,p; + RZ(a&&w); + if(VERB&AT(a)&&VERB&AT(w)){V*v; + v=VAV(a); if(CCOLON==v->id&&VERB&AT(v->f)&&VERB&AT(v->g))a=v->f; + v=VAV(w); if(CCOLON==v->id&&VERB&AT(v->f)&&VERB&AT(v->g))w=v->g; + R fdef(CCOLON,VERB,xv1,xv2,a,w,0L,0L,mr(a),lr(w),rr(w)); + } + RE(n=i0(a)); + if(equ(w,zero)){RZ(w=colon0(mark)); if(!n)R w;} + if(C2T&AT(w))RZ(w=cvt(LIT,w)); + if(10retcomm?m:mtv; + RE(b=preparse(d,hv+HN,hv+HN+1)); if(b)flag|=VTRY2; hv[2+HN]=jt->retcomm?d:mtv; + } + if(!n)R ca(w); + if(2>=n){ + RE(b=xop(h)); + if(b)flag|=VXOPR; + else if(2==n&&AN(m)&&!AN(d)){A*u=hv,*v=hv+HN,x; DO(HN, x=*u; *u++=*v; *v++=x;);} + } + flag|=VFIX; + switch(n){ + case 1: R fdef(CCOLON, ADV, b?xop1:xadv,0L, num[n],0L,h, flag, RMAX,RMAX,RMAX); + case 2: R fdef(CCOLON, CONJ, 0L,b?xop2:jtxdefn, num[n],0L,h, flag, RMAX,RMAX,RMAX); + case 3: R fdef(CCOLON, VERB, xn1,jtxdefn, num[n],0L,h, flag, RMAX,RMAX,RMAX); + case 4: R fdef(CCOLON, VERB, xn1,jtxdefn, num[n],0L,h, flag, RMAX,RMAX,RMAX); + case 13: R vtrans(w); + default: ASSERT(0,EVDOMAIN); +}} diff --git a/d.c b/d.c new file mode 100644 --- /dev/null +++ b/d.c @@ -0,0 +1,232 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Debug: Error Signalling and Display */ + +#ifdef _WIN32 +#include +#include +#endif + +#include "j.h" +#include "d.h" + + +static void jtep(J jt,I n,C*s){I m; + m=NETX-jt->etxn; m=MIN(n,m); + if(0etx+jt->etxn,s,m); jt->etxn+=m;} +} + +static void jteputs(J jt,C*s){ep((I)strlen(s),s);} + +static void jteputc(J jt,C c){ep(1L,&c);} + +static void jteputl(J jt,A w){ep(AN(w),CAV(w)); eputc(CLF);} + +static void jteputv(J jt,A w){I m=NETX-jt->etxn; jt->etxn+=thv(w,MIN(m,200),jt->etx+jt->etxn);} + /* numeric vector w */ + +static void jteputq(J jt,A w){C q=CQUOTE,*s; + if(equ(alp,w))eputs(" a."+!jt->nflag); + else{ + eputc(q); + s=CAV(w); DO(AN(w), eputc(s[i]); if(q==s[i])eputc(q);); + eputc(q); +}} /* string w, possibly with quotes */ + +static void jtefmt(J jt,C*s,I i){ + if(15etxn){C*v=jt->etx+jt->etxn; sprintf(v,s,i); jt->etxn+=strlen(v);} +} + +void jtshowerr(J jt){C b[1+2*NETX],*p,*q,*r; + if(jt->etxn&&jt->tostdout){ + p=b; q=jt->etx; r=q+jt->etxn; + while(qoutseq); p+=strlen(jt->outseq); ++q;}else *p++=*q++;} + *p=0; + jsto(jt,MTYOER,b); + } + jt->etxn=0; +} + +static void jtdspell(J jt,C id,A w){C c,s[5]; + if(id==CFCONS){if(jt->nflag)eputc(' '); eputv(VAV(w)->h); eputc(':');} + else{ + s[0]=' '; s[4]=0; + spellit(id,1+s); + c=s[1]; + eputs(s+!(c==CESC1||c==CESC2||jt->nflag&&CA==ctype[c])); +}} + +static void jtdisp(J jt,A w){B b=1&&AT(w)&NAME+NUMERIC; + if(b&&jt->nflag)eputc(' '); + switch(AT(w)){ + case B01: + case INT: + case FL: + case CMPX: + case XNUM: + case RAT: eputv(w); break; + case BOX: eputs(" a:"+!jt->nflag); break; + case NAME: ep(AN(w),NAV(w)->s); break; + case LIT: eputq(w); break; + case LPAR: eputc('('); break; + case RPAR: eputc(')'); break; + case ASGN: dspell(*CAV(w),w); break; + case MARK: break; + default: dspell(VAV(w)->id,w); + } + jt->nflag=b; +} + +static void jtseeparse(J jt,DC d){A*v,y;I m; + y=d->dcy; v=AAV(y); /* list of tokens */ + m=d->dci-1; /* index of active token when error found */ + jt->nflag=0; + DO(AN(y), if(i==m)eputs(" "); disp(v[i]);); +} /* display error line */ + +F1(jtunparse){A*v,z; + RZ(w); + jt->etxn=jt->nflag=0; + v=AAV(w); DO(AN(w), disp(v[i]);); z=str(jt->etxn,jt->etx); + jt->etxn=0; + R z; +} + +static void jtseecall(J jt,DC d){A a; + if(a=d->dca)ep(AN(a),NAV(a)->s); + efmt(d->dcx&&d->dcy?"[:"FMTI"]":"["FMTI"]",lnumsi(d)); +} /* display function line */ + +static void jtdhead(J jt,C k,DC d){static C s[]=" "; + *s=d&&d->dcsusp?'*':'|'; + ep(k+1L,s); +} /* preface stack display line */ + +void jtdebdisp(J jt,DC d){A*x,y;I e,t; + e=d->dcj; + t=d->dctype; + if(e&&!jt->etxn&&(t==DCPARSE||t==DCCALL)){x=e+AAV(jt->evm); dhead(0,0L); eputl(*x);} + switch(t){ + case DCPARSE: dhead(3,d); seeparse(d); if(NETX==jt->etxn)--jt->etxn; eputc(CLF); break; + case DCCALL: dhead(0,d); seecall(d); eputc(CLF); break; + case DCSCRIPT: dhead(0,d); efmt("[-"FMTI"] ", d->dcn-1); + if(0<=d->dcm){y=*(d->dcm+AAV(jt->slist)); ep(AN(y),CAV(y));} + eputc(CLF); +}} + +static B jtdebsi1(J jt,DC d){I t; + RZ(d); + t=d->dctype; + debdisp(d); + d=d->dclnk; + RZ(d&&t==DCPARSE); + t=d->dctype; + RZ(t==DCSCRIPT||t==DCCALL&&d->dcloc); + debdisp(d); + R 1; +} + +F1(jtdbstack){DC d=jt->sitop; + ASSERTMTV(w); + if(d){if(DCCALL!=d->dctype)d=d->dclnk; while(d){debdisp(d); d=d->dclnk;}} + R mtm; +} /* 13!:1 display SI stack */ + +F1(jtdbstackz){A y; + RE(dbstack(w)); + RZ(y=str(jt->etxn,jt->etx)); + jt->etxn=0; + R df1(y,cut(ds(CLEFT),num[-2])); +} /* 13!:18 SI stack as result */ + + +static void jtjsigstr(J jt,I e,I n,C*s){ + if(jt->jerr)R; + jt->jerr=(C)e; jt->jerr1=e; jt->etxn=0; + dhead(0,0L); + if(jt->db&&!spc()){eputs("ws full (can not suspend)"); eputc(CLF); jt->db=0;} + ep(n,s); + if(!jt->glock&&jt->curname){eputs(": "); ep(AN(jt->curname),NAV(jt->curname)->s); jt->curname=0;} + eputc(CLF); + if(n&&!jt->glock)debsi1(jt->sitop); + jt->etxn1=jt->etxn; +} /* signal error e with error text s of length n */ + +static void jtjsig(J jt,I e,A x){jsigstr(e,AN(x),CAV(x));} + /* signal error e with error text x */ + +void jtjsigd(J jt,C*s){C buf[100],*d="domain error: ";I m,n,p; + m=strlen(d); MC(buf,d,m); + n=strlen(s); p=MIN(n,100-m); MC(buf+m,s,p); + jsigstr(EVDOMAIN,m+p,buf); +} + +void jtjsignal(J jt,I e){A x; + if(EVATTN==e||EVBREAK==e||e==EVINPRUPT) *jt->adbreak=0; + x=0evm)):mtv; jsigstr(e,AN(x),CAV(x)); +} + +void jtjsignal3(J jt,I e,A w,I j){ + if(jt->jerr)R; + jt->jerr=(C)e; jt->jerr1=e; jt->etxn=0; + dhead(0,0L); + if(jt->db&&!spc()){eputs("ws full (can not suspend)"); eputc(CLF); jt->db=0;} + eputl(*(jt->jerr+AAV(jt->evm))); + if(!jt->glock){ + if(e==EVCTRL){dhead(3,0L); efmt("["FMTI"]",j); eputl(w);} + else{ + dhead(3,0L); eputl(w); + dhead(3,0L); DO(j, eputc(' ');); eputc('^'); eputc(CLF); + } + debsi1(jt->sitop); + } + jt->etxn1=jt->etxn; +} /* signal error e on line w with caret at j */ + +static F2(jtdbsig){I e; + RE(0); + if(!AN(w))R mtm; + RZ(w=vi(w)); e=*AV(w); + ASSERT(1<=e,EVDOMAIN); + ASSERT(e<=255,EVLIMIT); + if(a||e>NEVM){if(!a)a=mtv; RZ(a=vs(a)); jsig(e,a);} else jsignal(e); + R 0; +} + +F1(jtdbsig1){R dbsig(0L,w);} /* 13!:8 signal error */ +F2(jtdbsig2){R dbsig(a, w);} + + +F1(jtdberr){ASSERTMTV(w); R sc(jt->jerr1);} /* 13!:11 last error number */ +F1(jtdbetx){ASSERTMTV(w); R str(jt->etxn1,jt->etx);} /* 13!:12 last error text */ + + +A jtjerrno(J jt){ +#if !SY_WINCE + switch(errno){ + case EMFILE: + case ENFILE: jsignal(EVLIMIT ); R 0; + case ENOENT: jsignal(EVFNAME ); R 0; + case EBADF: jsignal(EVFNUM ); R 0; + case EACCES: jsignal(EVFACCESS); R 0; +#else /* WINCE: */ + switch(GetLastError()){ + case ERROR_DISK_FULL: + case ERROR_FILENAME_EXCED_RANGE: + case ERROR_NO_MORE_FILES: + case ERROR_NOT_ENOUGH_MEMORY: + case ERROR_NOT_ENOUGH_QUOTA: + case ERROR_TOO_MANY_OPEN_FILES: jsignal(EVLIMIT ); R 0; + case ERROR_BAD_PATHNAME: + case ERROR_INVALID_NAME: jsignal(EVDOMAIN ); R 0; + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + case ERROR_PATH_NOT_FOUND: + case ERROR_FILE_NOT_FOUND: jsignal(EVFNAME ); R 0; + case ERROR_ACCESS_DENIED: + case ERROR_WRITE_PROTECT: + case ERROR_SHARING_VIOLATION: jsignal(EVFACCESS); R 0; +#endif + default: jsignal(EVFACE); R 0; +}} /* see / */ diff --git a/d.h b/d.h new file mode 100644 --- /dev/null +++ b/d.h @@ -0,0 +1,39 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Debug */ + + +/* jt->db and jt->dbuser values; 0 means no debug */ + +#define DB1 1 /* full debug */ +#define DBERRCAP 2 /* stack error info capture */ +#define DBTRY 3 /* full debug & try/catch in effect (db only) */ + + +/* jt->dbsusact values: */ + +#define SUSCONT 0 /* continue current suspension */ +#define SUSCLEAR 1 /* clear stack */ +#define SUSRUN 2 /* run again */ +#define SUSRET 3 /* return result */ +#define SUSJUMP 4 /* jump to specified line */ +#define SUSNEXT 5 /* run next line */ +#define SUSSS 6 /* single step mode */ + + +/* si->dcss values; 0 means not single step */ + +#define SSCUTBACK 19 /* cut back one step level */ +#define SSSTEPOVER 20 /* run curr line; stop at next line in curr fn */ +#define SSSTEPINTO 21 /* run curr line; stop at next line */ +#define SSSTEPOUT 22 /* run curr fn to end; stop at next line */ +#define SSSTEPOVERs 30 +#define SSSTEPINTOs 31 + + +extern B jtdbstop(J,DC,I); +extern DC jtssnext(J,DC,C); +extern I lnumcw(I,A); +extern I lnumsi(DC); + diff --git a/dc.c b/dc.c new file mode 100644 --- /dev/null +++ b/dc.c @@ -0,0 +1,43 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Debug: Function Call Information */ + +#include "j.h" +#include "d.h" + + +static F1(jtdfrep){RZ(w); R NOUN&AT(w)?w:lrep(w);} + +static SYMWALK(jtdloc,A,BOX,5,2,1,{RZ(*zv++=sfn(0,d->name)); RZ(*zv++=dfrep(d->val));}) + +static B jtdrow(J jt,DC si,DC s0,A*zv){A fs,q,*qv,y;C c; + fs=si->dcf; + GA(q,BOX,si->dcx&&si->dcy?2:1,1,0); qv=AAV(q); + if(si->dcx)*qv++=dfrep(si->dcx); + if(si->dcy)*qv++=dfrep(si->dcy); + *zv++=sfn(0,si->dca); /* 0 name */ + *zv++=sc(si->dcj); /* 1 error number */ + *zv++=sc(lnumsi(si)); /* 2 line number */ + *zv++=num[ADV&AT(fs)?1:CONJ&AT(fs)?2:3]; /* 3 name class */ + *zv++=lrep(fs); /* 4 linear rep. */ + *zv++=0; /* 5 script name */ + *zv++=q; /* 6 argument list */ + if(si->dcloc){RZ(y=dloc(si->dcloc)); RZ(*zv++=grade2(y,ope(irs1(y,0L,1L,jthead))));} + else RZ(*zv++=iota(v2(0L,2L))); /* 7 locals */ + c=si->dcsusp||s0&&DCPARSE==s0->dctype&&s0->dcsusp?'*':' '; + RZ(*zv++=scc(c)); /* 8 * if begins a suspension */ + R 1; +} /* construct one row of function call matrix */ + +F1(jtdbcall){A y,*yv,z,*zv;DC si,s0=0;I c=9,m=0,*s; + ASSERTMTV(w); + si=jt->sitop; while(si){if(DCCALL==si->dctype)++m; si=si->dclnk;} + GA(z,BOX,m*c,2,0); s=AS(z); s[0]=m; s[1]=c; + si=jt->sitop; zv=AAV(z); + while(si){if(DCCALL==si->dctype){RZ(drow(si,s0,zv)); zv+=c;} s0=si; si=si->dclnk;} + RZ(y=from(scind(irs1(z,0L,1L,jthead)),over(snl(mtv),ace))); + yv=AAV(y); zv=5+AAV(z); + DO(m, *zv=*yv++; zv+=c;); + R z; +} /* 13!:13 function call matrix */ diff --git a/defs/hostdefs.c b/defs/hostdefs.c new file mode 100644 --- /dev/null +++ b/defs/hostdefs.c @@ -0,0 +1,159 @@ +#include +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#else + +#include +#include "winregex\rxposix.h" +#endif +#include +#include +#include +#define offset(r,f) (((char*)&((r*)0)->f)-((char*)((r*)0))) +main(){ + printf ("NB. do not edit -- created by sym2ijs\n\n"); + printf ("cocurrent <'jdefs'\n\n"); +#ifndef _WIN32 + printf ("F_OK=: %d\n",(int)F_OK); + printf ("R_OK=: %d\n",(int)R_OK); + printf ("W_OK=: %d\n",(int)W_OK); + printf ("X_OK=: %d\n",(int)X_OK); + printf ("STDIN_FILENO=: %d\n",(int)STDIN_FILENO); + printf ("STDOUT_FILENO=: %d\n",(int)STDOUT_FILENO); + printf ("STDERR_FILENO=: %d\n",(int)STDERR_FILENO); +#else + puts ("F_OK=:0"); + puts ("R_OK=:4"); + puts ("W_OK=:2"); + puts ("X_OK=:1"); +#endif + printf ("SEEK_CUR=: %d\n",(int)SEEK_CUR); + printf ("SEEK_END=: %d\n",(int)SEEK_END); + printf ("SEEK_SET=: %d\n",(int)SEEK_SET); + puts(""); + printf ("O_APPEND=: %d\n",(int)O_APPEND); + printf ("O_CREAT=: %d\n",(int)O_CREAT); + printf ("O_EXCL=: %d\n",(int)O_EXCL); + printf ("O_RDONLY=: %d\n",(int)O_RDONLY); + printf ("O_RDWR=: %d\n",(int)O_RDWR); + printf ("O_TRUNC=: %d\n",(int)O_TRUNC); + printf ("O_WRONLY=: %d\n",(int)O_WRONLY); + puts(""); +#ifndef _WIN32 + printf ("O_ACCMODE=: %d\n",(int)O_ACCMODE); + printf ("O_NOCTTY=: %d\n",(int)O_NOCTTY); + printf ("O_NONBLOCK=: %d\n",(int)O_NONBLOCK); + printf ("FD_CLOEXEC=: %d\n",(int)FD_CLOEXEC); + printf ("F_DUPFD=: %d\n",(int)F_DUPFD); + printf ("F_GETFD=: %d\n",(int)F_GETFD); + printf ("F_SETFD=: %d\n",(int)F_SETFD); + printf ("F_GETFL=: %d\n",(int)F_GETFL); + printf ("F_SETFL=: %d\n",(int)F_SETFL); + printf ("F_SETLK=: %d\n",(int)F_SETLK); + printf ("F_SETLKW=: %d\n",(int)F_SETLKW); + printf ("F_GETLK=: %d\n",(int)F_GETLK); + printf ("F_UNLCK=: %d\n",(int)F_UNLCK); + printf ("F_WRLCK=: %d\n",(int)F_WRLCK); + printf ("flock_sz=: %d\n",(int)sizeof (struct flock)); + printf ("l_len_off=: %d\n",(int)offset(struct flock,l_len)); + printf ("l_len_sz=: %d\n",(int)sizeof(((struct flock*)0)->l_len)); + printf ("l_pid_off=: %d\n",(int)offset(struct flock,l_pid)); + printf ("l_pid_sz=: %d\n",(int)sizeof(((struct flock*)0)->l_pid)); + printf ("l_start_off=: %d\n",(int)offset(struct flock,l_start)); + printf ("l_start_sz=: %d\n",(int)sizeof(((struct flock*)0)->l_start)); + printf ("l_type_off=: %d\n",(int)offset(struct flock,l_type)); + printf ("l_type_sz=: %d\n",(int)sizeof(((struct flock*)0)->l_type)); + printf ("l_whence_off=: %d\n",(int)offset(struct flock,l_whence)); + printf ("l_whence_sz=: %d\n",(int)sizeof(((struct flock*)0)->l_whence)); + puts(""); + printf ("PROT_READ=: %d\n",(int)PROT_READ); + printf ("PROT_WRITE=: %d\n",(int)PROT_WRITE); + printf ("PROT_EXEC=: %d\n",(int)PROT_EXEC); + printf ("PROT_NONE=: %d\n",(int)PROT_NONE); + printf ("MAP_SHARED=: %d\n",(int)MAP_SHARED); + printf ("MAP_PRIVATE=: %d\n",(int)MAP_PRIVATE); + printf ("MAP_FIXED=: %d\n",(int)MAP_FIXED); +#endif + puts(""); + printf ("REG_EXTENDED=: %d\n",(int)REG_EXTENDED); + printf ("REG_ICASE=: %d\n",(int)REG_ICASE); + printf ("REG_NOSUB=: %d\n",(int)REG_NOSUB); + printf ("REG_NEWLINE=: %d\n",(int)REG_NEWLINE); + puts(""); + printf ("regex_t_sz=: %d\n",(int)sizeof (regex_t)); + printf ("re_nsub_off=: %d\n",(int)offset(regex_t,re_nsub)); + printf ("re_nsub_sz=: %d\n",(int)sizeof(((regex_t*)0)->re_nsub)); + printf ("regmatch_t_sz=: %d\n",(int)sizeof (regmatch_t)); + printf ("rm_so_off=: %d\n",(int)offset(regmatch_t,rm_so)); + printf ("rm_so_sz=: %d\n",(int)sizeof(((regmatch_t*)0)->rm_so)); + printf ("rm_eo_off=: %d\n",(int)offset(regmatch_t,rm_eo)); + printf ("rm_eo_sz=: %d\n",(int)sizeof(((regmatch_t*)0)->rm_eo)); + puts(""); +#ifdef linux +#define fds_bits __fds_bits +#endif + puts(""); +#ifndef _WIN32 + printf ("fd_set_sz=: %d\n",(int)sizeof (fd_set)); + printf ("fds_bits_off=: %d\n",(int)offset(fd_set,fds_bits)); + printf ("fds_bits_sz=: %d\n",(int)sizeof(((fd_set*)0)->fds_bits)); +#endif + printf ("FD_SETSIZE=: %d\n",(int)FD_SETSIZE); + printf ("timeval_sz=: %d\n",(int)sizeof (struct timeval)); + printf ("tv_sec_off=: %d\n",(int)offset(struct timeval,tv_sec)); + printf ("tv_sec_sz=: %d\n",(int)sizeof(((struct timeval*)0)->tv_sec)); + printf ("tv_usec_off=: %d\n",(int)offset(struct timeval,tv_usec)); + printf ("tv_usec_sz=: %d\n",(int)sizeof(((struct timeval*)0)->tv_usec)); + puts(""); + printf ("E2BIG=: %d\n",(int)E2BIG); + printf ("EFAULT=: %d\n",(int)EFAULT); + printf ("ENFILE=: %d\n",(int)ENFILE); + printf ("ENOTTY=: %d\n",(int)ENOTTY); + printf ("EACCES=: %d\n",(int)EACCES); + printf ("EFBIG=: %d\n",(int)EFBIG); + printf ("ENODEV=: %d\n",(int)ENODEV); + printf ("ENXIO=: %d\n",(int)ENXIO); + printf ("EAGAIN=: %d\n",(int)EAGAIN); + printf ("ENOENT=: %d\n",(int)ENOENT); + printf ("EPERM=: %d\n",(int)EPERM); + printf ("EBADF=: %d\n",(int)EBADF); + printf ("EINTR=: %d\n",(int)EINTR); + printf ("ENOEXEC=: %d\n",(int)ENOEXEC); + printf ("EPIPE=: %d\n",(int)EPIPE); + printf ("EINVAL=: %d\n",(int)EINVAL); + printf ("ENOLCK=: %d\n",(int)ENOLCK); + printf ("ERANGE=: %d\n",(int)ERANGE); + printf ("EBUSY=: %d\n",(int)EBUSY); + printf ("EIO=: %d\n",(int)EIO); + printf ("ENOMEM=: %d\n",(int)ENOMEM); + printf ("EROFS=: %d\n",(int)EROFS); + printf ("EISDIR=: %d\n",(int)EISDIR); + printf ("ENOSPC=: %d\n",(int)ENOSPC); + printf ("ESPIPE=: %d\n",(int)ESPIPE); + printf ("ECHILD=: %d\n",(int)ECHILD); + printf ("EMFILE=: %d\n",(int)EMFILE); + printf ("ENOSYS=: %d\n",(int)ENOSYS); + printf ("ESRCH=: %d\n",(int)ESRCH); + printf ("EDEADLK=: %d\n",(int)EDEADLK); + printf ("EMLINK=: %d\n",(int)EMLINK); + printf ("ENOTDIR=: %d\n",(int)ENOTDIR); + printf ("EDOM=: %d\n",(int)EDOM); + printf ("ENOTEMPTY=: %d\n",(int)ENOTEMPTY); + printf ("EXDEV=: %d\n",(int)EXDEV); + printf ("EEXIST=: %d\n",(int)EEXIST); + printf ("ENAMETOOLONG=: %d\n",(int)ENAMETOOLONG); + puts(""); +#ifndef _WIN32 + printf ("EINPROGRESS=: %d\n",(int)EINPROGRESS); + printf ("ECANCELED=: %d\n",(int)ECANCELED); + printf ("ETIMEDOUT=: %d\n",(int)ETIMEDOUT); + printf ("EMSGSIZE=: %d\n",(int)EMSGSIZE); + printf ("ENOTSUP=: %d\n",(int)ENOTSUP); +#endif + exit (0); +} diff --git a/defs/hostdefs.sym b/defs/hostdefs.sym new file mode 100644 --- /dev/null +++ b/defs/hostdefs.sym @@ -0,0 +1,93 @@ + +#ifndef _WIN32 + + + + + + +#else + + +#include "winregex\rxposix.h" +#endif + + + + + +; unistd.h: +#ifndef _WIN32 +i F_OK R_OK W_OK X_OK +i STDIN_FILENO STDOUT_FILENO STDERR_FILENO +#else +J F_OK=:0 +J R_OK=:4 +J W_OK=:2 +J X_OK=:1 +#endif +i SEEK_CUR SEEK_END SEEK_SET +; Defining NULL is problematic in various ways. +; Most notably, it's unclear whether it should be boxed or not. + +; fcntl: +i O_APPEND O_CREAT O_EXCL O_RDONLY O_RDWR O_TRUNC O_WRONLY + +#ifndef _WIN32 +i O_ACCMODE O_NOCTTY O_NONBLOCK +i FD_CLOEXEC +i F_DUPFD F_GETFD F_SETFD F_GETFL F_SETFL +i F_SETLK F_SETLKW F_GETLK F_UNLCK F_WRLCK +st struct flock +f l_len +f l_pid +f l_start +f l_type +f l_whence + +; mmap: +i PROT_READ PROT_WRITE PROT_EXEC PROT_NONE +i MAP_SHARED MAP_PRIVATE MAP_FIXED +#endif + +; Regex stuff: +i REG_EXTENDED REG_ICASE REG_NOSUB REG_NEWLINE + +st regex_t +f re_nsub +st regmatch_t +f rm_so +f rm_eo + +; select(2) support. +; This is beyond posix.1, but the following definitions are pretty +; universal now. Linux apparently requires some special treatment. +#ifdef linux +#define fds_bits __fds_bits +#endif + +#ifndef _WIN32 +st fd_set +f fds_bits +#endif +i FD_SETSIZE +st struct timeval +f tv_sec +f tv_usec + +; POSIX error constants: +i E2BIG EFAULT ENFILE ENOTTY +i EACCES EFBIG ENODEV ENXIO +i EAGAIN ENOENT EPERM +i EBADF EINTR ENOEXEC EPIPE +i EINVAL ENOLCK ERANGE +i EBUSY EIO ENOMEM EROFS +i EISDIR ENOSPC ESPIPE +i ECHILD EMFILE ENOSYS ESRCH +i EDEADLK EMLINK ENOTDIR +i EDOM ENOTEMPTY EXDEV +i EEXIST ENAMETOOLONG + +#ifndef _WIN32 +i EINPROGRESS ECANCELED ETIMEDOUT EMSGSIZE ENOTSUP +#endif \ No newline at end of file diff --git a/defs/netdefs.c b/defs/netdefs.c new file mode 100644 --- /dev/null +++ b/defs/netdefs.c @@ -0,0 +1,236 @@ +#include +#ifdef _WIN32 +#include +#else +#include +#include +#ifdef sun +#include +#endif +#include +#include +#include +#include +#endif +#include +#define offset(r,f) (((char*)&((r*)0)->f)-((char*)((r*)0))) +main(){ + printf ("NB. do not edit -- created by sym2ijs\n\n"); + printf ("cocurrent <'jdefs'\n\n"); + printf ("FIONBIO=: %d\n",(int)FIONBIO); + printf ("FIONREAD=: %d\n",(int)FIONREAD); + printf ("FD_SETSIZE=: %d\n",(int)FD_SETSIZE); + puts(""); +#ifdef _WIN32 + printf ("SD_RECEIVE=: %d\n",(int)SD_RECEIVE); + printf ("SD_SEND=: %d\n",(int)SD_SEND); + printf ("SD_BOTH=: %d\n",(int)SD_BOTH); +#endif + puts(""); + printf ("sockaddr_sz=: %d\n",(int)sizeof (struct sockaddr)); + printf ("sa_family_off=: %d\n",(int)offset(struct sockaddr,sa_family)); + printf ("sa_family_sz=: %d\n",(int)sizeof(((struct sockaddr*)0)->sa_family)); + printf ("sa_data_off=: %d\n",(int)offset(struct sockaddr,sa_data)); + printf ("sa_data_sz=: %d\n",(int)sizeof(((struct sockaddr*)0)->sa_data)); + puts(""); + printf ("sockaddr_in_sz=: %d\n",(int)sizeof (struct sockaddr_in)); + printf ("sin_family_off=: %d\n",(int)offset(struct sockaddr_in,sin_family)); + printf ("sin_family_sz=: %d\n",(int)sizeof(((struct sockaddr_in*)0)->sin_family)); + printf ("sin_port_off=: %d\n",(int)offset(struct sockaddr_in,sin_port)); + printf ("sin_port_sz=: %d\n",(int)sizeof(((struct sockaddr_in*)0)->sin_port)); + printf ("sin_addr_off=: %d\n",(int)offset(struct sockaddr_in,sin_addr)); + printf ("sin_addr_sz=: %d\n",(int)sizeof(((struct sockaddr_in*)0)->sin_addr)); + puts(""); + printf ("in_addr_sz=: %d\n",(int)sizeof (struct in_addr)); + printf ("s_addr_off=: %d\n",(int)offset(struct in_addr,s_addr)); + printf ("s_addr_sz=: %d\n",(int)sizeof(((struct in_addr*)0)->s_addr)); + puts(""); + printf ("hostent_sz=: %d\n",(int)sizeof (struct hostent)); + printf ("h_name_off=: %d\n",(int)offset(struct hostent,h_name)); + printf ("h_name_sz=: %d\n",(int)sizeof(((struct hostent*)0)->h_name)); + printf ("h_aliases_off=: %d\n",(int)offset(struct hostent,h_aliases)); + printf ("h_aliases_sz=: %d\n",(int)sizeof(((struct hostent*)0)->h_aliases)); + printf ("h_addrtype_off=: %d\n",(int)offset(struct hostent,h_addrtype)); + printf ("h_addrtype_sz=: %d\n",(int)sizeof(((struct hostent*)0)->h_addrtype)); + printf ("h_length_off=: %d\n",(int)offset(struct hostent,h_length)); + printf ("h_length_sz=: %d\n",(int)sizeof(((struct hostent*)0)->h_length)); + printf ("h_addr_list_off=: %d\n",(int)offset(struct hostent,h_addr_list)); + printf ("h_addr_list_sz=: %d\n",(int)sizeof(((struct hostent*)0)->h_addr_list)); + puts(""); + puts(""); + printf ("SIOCATMARK=: %d\n",(int)SIOCATMARK); + puts(""); + puts(""); + printf ("IPPROTO_IP=: %d\n",(int)IPPROTO_IP); + printf ("IPPROTO_ICMP=: %d\n",(int)IPPROTO_ICMP); + printf ("IPPROTO_IGMP=: %d\n",(int)IPPROTO_IGMP); + printf ("IPPROTO_TCP=: %d\n",(int)IPPROTO_TCP); + printf ("IPPROTO_PUP=: %d\n",(int)IPPROTO_PUP); + printf ("IPPROTO_UDP=: %d\n",(int)IPPROTO_UDP); + printf ("IPPROTO_IDP=: %d\n",(int)IPPROTO_IDP); + printf ("IPPROTO_RAW=: %d\n",(int)IPPROTO_RAW); + printf ("IPPROTO_MAX=: %d\n",(int)IPPROTO_MAX); + puts(""); + puts(""); + printf ("INADDR_ANY=: %d\n",(int)INADDR_ANY); + printf ("INADDR_LOOPBACK=: %d\n",(int)INADDR_LOOPBACK); + printf ("INADDR_BROADCAST=: %d\n",(int)INADDR_BROADCAST); +#ifdef INADDR_NONE + printf ("INADDR_NONE=: %d\n",(int)INADDR_NONE); +#else + puts ("INADDR_NONE=: _1"); +#endif + puts(""); +#ifndef _WIN32 + printf ("INADDR_UNSPEC_GROUP=: %d\n",(int)INADDR_UNSPEC_GROUP); + printf ("INADDR_ALLHOSTS_GROUP=: %d\n",(int)INADDR_ALLHOSTS_GROUP); + printf ("INADDR_MAX_LOCAL_GROUP=: %d\n",(int)INADDR_MAX_LOCAL_GROUP); + printf ("IN_LOOPBACKNET=: %d\n",(int)IN_LOOPBACKNET); +#endif + puts(""); + printf ("SOCK_STREAM=: %d\n",(int)SOCK_STREAM); + printf ("SOCK_DGRAM=: %d\n",(int)SOCK_DGRAM); + printf ("SOCK_RAW=: %d\n",(int)SOCK_RAW); + printf ("SOCK_RDM=: %d\n",(int)SOCK_RDM); + printf ("SOCK_SEQPACKET=: %d\n",(int)SOCK_SEQPACKET); + puts(""); + printf ("SOL_SOCKET=: %d\n",(int)SOL_SOCKET); + printf ("SO_DEBUG=: %d\n",(int)SO_DEBUG); + printf ("SO_REUSEADDR=: %d\n",(int)SO_REUSEADDR); + printf ("SO_KEEPALIVE=: %d\n",(int)SO_KEEPALIVE); + printf ("SO_DONTROUTE=: %d\n",(int)SO_DONTROUTE); + printf ("SO_BROADCAST=: %d\n",(int)SO_BROADCAST); + printf ("SO_LINGER=: %d\n",(int)SO_LINGER); + printf ("SO_OOBINLINE=: %d\n",(int)SO_OOBINLINE); + puts(""); + printf ("SO_SNDBUF=: %d\n",(int)SO_SNDBUF); + printf ("SO_RCVBUF=: %d\n",(int)SO_RCVBUF); + printf ("SO_SNDLOWAT=: %d\n",(int)SO_SNDLOWAT); + printf ("SO_RCVLOWAT=: %d\n",(int)SO_RCVLOWAT); + printf ("SO_SNDTIMEO=: %d\n",(int)SO_SNDTIMEO); + printf ("SO_RCVTIMEO=: %d\n",(int)SO_RCVTIMEO); + printf ("SO_ERROR=: %d\n",(int)SO_ERROR); + printf ("SO_TYPE=: %d\n",(int)SO_TYPE); + puts(""); + printf ("linger_sz=: %d\n",(int)sizeof (struct linger)); + printf ("l_onoff_off=: %d\n",(int)offset(struct linger,l_onoff)); + printf ("l_onoff_sz=: %d\n",(int)sizeof(((struct linger*)0)->l_onoff)); + printf ("l_linger_off=: %d\n",(int)offset(struct linger,l_linger)); + printf ("l_linger_sz=: %d\n",(int)sizeof(((struct linger*)0)->l_linger)); + puts(""); + printf ("AF_UNSPEC=: %d\n",(int)AF_UNSPEC); + printf ("AF_UNIX=: %d\n",(int)AF_UNIX); + printf ("AF_INET=: %d\n",(int)AF_INET); + printf ("AF_SNA=: %d\n",(int)AF_SNA); + printf ("AF_DECnet=: %d\n",(int)AF_DECnet); + printf ("AF_APPLETALK=: %d\n",(int)AF_APPLETALK); + printf ("AF_IPX=: %d\n",(int)AF_IPX); + printf ("AF_MAX=: %d\n",(int)AF_MAX); + printf ("PF_UNSPEC=: %d\n",(int)PF_UNSPEC); + printf ("PF_UNIX=: %d\n",(int)PF_UNIX); + printf ("PF_INET=: %d\n",(int)PF_INET); + printf ("PF_SNA=: %d\n",(int)PF_SNA); + printf ("PF_DECnet=: %d\n",(int)PF_DECnet); + printf ("PF_APPLETALK=: %d\n",(int)PF_APPLETALK); + printf ("PF_IPX=: %d\n",(int)PF_IPX); + printf ("PF_MAX=: %d\n",(int)PF_MAX); + puts(""); + printf ("SOMAXCONN=: %d\n",(int)SOMAXCONN); + printf ("MSG_OOB=: %d\n",(int)MSG_OOB); + printf ("MSG_PEEK=: %d\n",(int)MSG_PEEK); + printf ("MSG_DONTROUTE=: %d\n",(int)MSG_DONTROUTE); + puts(""); +#ifndef _WIN32 + printf ("msghdr_sz=: %d\n",(int)sizeof (struct msghdr)); + printf ("msg_name_off=: %d\n",(int)offset(struct msghdr,msg_name)); + printf ("msg_name_sz=: %d\n",(int)sizeof(((struct msghdr*)0)->msg_name)); + printf ("msg_namelen_off=: %d\n",(int)offset(struct msghdr,msg_namelen)); + printf ("msg_namelen_sz=: %d\n",(int)sizeof(((struct msghdr*)0)->msg_namelen)); + printf ("msg_iov_off=: %d\n",(int)offset(struct msghdr,msg_iov)); + printf ("msg_iov_sz=: %d\n",(int)sizeof(((struct msghdr*)0)->msg_iov)); + printf ("msg_iovlen_off=: %d\n",(int)offset(struct msghdr,msg_iovlen)); + printf ("msg_iovlen_sz=: %d\n",(int)sizeof(((struct msghdr*)0)->msg_iovlen)); +#if defined(linux) || defined(Darwin) + printf ("msg_control_off=: %d\n",(int)offset(struct msghdr,msg_control)); + printf ("msg_control_sz=: %d\n",(int)sizeof(((struct msghdr*)0)->msg_control)); + printf ("msg_controllen_off=: %d\n",(int)offset(struct msghdr,msg_controllen)); + printf ("msg_controllen_sz=: %d\n",(int)sizeof(((struct msghdr*)0)->msg_controllen)); + printf ("msg_flags_off=: %d\n",(int)offset(struct msghdr,msg_flags)); + printf ("msg_flags_sz=: %d\n",(int)sizeof(((struct msghdr*)0)->msg_flags)); +#else + printf ("msg_accrights_off=: %d\n",(int)offset(struct msghdr,msg_accrights)); + printf ("msg_accrights_sz=: %d\n",(int)sizeof(((struct msghdr*)0)->msg_accrights)); + printf ("msg_accrightslen_off=: %d\n",(int)offset(struct msghdr,msg_accrightslen)); + printf ("msg_accrightslen_sz=: %d\n",(int)sizeof(((struct msghdr*)0)->msg_accrightslen)); +#endif +#endif + puts(""); +#ifdef _WIN32 + printf ("SOCKET_ERROR=: %d\n",(int)SOCKET_ERROR); + printf ("FD_READ=: %d\n",(int)FD_READ); + printf ("FD_WRITE=: %d\n",(int)FD_WRITE); + printf ("FD_OOB=: %d\n",(int)FD_OOB); + printf ("FD_ACCEPT=: %d\n",(int)FD_ACCEPT); + printf ("FD_CONNECT=: %d\n",(int)FD_CONNECT); + printf ("FD_CLOSE=: %d\n",(int)FD_CLOSE); + printf ("WSABASEERR=: %d\n",(int)WSABASEERR); + printf ("WSAEINTR=: %d\n",(int)WSAEINTR); + printf ("WSAEBADF=: %d\n",(int)WSAEBADF); + printf ("WSAEACCES=: %d\n",(int)WSAEACCES); + printf ("WSAEFAULT=: %d\n",(int)WSAEFAULT); + printf ("WSAEINVAL=: %d\n",(int)WSAEINVAL); + printf ("WSAEMFILE=: %d\n",(int)WSAEMFILE); + printf ("WSAEWOULDBLOCK=: %d\n",(int)WSAEWOULDBLOCK); + printf ("WSAEINPROGRESS=: %d\n",(int)WSAEINPROGRESS); + printf ("WSAEALREADY=: %d\n",(int)WSAEALREADY); + printf ("WSAENOTSOCK=: %d\n",(int)WSAENOTSOCK); + printf ("WSAEDESTADDRREQ=: %d\n",(int)WSAEDESTADDRREQ); + printf ("WSAEMSGSIZE=: %d\n",(int)WSAEMSGSIZE); + printf ("WSAEPROTOTYPE=: %d\n",(int)WSAEPROTOTYPE); + printf ("WSAENOPROTOOPT=: %d\n",(int)WSAENOPROTOOPT); + printf ("WSAEPROTONOSUPPORT=: %d\n",(int)WSAEPROTONOSUPPORT); + printf ("WSAESOCKTNOSUPPORT=: %d\n",(int)WSAESOCKTNOSUPPORT); + printf ("WSAEOPNOTSUPP=: %d\n",(int)WSAEOPNOTSUPP); + printf ("WSAEPFNOSUPPORT=: %d\n",(int)WSAEPFNOSUPPORT); + printf ("WSAEAFNOSUPPORT=: %d\n",(int)WSAEAFNOSUPPORT); + printf ("WSAEADDRINUSE=: %d\n",(int)WSAEADDRINUSE); + printf ("WSAEADDRNOTAVAIL=: %d\n",(int)WSAEADDRNOTAVAIL); + printf ("WSAENETDOWN=: %d\n",(int)WSAENETDOWN); + printf ("WSAENETUNREACH=: %d\n",(int)WSAENETUNREACH); + printf ("WSAENETRESET=: %d\n",(int)WSAENETRESET); + printf ("WSAECONNABORTED=: %d\n",(int)WSAECONNABORTED); + printf ("WSAECONNRESET=: %d\n",(int)WSAECONNRESET); + printf ("WSAENOBUFS=: %d\n",(int)WSAENOBUFS); + printf ("WSAEISCONN=: %d\n",(int)WSAEISCONN); + printf ("WSAENOTCONN=: %d\n",(int)WSAENOTCONN); + printf ("WSAESHUTDOWN=: %d\n",(int)WSAESHUTDOWN); + printf ("WSAETOOMANYREFS=: %d\n",(int)WSAETOOMANYREFS); + printf ("WSAETIMEDOUT=: %d\n",(int)WSAETIMEDOUT); + printf ("WSAECONNREFUSED=: %d\n",(int)WSAECONNREFUSED); + printf ("WSAELOOP=: %d\n",(int)WSAELOOP); + printf ("WSAENAMETOOLONG=: %d\n",(int)WSAENAMETOOLONG); + printf ("WSAEHOSTDOWN=: %d\n",(int)WSAEHOSTDOWN); + printf ("WSAEHOSTUNREACH=: %d\n",(int)WSAEHOSTUNREACH); + printf ("WSAENOTEMPTY=: %d\n",(int)WSAENOTEMPTY); + printf ("WSAEPROCLIM=: %d\n",(int)WSAEPROCLIM); + printf ("WSAEUSERS=: %d\n",(int)WSAEUSERS); + printf ("WSAEDQUOT=: %d\n",(int)WSAEDQUOT); + printf ("WSAESTALE=: %d\n",(int)WSAESTALE); + printf ("WSAEREMOTE=: %d\n",(int)WSAEREMOTE); + printf ("WSASYSNOTREADY=: %d\n",(int)WSASYSNOTREADY); + printf ("WSAVERNOTSUPPORTED=: %d\n",(int)WSAVERNOTSUPPORTED); + printf ("WSANOTINITIALISED=: %d\n",(int)WSANOTINITIALISED); + printf ("WSAHOST_NOT_FOUND=: %d\n",(int)WSAHOST_NOT_FOUND); + printf ("HOST_NOT_FOUND=: %d\n",(int)HOST_NOT_FOUND); + printf ("WSATRY_AGAIN=: %d\n",(int)WSATRY_AGAIN); + printf ("TRY_AGAIN=: %d\n",(int)TRY_AGAIN); + printf ("WSANO_RECOVERY=: %d\n",(int)WSANO_RECOVERY); + printf ("NO_RECOVERY=: %d\n",(int)NO_RECOVERY); + printf ("WSANO_DATA=: %d\n",(int)WSANO_DATA); + printf ("NO_DATA=: %d\n",(int)NO_DATA); + printf ("WSANO_ADDRESS=: %d\n",(int)WSANO_ADDRESS); + printf ("NO_ADDRESS=: %d\n",(int)NO_ADDRESS); + printf ("WM_USER=: %d\n",(int)WM_USER); +#endif + exit (0); +} diff --git a/defs/netdefs.sym b/defs/netdefs.sym new file mode 100644 --- /dev/null +++ b/defs/netdefs.sym @@ -0,0 +1,135 @@ + +#ifdef _WIN32 + +#else + + +#ifdef sun + +#endif + + + + +#endif + + + +; Networking-related definitions. +; (Keep "strongly-POSIX-related" definitions in unixsyms.sym, though.) +; + +i FIONBIO FIONREAD FD_SETSIZE + +#ifdef _WIN32 +i SD_RECEIVE SD_SEND SD_BOTH +#endif + +st struct sockaddr +f sa_family +f sa_data + +st struct sockaddr_in +f sin_family +f sin_port +f sin_addr + +st struct in_addr +f s_addr + +st struct hostent +f h_name +f h_aliases +f h_addrtype +f h_length +f h_addr_list + +; Provide just a tiny tiny subset of socket ioctls: + +i SIOCATMARK + +; The following are all "classic" Well Known Numbers as delivered +; with BSD4.3. The official reference today would be a look at +; the IANA lists, most notably RFC 1700. +; All the constants should probably better _not_ be used. +; getprotobyname etc. are they way to go. +; +; Having said that: +; We will restrict ourselves only to those constants listed with +; every netinet/in.h on any platform. + +i IPPROTO_IP IPPROTO_ICMP IPPROTO_IGMP IPPROTO_TCP +i IPPROTO_PUP IPPROTO_UDP IPPROTO_IDP +i IPPROTO_RAW IPPROTO_MAX + +; IMP link numbers? whoa, they lost their relevance in the late 70s... +; I doubt there's still _any_ of the (four?) IMP nodes is still running. +; Solaris has them, Linux not. Trash these entries. +; i IMPLINK_IP IMPLINK_LOWEXPER IMPLINK_HIGHEXPER + +i INADDR_ANY INADDR_LOOPBACK INADDR_BROADCAST +; INADDR_NONE is referring to the (deprecated) return value of +; the deprecated function inet_addr. The value is usually -1 +; (even though Solaris' inet_addr() return an unsigned long...) and +; actually clashes with the valid address INADDR_BROADCAST. Sigh... +#ifdef INADDR_NONE +i INADDR_NONE +#else +J INADDR_NONE=: _1 +#endif + +#ifndef _WIN32 +i INADDR_UNSPEC_GROUP INADDR_ALLHOSTS_GROUP INADDR_MAX_LOCAL_GROUP +i IN_LOOPBACKNET +#endif + +i SOCK_STREAM SOCK_DGRAM SOCK_RAW SOCK_RDM SOCK_SEQPACKET + +i SOL_SOCKET +i SO_DEBUG SO_REUSEADDR SO_KEEPALIVE SO_DONTROUTE +i SO_BROADCAST SO_LINGER SO_OOBINLINE + +i SO_SNDBUF SO_RCVBUF SO_SNDLOWAT SO_RCVLOWAT SO_SNDTIMEO SO_RCVTIMEO +i SO_ERROR SO_TYPE + +st struct linger +f l_onoff +f l_linger + +; Again, only the common subset: +i AF_UNSPEC AF_UNIX AF_INET AF_SNA AF_DECnet AF_APPLETALK AF_IPX AF_MAX +i PF_UNSPEC PF_UNIX PF_INET PF_SNA PF_DECnet PF_APPLETALK PF_IPX PF_MAX + +i SOMAXCONN +i MSG_OOB MSG_PEEK MSG_DONTROUTE + +#ifndef _WIN32 +st struct msghdr +f msg_name +f msg_namelen +f msg_iov +f msg_iovlen +#if defined(linux) || defined(Darwin) +f msg_control +f msg_controllen +f msg_flags +#else +f msg_accrights +f msg_accrightslen +#endif +#endif + +#ifdef _WIN32 +i SOCKET_ERROR +i FD_READ FD_WRITE FD_OOB FD_ACCEPT FD_CONNECT FD_CLOSE +i WSABASEERR WSAEINTR WSAEBADF WSAEACCES WSAEFAULT WSAEINVAL WSAEMFILE WSAEWOULDBLOCK +i WSAEINPROGRESS WSAEALREADY WSAENOTSOCK WSAEDESTADDRREQ WSAEMSGSIZE WSAEPROTOTYPE +i WSAENOPROTOOPT WSAEPROTONOSUPPORT WSAESOCKTNOSUPPORT WSAEOPNOTSUPP WSAEPFNOSUPPORT +i WSAEAFNOSUPPORT WSAEADDRINUSE WSAEADDRNOTAVAIL WSAENETDOWN WSAENETUNREACH +i WSAENETRESET WSAECONNABORTED WSAECONNRESET WSAENOBUFS WSAEISCONN WSAENOTCONN +i WSAESHUTDOWN WSAETOOMANYREFS WSAETIMEDOUT WSAECONNREFUSED WSAELOOP WSAENAMETOOLONG +i WSAEHOSTDOWN WSAEHOSTUNREACH WSAENOTEMPTY WSAEPROCLIM WSAEUSERS WSAEDQUOT WSAESTALE +i WSAEREMOTE WSASYSNOTREADY WSAVERNOTSUPPORTED WSANOTINITIALISED WSAHOST_NOT_FOUND +i HOST_NOT_FOUND WSATRY_AGAIN TRY_AGAIN WSANO_RECOVERY NO_RECOVERY WSANO_DATA +i NO_DATA WSANO_ADDRESS NO_ADDRESS WM_USER +#endif \ No newline at end of file diff --git a/defs/sym2ijs.ijs b/defs/sym2ijs.ijs new file mode 100644 --- /dev/null +++ b/defs/sym2ijs.ijs @@ -0,0 +1,178 @@ +NB. built from project: source\api\sym2ijs\sym2ijs +NB. sym2ijs +NB. +NB. format: +NB. path sym2ijs name +NB. +NB. e.g. +NB. '\dev\defs\' sym2ijs 'hostdefs' +NB. see doc at end for details + +NB. require 'files strings misc' + +NB. ========================================================= +include1=: 3 : 0 +'#include ', y +) + +NB. ========================================================= +NB. integer +integer1=: 3 : 0 +printf each ;: }. y +) + +NB. ========================================================= +NB. jcode +jcode1=: 3 : 0 +TAB,'puts ("',(2 }. y),'");' +) + +NB. ========================================================= +printf=: 3 : 0 +printf~ y +: +TAB,'printf ("',x,'=: %d\n",(int)',y,');' +) + +NB. ========================================================= +structure1=: 3 : 0 +id=. deb 3 }. 0 pick y +sd=. (7 * 'struct ' -: 7 {. id) }. id +bal=. }. y +msk=. *. /\ ({.&> bal) e. 'f#' +r=. <(sd,'_sz') printf 'sizeof (',id,')' +r=. r, id&structure2 each msk # bal +(< S: 0 r), (-.msk) # bal +) + +NB. ========================================================= +structure2=: 4 : 0 +if. 'f' ~: {. y do. y return. end. +id=. deb 2 }. y +r=. (id,'_off') printf 'offset(',x,',',id,')' +s=. (id,'_sz') printf 'sizeof(((',x,'*)0)->',id,')' +r;s +) + + +NB. ========================================================= +j=. cutopen (0 : 0) rplc '~',TAB +#define offset(r,f) (((char*)&((r*)0)->f)-((char*)((r*)0))) +main(){ +~printf ("NB. do not edit -- created by sym2ijs\n\n"); +~printf ("cocurrent <'jdefs'\n\n"); +) + +SYMTXT=: cutopen j rplc '~',TAB + +bx=: 3 : 'y#i.#y' NB.! +tolist=: 3 : ';y,each LF' NB.! + +NB. ========================================================= +NB. [path] sym2ijs name --- '\dev\defs\' sym2ijs 'netdefs' +NB. reads name.sym and creates name.c +sym2ijs=: 3 : 0 +'' sym2ijs y +: +dat=. 'b' fread jpath x,y,'.sym' +dat=. deb each dat +dat=. (';' ~: {.&> dat) # dat + +NB. split off includes from main: +ndx=. (+. /\. '<' = {.&> dat) i. 0 +hdr=. ndx {. dat +bal=. ndx }. dat +bal=. bal }.~ (bal ~: <'') i. 1 + +NB. includes: +ndx=. bx Q=:'<' = {.&> hdr +hdr=. (include1 each ndx { hdr) ndx } hdr + +NB. structures: +msk=. 1,('t' = {.&> bal) +. (<'st') = 2 {.each bal +bal=. }. < S: 0 msk <@structure1;.1 '';bal + +NB. integers: +ndx=. bx 'i' = {.&> bal +bal=. (integer1 each ndx { bal) ndx } bal +bal=. < S: 0 bal + +NB. J code: +ndx=. bx 'J' = {.&> bal +bal=. (jcode1 each ndx { bal) ndx } bal +bal=. < S: 0 bal + +NB. empties: +ndx=. bx 0 = # &> bal +bal=. ( - include the specified system header file + +"filename" - include the specified local header file. + +first emtpy line - switch from global section in the intermediary C program to the +main() function issuing all the print statements for the values. No header files may +be listed after this line. Other empty lines are preserved in the J script output. + +i symbol ... - integer-typed symbol(s) defined as a C header constants or C variables. +Corresponding assignments to J symbols will be generated. + +t typename - define the (J) symbol typename_sz to have the value of sizeof(typename) . + +st typename - a structure type is introduced, leading to a typename_sz + +st struct structtag - a structure type is introduced, leading to a typename_sz. +The struct keyword has to be used where only this type of defintion is used in +the header file. + +An st line may be followed by f lines for fields in the structure. + +f fieldname - define fieldname_sz and the offset fieldname_off for a member +of the structure + +; comments + +C literal C code + +J literal J code + +# C preprocessor directive - passed to the intermediate C program allowing easy +conditional code. +) \ No newline at end of file diff --git a/docs/copyright.txt b/docs/copyright.txt new file mode 100644 --- /dev/null +++ b/docs/copyright.txt @@ -0,0 +1,15 @@ + +JSOFTWARE SOURCES refers to all files in this Jsoftware release +package except for file gpl3.txt. + +JSOFTWARE SOURCES are: +Copyright 1990-2011, Jsoftware Inc. All rights reserved. + +JSOFTWARE SOURCES are: +Licensed under GNU General Public License as published by the +Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +See gpl3.txt for GNU General Public License version 3. +Additional info at http://www.gnu.org/licenses. + diff --git a/docs/gpl3.txt b/docs/gpl3.txt new file mode 100644 --- /dev/null +++ b/docs/gpl3.txt @@ -0,0 +1,621 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS diff --git a/docs/ioj/ioj.htm b/docs/ioj/ioj.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/ioj.htm @@ -0,0 +1,149 @@ + + + +An Implementation of J + + + + +

+An Implementation of J
+Roger K.W. Hui +

+Copyright © 1990-2011, Jsoftware Inc.
last updated: 2000-06-23 +
+ +
+

Preface

+J is a dialect of APL freely available on a wide variety of machines. +It is the latest in the line of development known as "dictionary APL". +The spelling scheme uses the ASCII alphabet. +The underlying concepts, such as arrays, verbs, adverbs, and rank, +are extensions and generalizations of ideas in APL\360. +Anomalies have been removed. +The result is at once simpler and more powerful than previous dialects.

+ +This document describes an implementation of J in C. +The reader is assumed to be familiar with J and C. +J is specified by the +J Dictionary, and +introductions to the language are available in +Programming in J and +J Primer; +C is described in +The C Programming Language.

+ +Why "J"? It is easy to type. + +

Acknowledgment

+

Ex ungue leonem.

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Contents
  
0. Introduction6. Display
  6.1 Numeric Display
1. Interpreting a Sentence  6.2 Boxed Display
  1.1 Word Formation  6.3 Formatted Display
  1.2 Parsing 
  1.3 Trains7. Comparatives
  1.4 Name Resolution 
 Appendices
2. Nouns  A. Incunabulum
  2.1 Arrays  B. Special Code
  2.2 Types  C. Test Scripts
  2.3 Memory Management        D. Program Files
  2.4 Global Variables  E. Foreign Conjunction
   F. System Summary
3. Verbs 
  3.1 Anatomy of a VerbBibliography
  3.2 RankGlossary and Index
  3.3 Atomic (Scalar) Verbs 
  3.4 Obverses, Identities, and Variants     
  3.5 Error Handling 
  
4. Adverbs and Conjunctions 
  
5. Representation 
  5.1 Atomic Representation 
  5.2 Boxed Representation 
  5.3 Tree Representation 
  5.4 Linear Representation 
+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + diff --git a/docs/ioj/iojATW.htm b/docs/ioj/iojATW.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojATW.htm @@ -0,0 +1,83 @@ + + + +An Implementation of J -- Incunabulum + + + + +

Incunabulum
+An Implementation of J

+ +
+
+ +One summer weekend in 1989, Arthur Whitney visited Ken Iverson at +Kiln Farm and produced — on one page and in one afternoon — +an interpreter fragment on the AT&T 3B1 computer. +I studied this interpreter for about a week for its organization +and programming style; and on Sunday, August 27, 1989, at about +four o'clock in the afternoon, wrote the first line of +code that became the implementation described in this document.

+ +Arthur's one-page interpreter fragment is as follows:

+ +
+typedef char C;typedef long I;
+typedef struct a{I t,r,d[3],p[2];}*A;
+#define P printf
+#define R return
+#define V1(f) A f(w)A w;
+#define V2(f) A f(a,w)A a,w;
+#define DO(n,x) {I i=0,_n=(n);for(;i<_n;++i){x;}}
+I *ma(n){R(I*)malloc(n*4);}mv(d,s,n)I *d,*s;{DO(n,d[i]=s[i]);}
+tr(r,d)I *d;{I z=1;DO(r,z=z*d[i]);R z;}
+A ga(t,r,d)I *d;{A z=(A)ma(5+tr(r,d));z->t=t,z->r=r,mv(z->d,d,r);
+ R z;}
+V1(iota){I n=*w->p;A z=ga(0,1,&n);DO(n,z->p[i]=i);R z;}
+V2(plus){I r=w->r,*d=w->d,n=tr(r,d);A z=ga(0,r,d);
+ DO(n,z->p[i]=a->p[i]+w->p[i]);R z;}
+V2(from){I r=w->r-1,*d=w->d+1,n=tr(r,d);
+ A z=ga(w->t,r,d);mv(z->p,w->p+(n**a->p),n);R z;}
+V1(box){A z=ga(1,0,0);*z->p=(I)w;R z;}
+V2(cat){I an=tr(a->r,a->d),wn=tr(w->r,w->d),n=an+wn;
+ A z=ga(w->t,1,&n);mv(z->p,a->p,an);mv(z->p+an,w->p,wn);R z;}
+V2(find){}
+V2(rsh){I r=a->r?*a->d:1,n=tr(r,a->p),wn=tr(w->r,w->d);
+ A z=ga(w->t,r,a->p);mv(z->p,w->p,wn=n>wn?wn:n);
+ if(n-=wn)mv(z->p+wn,z->p,n);R z;}
+V1(sha){A z=ga(0,1,&w->r);mv(z->p,w->d,w->r);R z;}
+V1(id){R w;}V1(size){A z=ga(0,0,0);*z->p=w->r?*w->d:1;R z;}
+pi(i){P("%d ",i);}nl(){P("\n");}
+pr(w)A w;{I r=w->r,*d=w->d,n=tr(r,d);DO(r,pi(d[i]));nl();
+ if(w->t)DO(n,P("< ");pr(w->p[i]))else DO(n,pi(w->p[i]));nl();}
+
+C vt[]="+{~<#,";
+A(*vd[])()={0,plus,from,find,0,rsh,cat},
+ (*vm[])()={0,id,size,iota,box,sha,0};
+I st[26]; qp(a){R  a>='a'&&a<='z';}qv(a){R a<'a';}
+A ex(e)I *e;{I a=*e;
+ if(qp(a)){if(e[1]=='=')R st[a-'a']=ex(e+2);a= st[ a-'a'];}
+ R qv(a)?(*vm[a])(ex(e+1)):e[1]?(*vd[e[1]])(a,ex(e+2)):(A)a;}
+noun(c){A z;if(c<'0'||c>'9')R 0;z=ga(0,0,0);*z->p=c-'0';R z;}
+verb(c){I i=0;for(;vt[i];)if(vt[i++]==c)R i;R 0;}
+I *wd(s)C *s;{I a,n=strlen(s),*e=ma(n+1);C c;
+ DO(n,e[i]=(a=noun(c=s[i]))?a:(a=verb(c))?a:c);e[n]=0;R e;}
+
+main(){C s[99];while(gets(s))pr(ex(wd(s)));}
+
+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojAdv.htm b/docs/ioj/iojAdv.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojAdv.htm @@ -0,0 +1,263 @@ + + + +An Implementation of J -- Adverbs and Conjunctions + + + + +

Adverbs and Conjunctions
+An Implementation of J

+ +
+
+ +An adverb is monadic, applying to a noun or verb argument on its left; +a conjunction is dyadic, applying to noun or verb arguments on its +left and right. The result is usually a verb, but can also +be a noun, adverb, or conjunction.

+ +The conjunction & is used here to illustrate the relationship +between relevant system components. +(The implementation of adverbs is similar.) +& derives a verb depending on whether the arguments are +nouns (m and n) or +verbs (u and v):

+ +
+   m&n       gerund join
+   m&v       m&v y is m v y
+   u&n       u&n y is y v n
+   u&v       u&v y is u v y;   x u&v y is (v x) u (v y)
+
+ +A verb defined from & is (internally) an +array of type VERB +whose value is interpreted according to the defined +type V in file jtype.h:

+ +
+   typedef struct {AF f1,f2;A f,g,h;I flag,mr,lr,rr;C id;} V;
+ + + + + + + + + + + + + +
    f1     monad
f2 dyad
f left conjunction argument or adverb argument
g right conjunction argument
h auxiliary argument
flag bit flags
mr monadic rank
lr left rank
rr right rank
id ID byte

+ +If fn=: %.&|:, the arrays would be:

+ +
+         k   flag    m     t     c     n     r
+      ŚÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀ
+   fn ³   28³    0³    8³ VERB³    3³    1³    0³...
+      ĄÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮ
+            ĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄæ
+         ...³  on1³  on2³   %.³   |:³    0³    0³    _³    _³    _³&    ³
+            ĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄŁ
+               f1    f2    f     g     h   flag    mr    lr    rr   id
+
+         k   flag    m     t     c     n     r
+      ŚÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀ
+   %. ³   28³    0³    8³ VERB³    _³    1³    0³...
+      ĄÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮ
+            ĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄæ
+         ...³ minv³ mdiv³    0³    0³    0³    0³    2³    _³    2³%.   ³
+            ĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄŁ
+               f1    f2    f     g     h   flag    mr    lr    rr   id
+
+         k   flag    m     t     c     n     r
+      ŚÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀ
+   |: ³   28³    0³    8³ VERB³    _³    1³    0³...
+      ĄÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮ
+            ĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄĀÄÄÄÄÄæ
+         ...³cant1³cant2³    0³    0³    0³    0³    _³    1³    _³|:   ³
+            ĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄĮÄÄÄÄÄŁ
+               f1    f2    f     g     h   flag    mr    lr    rr   id
+
+ +Access to the parts of fn is by name and by macros defined in files jt.h +and a.h, and never by offsets and indices. +Thus AV(fn) points to the value part of fn. +And if sv=(V*)AV(fn), +then sv->f1 is on1; +sv->f2 is on2; +sv->f is the array for %.; +sv->g is the array for |: +(that is, sv->f and sv->g are +arrays similar to fn); +sv->mr is _ (indicating +that fn has infinite monadic rank); and so on. +The macro VAV(f), defined +as ((V*)AV(f)), +is useful for working with adverbs and conjunctions.

+ +To introduce & into the system, functions which +implement & are added +to file c.c (or one of the c*.c files), and declarations of +global objects are added to file je.h:
+ +
+File c.c:
+   static CS1(on1,  CALL2(f1,CALL2(g1,w,gs),fs))
+   static CS2(on2,  CALL3(f2,CALL2(g1,a,gs),CALL2(g1,w,gs),fs))
+
+   static DF1(withl){DECLFG; R jt->rank?irs2(fs,w,gs,AR(fs),jt->rank[1],g2):CALL3(g2,fs,w,gs);}
+   static DF1(withr){DECLFG; R jt->rank?irs2(w,gs,fs,jt->rank[1],AR(gs),f2):CALL3(f2,w,gs,fs);}
+
+   F2(jtamp){I m;
+    RZ(a&&w);
+    switch(CONJCASE(a,w)){
+     default: ASSERTSYS(0,"amp");
+     case NN: R gjoin(CAMP,a,w);
+     case NV: R CDERIV(CAMP,withl,0L,RMAX,RMAX,RMAX);
+     case VN: R CDERIV(CAMP,withr,0L,RMAX,RMAX,RMAX);
+     case VV: m=mr(w); R CDERIV(CAMP,ID(a)==CSLASH&&ID(w)==CCOMMA?jtredravel:on1,on2,m,m,m);
+   }}
+
+File je.h:
+   extern F2(jtamp);
+
+ +Corresponding to the four possibilities, amp defines +four cases. (The impossible default case is to +obviate a spurious C compiler warning.) +The functions withl, withr, on1, +and on2 are applied when a verb derived from & is applied. +The VV case also recognizes u/&, as a special case, +whereby redravel is applied instead of on1.

+ +For the example in question, %.&|: m=: ?4 4$100 first +branches to the case VV in amp, and +subsequently applies on1 to m. +Consider a partial macro expansion of on1 and the +values of its local variables:

+ +
+Macro Expansion:
+   static A on1(J jt,A w,A self){PROLOG;V*sv=VAV(self);
+    A fs=sv->f;AF f1=fs?VAV(fs)->f1:0,f2=fs?VAV(fs)->f2:0;
+    A gs=sv->g;AF g1=gs?VAV(gs)->f1:0,g2=gs?VAV(gs)->f2:0; A z;
+    PREF1(on1); 
+    z=f1(jt,g1(jt,w,gs),fs);
+    EPILOG(z);
+   }
+
+Local Variables: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    w       the matrix m
selfthe verb fn
svpointer to the value part of fn as an array
fsleft argument to &, that is %.
f1monad of %.
f2dyad of %.
gsright argument to &, that is |:
g1monad of |:
g2dyad of |:

+ +The initialization of sv, fs, f1, +and so on are the same +for all adverbs and conjunctions; the details of such +initialization are normally suppressed by the use of macros. +If an argument to & (i.e. fs or gs) +is itself a result +of adverbs and conjunctions, expressions such as g1(jt,w,gs) +or f1(jt,xxx,gs) engender further executions +as occurs in on1. +The macro PREF1 implements +rank, +and the macros PROLOG +and EPILOG manage memory.

+ +The association between & and amp is established in the +table pst +in file t.c, exactly the way such associations are done for verbs. +In particular, CAMP is the ID for & +and ds(CAMP) is & as an array +(that is, ds(CAMP) is &).

+ +The utilities df1 +and df2 in file au.c +apply the monad or the dyad +of a verb. For example:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ds(CPOUND)#
ds(COPE)>
amp(ds(CPOUND),ds(COPE))#&>
 
df1(w,ds(CPOUND))# w
df1(  w,amp(ds(CPOUND),ds(COPE)))#&> w
df2(a,w,amp(ds(CPOUND),ds(COPE)))   a #&> w

+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojBib.htm b/docs/ioj/iojBib.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojBib.htm @@ -0,0 +1,144 @@ + + + +An Implementation of J -- Bibliography + + + + +

Bibliography
+An Implementation of J

+ +
+
+ +Abramowitz, M. and I.A. Stegun, Handbook of Mathematical Functions, +National Bureau of Standards, 1964 6.

+ +Bernecky, R., Comparison Tolerance, SHARP APL Technical Notes 23, +1977 6 10.

+ +Bernecky, R., An Introduction to Function Rank, APL88, +APL Quote-Quad Volume 18, Number 2, 1987 12.

+ +Bernecky, R., and R.K.W. Hui, Gerunds and Representations, APL91, +APL Quote-Quad, Volume 21, Number 4, 1991 8.

+ +Bernecky, R., and K.E. Iverson, Operators and Enclosed Arrays, +1980 APL User's Meeting Conference Proceedings, 1980 10 6.

+ +Bernecky, R., K.E. Iverson, E.E. McDonnell, +R.C. Metzger, and J.H. Schueler, +Language Extensions of May 1983, SHARP APL Technical Note 45, +I.P. Sharp Associates, 1983 5 2.

+ +Berry, P.C., SHARP APL Reference Manual, I.P. Sharp Associates, +1979 3; Additions and Corrections, 1981 6.

+ +Burke, C., R.K.W. Hui, K.E. Iverson, E.E. McDonnell, and D.B. McIntyre, +J Phrases, Iverson Software Inc., 1996.

+ +Falkoff, A.D., and K.E. Iverson, APL\360 User's Manual, IBM Corporation, +1968 8.

+ +Falkoff, A.D., and K.E. Iverson, The Design of APL, IBM Journal +of Research and Development, Volume 17, Number 4, 1973 7.

+ +Falkoff, A.D., and K.E. Iverson, The Evolution of APL, +ACM SIGPLAN Notices, Volume 13, Number 8, 1978 8.

+ +Hodgkinson, R., APL Procedures, APL86, +APL Quote-Quad 16.4, 1986 7.

+ +Hui, R.K.W., Some Uses of { and }, APL87, APL Quote-Quad, +Volume 17, Number 4, 1987 5.

+ +Hui, R.K.W., An Implementation of J, Iverson Software Inc., +1992 1 27.

+ +Hui, R.K.W., Rank and Uniformity, APL95, APL Quote-Quad, +Volume 25, Number 4, 1995 6.

+ +Hui, R.K.W., and Iverson, K.E., +J Introduction and Dictionary, Iverson Software Inc., 1998.

+ +Hui, R.K.W., K.E. Iverson, and E.E. McDonnell, Tacit Definition, +APL91, APL Quote-Quad, Volume 21, Number 4, 1991 8.

+ +Hui, R.K.W., K.E. Iverson, E.E. McDonnell, and A.T. Whitney, +APL\?, APL90, APL Quote-Quad, Volume 20, Number 4, 1990 7.

+ +Iverson, E.B., J Primer, Iverson Software Inc., 1996.

+ +Iverson, K.E., A Programming Language, Wiley, 1962 5.

+ +Iverson, K.E., Operators and Functions, Research Report #RC7091, +IBM Corporation, 1978 4 26.

+ +Iverson, K.E., Notation as a Tool of Thought, Communications +of the ACM, Volume 23, Number 8, 1980 8.

+ +Iverson, K.E., Rationalized APL, I.P. Sharp Associates Limited, +1983 1 6.

+ +Iverson, K.E., APL87, APL87, APL Quote-Quad, +Volume 17, Number 4, 1987 5.

+ +Iverson, K.E., A Dictionary of APL, APL Quote-Quad, +Volume 18, Number 1, 1987 9.

+ +Iverson, K.E., A Personal View of APL, +IBM Systems Journal, Volume 30, Number 4, 1991 12.

+ +Iverson, K.E., Arithmetic, Iverson Software Inc., 1991.

+ +Iverson, K.E., Programming in J, +Iverson Software Inc., 1991.

+ +Iverson, K.E., Tangible Math, Iverson Software Inc., 1991.

+ +Iverson, K.E., and E.E. McDonnell, Phrasal Forms, APL89, APL Quote-Quad, +Volume 19, Number 4, 1989 8.

+ +Iverson, K.E., and A.T. Whitney, Practical Uses of a Model of APL, +APL82, APL Quote-Quad, Volume 13, Number 1, 1982 9.

+ +Keenan, D.J., Operators and Uniform Forms, APL79, +APL Quote-Quad, Volume 9, Number 4, 1979 6.

+ +Kernighan, B.W., and D.M. Ritchie, +The C Programming Language, Prentice-Hall, 1978.

+ +McDonnell, E.E. and J.O. Shallit, Extending APL to Infinity, +APL80, North-Holland Publishing Company, 1980.

+ +McIntyre, D.B., Mastering J, +APL91, APL Quote-Quad, Volume 21, Number 4, 1991 8.

+ +McIntyre, D.B., Language as an Intellectual Tool: +From Hieroglyphics to APL, +IBM Systems Journal, Volume 30, Number 4, 1991 12.

+ +Pesch, R.H., Empty Frames in Sharp APL, APL86, +APL Quote-Quad, Volume 16, Number 4, 1986 7.

+ +Steinbrook, D.H., SAX Reference, +I.P. Sharp Associates, 1986.

+ +Whitney, A.T., A, plenary session, APL89, 1989 8.

+ +Whitney, A.T., private communication, Kiln Farm, 1992 5 24.

+
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + diff --git a/docs/ioj/iojComp.htm b/docs/ioj/iojComp.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojComp.htm @@ -0,0 +1,214 @@ + + + +An Implementation of J -- Comparatives + + + + +

Comparatives
+An Implementation of J

+ +
+
+ +Comparisons between finite numbers are tolerant, as defined in +Bernecky [1977]:

+ +   x = y   if   (|x-y) <:!.0 ct * (|x)>.(|y) +

+ +(<:!.0 means exact less than or equal.) +That is, x and y are tolerantly equal if the smaller +is on or within the circle centered at the larger, having +radius ct times the magnitude of the +larger. ct, comparison tolerance, +is a real number between 0 and 2^_34 with a default value +of 2^_44; a non-default tolerance may be specified +using the fit conjunction +(!.). Tolerant relations can be modelled as follows:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ct=: 2^_44comparison tolerance
teq=: |@- <:!.0 ct&*@>.&|equal
tne=: -.@teqnot equal
tlt=: < !.0 *. tneless than
tgt=: > !.0 *. tnegreater than
tle=: <:!.0 +. teqless than or equal to
tge=: >:!.0 +. teqgreater than or equal to
tfloor=: <.!.0@(0.5&+) ([ - tgt) ]   floor
tceil=: <.!.0@(0.5&+) ([ + tlt) ]ceiling
dsignum=: ct&<@| * 0&< - 0&>signum (real)
jsignum=: ct&<@| * (%|)signum (complex)
+
+ +Additionally, some comparisons internal to the system are fuzzy. +Fuzzy comparisons are like tolerant comparisons, but depend on the +parameter fuzz, having fixed +value 2^_44. Such comparisons are used in +certain domain tests; for example, (2 3+1e_14)$'abc' is valid +but (2 3+1e_12)$'abc' is not. Fuzzy comparisons can be +modelled as follows:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    fuzz=:2^_44
int=:(-2^31)&<: *. <&(2^31)
real=:{.@+.
feq=:|@- <:!.0 fuzz&*@>.&|
freal=:>:!.0 / @: ((fuzz,1)&*) @: | @: +.
BfromD=:]`(1&=) @. (feq 1&=)
IfromD=:]`<. @. (int *. (feq <.))
DfromZ =:]`real @. (feq real)
+
+ +The utility int tests for membership in the +interval -2^31 to _1+2^31 inclusive. real produces +the real part of a complex number. feq is 1 if its arguments +are equal within fuzz; freal is 1 if its complex argument is within +fuzz of real. BfromD, IfromD, and DfromZ convert +between types: boolean from real ("double"), integer from real, and real +from complex.

+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojDisp.htm b/docs/ioj/iojDisp.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojDisp.htm @@ -0,0 +1,341 @@ + + + +An Implementation of J -- Display + + + + +

Display
+An Implementation of J

+ +Numeric Display
+Boxed Display
+Formatted Display
+
+ +
+
+ +If the last operation in a line of user input is not assignment, +the result of the line is displayed. More specifically, if the global +variable asgn is zero at the end of +executing an input line, +and the line had no errors, jpr is invoked to display the +result. jpr first applies thorn1 (the monad ":) +to compute the display of y, then writes the +lines to the screen.

+ +In all cases, the display of an object is a literal array. +The display of a literal array is itself. The display of a +verb, adverb, or conjunction is that of the currently +selected representation(s). +The display of a numeric array, that of a +boxed array, and +format are now discussed.

+ +Display is implemented by functions and variables in the files +f.c and f2.c.

+
+ +Numeric Display

+ +The display of a numeric array y is a literal array +having the same rank as y (but at least one), such that the shape +of ":y matches the shape of y in all but the last axis. +Columns are right-justified and are separated by one space. +The conversion from numeric to literal can be modelled as follows:
+ +
+sprintf =: ":
+real    =: {.@+.
+imag    =: {:@+.
+
+minus   =: $&'_'@('-'&=@{.)
+ubar    =: >@({&(<;._1 ' _ _ _. _.'))@('iInN'&i.@{.)
+afte    =: minus , (i.&0@(e.&'-+0') }. ])
+efmt    =: >:@(i.&'e') ({. , afte@}.) ]
+finite  =: ]`efmt@.('e'&e.)
+massage =: finite`ubar@.(e.&'iInN'@{.)
+fmtD    =: (minus,massage@(e.&'-+'@{.}.])) @ sprintf
+
+cleanZ  =: (* ] >&| (2^_44)"_ * |.)&.+.
+fmtZ1   =: fmtD@real , 'j'&,@fmtD@imag`(''"_)@.(0&=@imag)
+fmtZ    =: fmtZ1 @ cleanZ
+
+fmtB    =: {&'01'
+fmtI    =: sprintf
+fmt     =: (fmtB&.>)`(fmtI&.>)`(fmtD&.>)`(fmtZ&.>) @. (1 4 8&i.@(3!:0))
+
+sh      =: (*/@}:,{:@(1&,))@$ ($,) ]
+width   =: (<:@{. 0} ])@:>:@(>./)@sh@:(#&>)
+th      =: (-@width ;@:({.&.>)"1 ]) @ fmt
+
+ +The model is divided into groups of verbs. The first group +are utilities:

+ +sprintf   a function in the C library
+type      type
+real      the real part of a complex number
+imag      the imaginary part of a complex number

+ +fmtD formats a real number. Its constituents transform the result +of sprintf to follow J conventions in the treatment of negative +signs (minus), exponential +notation (efmt and afte), and +infinities and indeterminates (ubar).

+ +fmt formats a numeric array into an array of boxed strings. +It invokes formatters specialized for the different types: fmtB +(Boolean), fmtI (integer), fmtD (floating point), +and fmtZ (complex).

+ +sh shapes an array into a table having the same number +of rows. width computes the maximum width in each column +of an array of boxed strings. th is a model of ": +on numeric arrays.

+ +
+ +

Boxed Display

+ +The display of a boxed array b is a literal array d=:":b +such that:
+ • The rank of d is the greater of 2 or the rank of b.
+ • Excluding the last two axes, the shape of d matches +the shape of b.
+ • The frame (formed by Ś Ā æĆ Å “Ą Į Ł ³ Ä) +is the same in all the planes.

+ +Boxed display can be modelled as follows:
+ +

+boxed   =: 32&= @ (3!:0)
+mt      =: 0&e.@$
+boxc    =: {. 9!:6 ''
+tcorn   =: 2  0{boxc
+tint    =: 1 10{boxc
+bcorn   =: 8  6{boxc
+bint    =: 7 10{boxc
+
+sh      =: (*/@}: , {:)@(1&,)@$ $ ,
+rows    =: */\.@}:@$
+bl      =: }.@(,&0)@(+/)@(0&=)@(|/ i.@{.@(,&1))
+mask    =: 1&,. #&, ,.&0@>:@i.@#
+mat     =: mask@bl@rows { ' '&,@sh
+
+edge    =: ,@(1&,.)@[ }.@# +:@#@[ $ ]
+left    =: edge&(3 9{boxc)@>@(0&{)@[ , "0 1"2 ]
+right   =: edge&(5 9{boxc)@>@(0&{)@[ ,~"0 1"2 ]
+top     =: 1&|.@(tcorn&,)@(edge&tint)@>@(1&{)@[ ,"2  ]
+bot     =: 1&|.@(bcorn&,)@(edge&bint)@>@(1&{)@[ ,"2~ ]
+perim   =: [ top [ bot [ left [ right ]
+
+topleft =: (4{boxc)&((<0 0)}) @ ((_2{boxc)&,.) @ ((_1{boxc)&,)
+inside  =: 1 1&}. @ ; @: (,.&.>/"1) @: (topleft&.>)
+take    =: [ {. ]`(]&' ')@.mt@]
+frame   =: [ perim {@[ inside@:(take&.>)"2 ,:^:(1&=@#@$)@]
+rc      =: (>./@sh&.>) @: (,.@|:"2@:(0&{"1);1&{"1) @: ($&>)
+
+thorn1  =: ":`thbox @. boxed
+thbox   =: (rc frame ]) @: (mat@thorn1&.>)
+
+ +The model is divided into groups of definitions (which are verbs +unless indicated otherwise). The first group are utilities:

+ +boxed     1 if boxed
+mt        1 if empty
+boxc      (noun) box drawing characters
+tcorn     (noun) the characters æ Ś
+tint      (noun) the characters Ā Ä
+bcorn     (noun) the characters Ł Ą
+bint      (noun) the characters Į Ä
+
+ +mat is the main verb of the next group of definitions. +The argument is a literal array; the result is a literal matrix image of +the array — a literal table that "looks like" the argument array.

+ +perim draws a perimeter around each plane of the right argument: +According to the information in the left argument (a result +of rc), perim puts + æ Ś Ā Ä (top), + Ł Ą Į Ä (bot), + Ć ³ (left), or + “ ³ (right) at +appropriate positions on the perimeter of each plane.

+ +topleft catenates the characters Å ³ Ä +on the top and left edges of a literal table. inside produces +the inside (excluding perimeter) of a plane of the display. take +is {. if the right argument is non-empty, and is an array +of blanks otherwise. frame applies to an array of boxed tabular +displays, and computes the overall display. rc computes the +number of rows and columns in the display of atoms in a plane.

+ +thorn1 models ":; thbox models ": on +a boxed array.

+ +The following examples illustrate the inner workings of the model:
+
+   y=: 2 3$(i.2 3);'abc';(i.4 1);(<2 2$'ussr');12;<+&.>i.2 2 3
+   x=: mat@thorn1&.>y
+
+   $&.> x              rc x              { rc x
+ŚÄÄÄĀÄÄÄĀÄÄÄÄæ      ŚÄÄÄÄĀÄÄÄÄÄæ      ŚÄÄÄÄĀÄÄÄÄĀÄÄÄÄæ
+³2 5³1 3³4 1 ³      ³4 11³5 3 9³      ³4 5 ³4 3 ³4 9 ³
+ĆÄÄÄÅÄÄÄÅÄÄÄÄ“      ĄÄÄÄÄĮÄÄÄÄÄŁ      ĆÄÄÄÄÅÄÄÄÄÅÄÄÄÄ“
+³4 4³1 2³11 9³                        ³11 5³11 3³11 9³
+ĄÄÄÄĮÄÄÄĮÄÄÄÄŁ                        ĄÄÄÄÄĮÄÄÄÄĮÄÄÄÄŁ
+
+   a =: 2 3 4 $ 'abcdefghijklmnopqrstuvwx'
+
+   a                   mat a             $a
+abcd                abcd              2 3 4
+efgh                efgh
+ijkl                ijkl                 $ mat a
+                                      7 4
+mnop                mnop
+qrst                qrst
+uvwx                uvwx
+
+   
+   topleft 3 4$'a'
+ÅÄÄÄÄ
+³aaaa
+³aaaa
+³aaaa
+   (2 3;4 5) perim 6 10$'a'
+ŚÄÄÄÄĀÄÄÄÄÄæ
+³aaaaaaaaaa³
+³aaaaaaaaaa³
+Ćaaaaaaaaaa“
+³aaaaaaaaaa³
+³aaaaaaaaaa³
+³aaaaaaaaaa³
+ĄÄÄÄÄĮÄÄÄÄÄŁ
+   
+   ] t=: ({rc x) inside@:(take&.>)"2 x
+0 1 2³abc³0        
+3 4 5³   ³1        
+     ³   ³2        
+     ³   ³3        
+ÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄ
+ŚÄÄæ ³12 ³ŚÄĀÄÄĀÄÄæ
+³us³ ³   ³³0³1 ³2 ³
+³sr³ ³   ³ĆÄÅÄÄÅÄÄ“
+ĄÄÄŁ ³   ³³3³4 ³5 ³
+     ³   ³ĄÄĮÄÄĮÄÄŁ
+     ³   ³         
+     ³   ³ŚÄĀÄÄĀÄÄæ
+     ³   ³³6³7 ³8 ³
+     ³   ³ĆÄÅÄÄÅÄÄ“
+     ³   ³³9³10³11³
+     ³   ³ĄÄĮÄÄĮÄÄŁ
+   (rc x) perim t
+ŚÄÄÄÄÄĀÄÄÄĀÄÄÄÄÄÄÄÄÄæ
+³0 1 2³abc³0        ³
+³3 4 5³   ³1        ³
+³     ³   ³2        ³
+³     ³   ³3        ³
+ĆÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄ“
+³ŚÄÄæ ³12 ³ŚÄĀÄÄĀÄÄæ³
+³³us³ ³   ³³0³1 ³2 ³³
+³³sr³ ³   ³ĆÄÅÄÄÅÄÄ“³
+³ĄÄÄŁ ³   ³³3³4 ³5 ³³
+³     ³   ³ĄÄĮÄÄĮÄÄŁ³
+³     ³   ³         ³
+³     ³   ³ŚÄĀÄÄĀÄÄæ³
+³     ³   ³³6³7 ³8 ³³
+³     ³   ³ĆÄÅÄÄÅÄÄ“³
+³     ³   ³³9³10³11³³
+³     ³   ³ĄÄĮÄÄĮÄÄŁ³
+ĄÄÄÄÄÄĮÄÄÄĮÄÄÄÄÄÄÄÄÄŁ
+
+
+ +

Formatted Display

+ +x":y is a literal representation of y specified +by x. Positive elements of x specify +fixed-point notation, while negative +elements specify exponential notation. The left and right ranks are one; +that is, lists in the arguments are independently formatted. +The computation can be modelled as follows:
+ +

+fmtexp   =: {&'++-'@* , _3&{.@('00'&,)@":@|
+cexp     =: >:@(i.&'e') ({. , fmtexp@".@}.) ]
+cminus   =: '-'&((e.&'_' # i.@#)@]})
+larg     =: (+_20&*@(0&=))@-@(1&|)@|@".@(-.&' %e')
+nsprintf =: larg@[ cexp@cminus@":"1 ]
+psprintf =: ".@(-.&' %f')@[ ($&' '@(0&=)@<.@[ , cminus@":"1) ]
+sprintf  =: nsprintf`psprintf@.('f'&e.@[)
+
+wd       =: <.@|
+npstr    =: ' %- '&,@(,&'e')@(0.1&":)@(-1&<)@|
+ppstr    =: *@wd }. ' %'&,@(,&'f')@(0.1&":)
+pstr     =: npstr`ppstr@.(0&<:)
+
+jexp     =: >:@(i.&'e') ({. , ":@".@(-.&' +')@}.) ]
+jminus   =: '_'&((e.&'-' # i.@#)@]})
+stars    =: ]`{.@.(*@[)`($&'*'@[)@.(*@[*.(<#))
+c2j      =: stars ]`jexp@.('e'&e.)@jminus
+
+lb       =: (0&=@wd *. 0&<:)@{.
+thcell   =: (wd@[ <@c2j pstr@[ sprintf ])"0
+thorn2   =: (lb@[ }. ;@:thcell) " 1
+
+ +The model is divided into groups of verbs.

+ +sprintf is a limited model of sprintf in the C library, +applying to a string containing a single %e or %f conversion +specification and to a single number. +Thus, if embrace=:('{'&,)@(,&'}'), then:
+
+   embrace ' %0.3f' sprintf ^5            { 148.413}
+   embrace '%9.3f' sprintf ^_5            {    0.007}
+   embrace ' %- 0.3e' sprintf ^_5         {  6.738e-003}
+   embrace ' %- 9.3e' sprintf -^5         { -1.484e+002}
+   embrace ' %- 6.3e' sprintf -^_5        { -6.738e-003}
+
+pstr applies to the left argument of ": and produces +the necessary left argument to sprintf. For example: +
+    x          embrace pstr x
+
+   _12         { %- 11.0e}
+   _7.3        { %- 6.3e}
+   _0.3        { %- 0.3e}
+   0           { %0.0f}
+   0.3         { %0.3f}
+   7.3         {%7.3f}
+   12          {%12.0f}
+
+c2j and its constituents transform the result of sprintf +to follow J conventions, in the treatment of signs (jminus), +exponential notation (jexp), and overflow (stars).

+ +thorn2 is a model of the dyad ":. It works by +applying thcell to corresponding atoms of the arguments, +producing a list of boxes; the leading blank of the razed result is then +dropped or not, according to the value of lb on +the left argument.

+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojFiles.htm b/docs/ioj/iojFiles.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojFiles.htm @@ -0,0 +1,179 @@ + + + +An Implementation of J -- Program Files + + + + +

Program Files
+An Implementation of J

+ +
+
+
+
j.h
Global Definitions +
ja.h
Aliases for jt +
jc.h
Character Definitions +
je.h
Extern Declarations +
jerr.h
Error Codes +
js.h
SYS_ and friends +
jt.h
Definitions for jt +
jtype.h
Type Definitions +
+
+
a.h
Adverbs: Macros and Defined-Constants (for Adverbs and Conjunctions) +
a.c
Adverbs +
af.c
Adverbs: Fix +
ai.c
Adverbs: Inverse & Identity Functions +
aicap.c
Adverbs: I. +
am.c
Adverbs: Amend +
am1.c
Adverbs: a ind}z where z is sparse and ind is box a0;a1;a2;... +
amn.c
Adverbs: a ind}z where z is sparse and ind is <"1 integers +
ao.c
Adverbs: Oblique and Key +
ap.c
Adverbs: Prefix and Infix +
ar.c
Adverbs: Reduce (Insert) and Outer Product +
as.c
Adverbs: Suffix and Outfix +
au.c
Adverbs: Utilities +
+
+
c.c
Conjunctions +
ca.c
Conjunctions: Atop and Ampersand +
cc.c
Conjunctions: Cuts +
cd.c
Conjunctions: Differentiation and Integration +
cf.c
Conjunctions: Forks +
cg.c
Conjunctions: Gerunds ` and `: +
ch.c
Conjunctions: Hypergeometric Series +
cl.c
Conjunctions: L: and S: +
cp.c
Conjunctions: Power Operator ^: and Associates +
cr.c
Conjunctions: Rank Associates +
crs.c
Conjunctions: Rank on Sparse Arrays +
ct.c
Conjunctions: Taylor's Series +
cu.c
Conjunctions: Under and Each +
cv.c
Conjunctions: Variants (!.) +
cx.c
Conjunctions: Explicit Definition : and Associates +
+
+
d.c
Debug: Error Display +
dc.c
Debug: Function Call Information +
ds.c
Debug: Stops and Suspensions +
+
+
f.c
Format: ": Monad +
f2.c
Format: ": Dyad +
+
+
io.h
Input/Output +
i.c
Initializations +
io.c
Input/Output +
+
+
j.c
main(), Main Loop, & Global Variables +
+
+
k.c
Conversions Amongst Internal Types +
+
+
m.h
Memory Management +
m.c
Memory Management +
mbx.c
Memory-Mapped Boxed Arrays +
+
+
p.h
Parsing: Macros and Defined Constants +
p.c
Parsing; see APL Dictionary, pp. 12-13 & 38. +
pc.c
Parsing: Tacit Adverb/Conjunction Translator (11 : and 12 : ) +
pt.c
Parsing: Trace +
pv.c
Parsing: Tacit Verb Translator (13 : ) +
px.c
Execute and Associates +
+
+
r.c
Representations: Atomic, Boxed, and 5!:0 +
rl.c
Representations: Linear and Paren +
rt.c
Representations: Tree +
+
+
s.c
Symbol Table +
sc.c
Symbol Table: Function Call (unquote) +
sl.c
Symbol Table: Locales +
sn.c
Symbol Table: Names +
+
+
t.c
Table of Primitive Symbols +
+
+
u.c
Interpreter Utilities +
+
+
va.h
Verbs: Macros and Defined Constants for Atomic (Scalar) Verbs +
vasm.h
Verbs: Assembly Routines for Integer + * - with Overflow +
ve.h
Atomic Verbs +
vq.h
Rational Numbers +
vx.h
Extended Precision +
vz.h
Complex Numbers +
v.c
Verbs +
v0.c
Verbs: Polynomial Roots & Polynomial Evaluation +
v1.c
Verbs: Match Associates +
v2.c
Verbs: Primes and Factoring +
va1.c
Verbs: Monadic Atomic +
va2.c
Verbs: Atomic (Scalar) Dyadic +
va2s.c
Verbs: Atomic (Scalar) Dyadic Verbs on Sparse Arrays +
vb.c
Verbs: Boolean-Valued +
vbang.c
Verbs: ! +
vcant.c
Verbs: Transpose +
vcat.c
Verbs: Catenate and Friends +
vcomp.c
Verbs: Comparatives +
vd.c
Verbs: Domino +
ve.c
Verbs: Elementary Functions (Arithmetic, etc.) +
vf.c
Verbs: Fill-Dependent Verbs +
vfrom.c
Verbs: From & Associates. See Hui, Some Uses of { and }, APL87. +
vg.c
Verbs: Grades +
vgauss.c
Verbs: Gaussian Elimination +
vi.c
Verbs: Index-of +
visp.c
Verbs: Index-of on Sparse Arrays +
vm.c
Verbs: "Mathematical" Functions (Irrational, Transcendental, etc.) +
vo.c
Verbs: Box & Open +
vp.c
Verbs: Permutations +
vq.c
Verbs: Rational Numbers +
vs.c
Verbs: $. Sparse Arrays +
vt.c
Verbs: Take and Drop +
vx.c
Verbs: Extended Precision Integers +
vz.c
Verbs: Complex-Valued Scalar Functions +
+
+
w.h
Words +
w.c
Words: Word Formation +
wc.c
Words: Control Words +
wn.c
Words: Numeric Input Conversion +
ws.c
Words: Spelling +
+
+
x.h
Xenos: Macros and Defined Constants for !: +
x.c
Xenos aka Foreign: External, Experimental, & Extra +
x15.c
Xenos: DLL call driver +
xa.c
Xenos: Miscellaneous +
xb.c
Xenos: Binary Representation +
xd.c
Xenos: file directory, attributes, & permission +
xf.c
Xenos: Files +
xh.c
Xenos: Host Command Facilities +
xi.c
Xenos: Implementation Internals +
xl.c
Xenos: File Lock/Unlock +
xo.c
Xenos: File Open/Close +
xr.c
Xenos: Interface to regexp Regular Expressions Package +
xs.c
Xenos: Scripts +
xt.c
Xenos: time and space +
+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + diff --git a/docs/ioj/iojGloss.htm b/docs/ioj/iojGloss.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojGloss.htm @@ -0,0 +1,329 @@ + + + +An Implementation of J -- Glossary + + + + +

Glossary
+An Implementation of J

+ +
+
+ +An explanation is provided for significant names in the system. +Names spelled with majuscules denote defined +types (typedef) or #define +constants and macros; those spelled with minuscules denote +C functions and variables.

+ +Each entry has a name, its frequency of occurrence, +and a brief description.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              
A1157The data type of an array; the data type of BOX array elements
a1883The left argument of a verb
a0j19The complex atom 0j1
ainf14The floating point atom _
AN(x)759The n part of an array (the number of atoms in the value part)
apv(n,b,m)96The arithmetic progression vector b+m*i.n
AN(x)759The n part of an array; the number of atoms in the value part
AR(x)581The r part of an array; the rank of an array
AS(x)477The s part of an array; the shape of an array
ASSERT(p,e)822Signal error e if proposition p is not true
AT(x)733The t part of an array; the type of an array
B706The data type of B01 array elements
B01160The type of a Boolean array
bp(t)92The number of bytes per atom of type t
C566The data type of LIT array elements
cstr(s)93A string with value the characters in the 0-terminated string s
DO(n,stmt)905Execute n times the statement stmt, +with local variable i running from 0 to n-1
EPILOG(x)82Free all temporary storage used since the +last PROLOG, then return x as a result
F1(f)705Define f as a monadic verb or an adverb
F2(f)326Define f as a dyadic verb or a conjunction
GA(t,n,r,s)583Create an array of type t of rank r and +shape s, with n atoms
I1537The data type in C of a full-word integer
iv017,2-2, the integer vector 0
iv118,2-1, the integer vector 1
jt2557Points to a structure of all the global variables for a J instance
LIT566The type of a literal (character) array + (CHAR conflicts with C usage)
mtm44The empty matrix i.0 0
mtv73The empty vector i.0
neg122The integer atom _1
one98The Boolean atom 1
pie5The floating point atom p +(pi conflicts with C usage)
PROLOG85Establish a checkpoint for temporary storage usage
RE(x)220Return 0 if an error is signalled in executing x +
RZ(x)1537Return 0 if x is 0
sc(k)217   An integer atom with value k (equivalent to sc4(INT,k))
sc4(t,k)5An atom of type t with 4-byte value k
scc(c)17A literal atom with value c
scf(x)26A floating point atom with value x
str(n,s)52A string (literal list) of length n with value the characters +pointed to by s
two24The integer atom 2
v1(k)15The integer vector ,k
v2(a,b)72The integer vector a,b
vec(t,n,v)  81A vector of length n of type t, +with values pointed to by v
vi(x)45"Verify integer", convert x to integer
w3207The right argument of a verb
zero129The Boolean atom 0

+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojIndex.htm b/docs/ioj/iojIndex.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojIndex.htm @@ -0,0 +1,916 @@ + + + +An Implementation of J -- Glossary and Index + + + + +

Glossary and Index
+An Implementation of J

+ +
+
+ +An explanation is provided for significant names in the system. +Names spelled with majuscules denote defined +types (typedef) or #define +constants and macros; those spelled with minuscules denote +C functions and variables.

+ +Each entry has a name, its frequency of occurrence, +and a brief description.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              
A1157the data type of an array; +the data type for a BOX array
a1855the left argument of a verb
a0j19the complex atom 0j1
adverb
AF58the data type of a function that takes array arguments +and returns an array result
agreement
AH16the number of words in the header of an array, +excluding the shape
ainf14the floating point atom _
AN(x)759the n part of an array (the number of atoms in the value part)
APL A Programming Language
apv(n,b,m)96the arithmetic progression vector b+m*i.n
AR(x)581the r part of an array; the rank of an array
array
AS(x)477the s part of an array; the shape of an array
ASCII
asgn101 if assignment is last operation on a user input line
assembly code
ASSERT(p,e)822signal error e if proposition p is not true
AT(x)733the t part of an array; the type of an array
atomic representation
atomic verb
 
B706the data type for a B01 array
B01160Boolean array type +(BOOL conflicts with C usage)
Bernecky, Robert
Berry, Paul
BOX115boxed array type
box drawing character
boxed display
boxed representation
bp(t)92the number of bytes per atom of type t
Burke, Chris
 
C566the data type for a LIT array
CMPX83complex number array type
comparatives
comparison tolerance
conjunctions
constants
conventional function a function that returns zero on zero arguments and on errors
cstr(s)93a string with value the characters in the 0-terminated string s
 
df1(w,self)90apply the monad of the verb self
df2(a,w,self)67apply the dyad of the verb self
dictionary
display
DO(n,stmt)905execute n times the statement stmt, +with local variable i running from 0 to n-1
ds(s)151the primitive whose ID is s
 
enqueue(a,w)3prepare sentence w for parsing; + a is wordil(w)
EPILOG(x)82free temporary storage used since the +last PROLOG, then return x
error handling
evinit3initialize the error messages
evm7a list of the error messages
 
F1(f)705define f as a monadic verb or an adverb
F1RANK(r,f1,self)52implements monadic rank r on the verb self whose +monad is f1
+F2(f)326define f as a dyadic verb or a conjunction
F2RANK(l,r,f2,self)30implements dyadic ranks l and r on the +verb self whose dyad is f2
Falkoff, Adin
fit the conjunction !. that produces +variants of a verb
FL115floating point array type
folk(x,y,z)53implements a trident (fork conflicts with UNIX usage)
fork
foreign conjunction
format
formatted display
free(x) C library routine; frees memory block x previously +allocated by malloc
fuzz13a system parameter used in domain tests
 
GA(t,n,r,s)583create an array of type t of rank r and +shape s, with n atoms
gerund
global variables
 
header the non-value parts of an array, offset, flag, max bytes, type, etc.
hook
Hui, Roger
 
I1537the data type of an INT array
ID a one-byte value that identifies a primitive
iden(w)6the identity function for verb w
identity
immediate execution
immex(w)7"immediate execution" on w, +displaying the result if the last operation is not assignment
incunabulum
inflect
in-place
INT390integer array type
inv(w)21the obverse for verb w
invamp3the obverse for verb w which is of +the form x&v or v&y
invf2a 2-row table of primitives whose obverses are also primitive
inverse
+iv017,2-2, the integer vector 0
iv118,2-1, the integer vector 1
Iverson, Eric
Iverson, Kenneth E.
 
J606the data type for jt
jerr104the current error number, or 0 if no current error
jsignal(e)24signal error number e
jt2557points to a structure of all the global variables for a J instance
 
Kiln Farm
 
linear representation
LIT566literal (character) array type +(CHAR conflicts with C usage)
 
malloc(n) C library routine; allocate n bytes of memory
marker
memory management
McDonnell, Eugene
McIntyre, Donald
mtm44the empty matrix i.0 0
mtv73the empty vector i.0
 
name resolution
NB. comment
neg122the integer atom _1
NEVM9the number of error messages
nouns
numeric display
 
obverse
one98the Boolean atom 1
 
parsing
pdef113initialize the pst table
+pie5the floating point atom p +(pi conflicts with C usage)
pinit3initialize the pst table
PREF1
PREF2
program files
PROLOG85establish a checkpoint for temporary storage usage
pst16primitive symbols definition table
 
queue data structure for parsing
 
R2510an alias for return
rank
rank1ex(w,fs,r,f1)16execute fs"r w; f1 is the monad of fs
rank2ex(a,w,fs,l,r,f2)29execute a fs"(l,r) w; f2 is the dyad of fs
ravel the atoms of an array, in ravelled (row major) order
+RE(x)220return 0 if an error is signalled in executing x +
recognized phrase
representation
rhematic rules
+RZ(x)1537return 0 if x is 0
 
+sc(k)217an integer atom with value k; equivalent to sc4(INT,k)
sc4(t,k)5an atom of type t with 4-byte value k
scc(c)17a literal atom with value c
+scf(x)26a floating point atom with value x
self148an array representing the current verb
special code
spell5a 3-row table defining the primitive words
spellin(n,s)5the ID of the word in the length-n string s
spelling
spellout(c)19spell out the word whose ID is c
stack
str(n,s)52a string (literal list) of length n with value the characters +pointed to by s
SYMB11symbol table array type
symbis(a,w,g)10assign the name a to array w in symbol table g
symbol table
symbrd(w)10retrieve the value for name w from the current symbol table
system summary
 
test scripts
thorn1(w)18implements the monad ":
tokens(w)16tokenize sentence w; +convert w into a parse queue
tolerance
tpop(x)15free temporary storage used since the checkpoint x
trains
tree representation
tstack
two24the integer atom 2
 
V88the data type of a VERB array
v1(k)15the integer vector ,k
+v2(a,b)72the integer vector a,b
value the atoms of an array, in ravelled (row major) order
variant
VAV(x)191the value part of a VERB array
vec(t,n,v)81a vector of length n of type t, +with values pointed to by v
VERB185verb array type; the type of an array representing a verb
verb
vi(x)45"verify integer", convert x to integer
 
w3207the right argument of a verb
Whitney, Arthur
word formation
word parallel
wordil(w)5the words in sentence w as a 2-column table of index and length
 
X130the data type for an XNUM array
XNUM107extended-precision integer array type
 
Z130the data type for a CMPX array
zero129the Boolean atom 0

+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojIntro.htm b/docs/ioj/iojIntro.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojIntro.htm @@ -0,0 +1,109 @@ + + + +An Implementation of J -- Introduction + + + + +

Introduction
+An Implementation of J

+ +
+ + +
    +
  • main +
      +
    • jinit2 +
    • immloop +
        +
      • prompt +
      • jgets +
      • immex +
          +
        • tokens +
            +
          • wordil +
          • enqueue +
          +
        • parse +
            +
          • monad +
          • dyad +
          • adv +
          • conj +
          • trident +
          • bident +
          • is +
          • punc +
          • move +
          +
        • jpr +
        +
      • tpop +
      +
    +
+
+The system is organized as diagrammed above. The main +function main calls jinit2 for initializations, +then immloop ("immediate execution" loop), which repeats the +following steps:

+ +prompt and jgets prompt and accept an input sentence.

+ +immex is the heart of the execution loop. The argument is a +string of the input sentence. The processing is divided into three parts: + +
    +
  • tokens — word formation — applies the rhematic rules to +partition the sentence into words. +
  • parse interprets the sentence according to the parsing rules. +Parsing is controlled by a table of (pattern,action) pairs; the eleven possible +actions are embodied as the function listed under parse in the diagram. +
  • jpr displays the result of the sentence. +
+ +Finally, tpop frees the temporary storage used in an iteration.

+ +The fundamental data structure is the APL array (an object of +data type A), used to represent all the possible objects in J. +Most functions in the implementation accepts arrays as argument and return +them as result. Functions tend to be short and compact, and functions +which implement J primitives are used freely. Extensive use is made of +C preprocessor definitions and macros. Although the implementation +language is C, the programming style is unmistakably APL.

+ +This document is organized along the lines of the dictionary: +Chapter 1 describes the +interpretation of a sentence. +Chapters 2, 3, and 4 describe +nouns, +verbs, and +adverbs and conjunctions. +Chapter 5 presents alternative representations. +Chapter 6 describes display. +Chapter 7, the final chapter, describes +comparisons.

+ +The remainder of the document contains various useful bits. +In particular, the Appendix contains a +system summary, +a means of quickly locating a primitive +in the program files.

+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + diff --git a/docs/ioj/iojNoun.htm b/docs/ioj/iojNoun.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojNoun.htm @@ -0,0 +1,517 @@ + + + +An Implementation of J -- Nouns + + + + +

Nouns
+An Implementation of J

+ +Arrays
+Types
+Memory Management
+Global Variables

+ +
+
+ +Arrays

+ +The fundamental data structure is the array, that is, an object of +the C data type A defined in file jtype.h:
+ +
+   typedef long I;
+   typedef struct {I k,flag,m,t,c,n,r,s[1];}* A;
+
+ +All objects, whether numeric, literal, or boxed, whether +noun, verb, adverb, or conjunction, are represented by arrays. +For example, the string 'Cogito, ergo sum.', the +atom 1.61803, and the table 11+i.3 4 are +represented thus:

+
+     k   flag  m    t    c    n    r   s[0]
+   ŚÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄæ
+   ³  32³   0³  20³CHAR³   2³  17³   1³  17³Cogi³to, ³ergo³ sum³.   ³
+   ĄÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄŁ
+
+     k   flag  m    t    c    n    r
+   ŚÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄæ
+   ³  28³   0³   8³  FL³   2³   1³   0³  1.61803³
+   ĄÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄŁ
+
+     k   flag  m    t    c    n    r   s[0] s[1]
+   ŚÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀ
+   ³  36³   0³  48³ INT³   2³  12³   2³   3³   4³  11³  12³  13³
+   ĄÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮ
+                       ĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄĀÄÄÄÄæ
+                       ³  14³  15³  16³  17³  18³  19³  20³  21³  22³
+                       ĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄĮÄÄÄÄŁ
+
+ +The parts of an array, and macros for manipulating them, +are as follows:

+ + + + + + + + + + + + + + + + +
    Part          Macro             Description
k AK offset of ravel with respect to byte 0 of the array
flag AFLAG flag
m AM maximum # of bytes in ravel
t AT type
c AC reference count
n AN # of atoms in ravel
r AR rank
s AS pointer to shape
AV "ravel" or "value", pointer to atoms in ravelled order

+ +An array has a "header" and a "value". The header are the +parts k, flag, m, t, and so forth, +including the shape s, which consists of r +integers whose product equals n. +The value, the atoms of the array in ravelled (row major) order, +usually follow immediately after s, but can be +separate from the header, according to the value in the k part. +Setting the parts of an array incorrectly, or exceeding the bounds +of the array specified by these parts, almost always lead to +erratic behaviour and catastrophic failure.

+ +The macros AK, AFLAG, AM, AT, + AC, AN, and AR denote "fullword" +integers and may occur on the left or right of an assignment +(i.e. they are "lvalues".) AS is an integer +pointer. AV is also an integer pointer, and must be cast +to a C data type appropriate to the type of array. +(See Types.)

+ +All arrays are created using the macro GA in file j.h. +The statement
+
+   GA(xyz,t,n,r,s);
+
+creates an array named xyz of type t and +rank r, having n atoms and shape s. +If the rank is 0, s is ignored; if the rank is 1, again s +is ignored, and the shape is set to n. Otherwise, +if s is nonzero, GA initializes the shape from +the r integers pointed to by s, and +if s is 0, the shape is not initialized +and must be initialized subsequently. GA returns zero +if the array can not be created.

+ +For example, the arrays diagrammed above can be created as follows, +under the names ces, phi, and m:
+ +
+   typedef char   C;
+   typedef double D;
+
+   A ces,m,phi; I j,*s,*v;
+
+   GA(ces,CHAR,17,1,0);
+   memcpy((C*)AV(ces),"Cogito, ergo sum.",(size_t)17);
+
+   GA(phi,FL,1,0,0);
+   *(D*)AV(phi)=1.61803;
+
+   GA(m,INT,12,2,0);
+   s=AS(m); *s=3; *(1+s)=4;
+   v=AV(m); for(j=11;23>j;++j)*v++=j;
+
+ +The following utilities (file u.c) and +array constants (file i.c) are +convenient for working with simple arrays. +The frequency of use gives a sense of their utility.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
       FacilityFreq.      Description
 
sc(I k)217   An integer atom with value k (equivalent to sc4(INT,k))
sc4(I t,I k)5An atom of type t with 4-byte value k
scf(D x)26A floating point atom with value x
scc(C x)17A literal atom with value c
apv(I n,I b,I m)96The arithmetic progression vector b+m*i.n
str(I n,C*s)52A string (literal list) of length n with value the characters +pointed to by s
cstr(C*s)93A string with value the characters in the 0-terminated string s
v2(I a,I b)72The integer vector a,b
v1(I k)15The integer vector ,k
vec(I t,I n,void*v)  81A vector of length n of type t, +with values pointed to by v
 
zero1290
one981
two242
neg122_1
pie51p1 (pi conflicts with C usage)
a0j190j1
ainf14_
iv017,2-2
iv118,2-1
mtv73i.0
mtm44i.0 0

+ +For example, the arrays diagrammed above +can be created by str(17L,"Cogito, ergo sum.") +or cstr("Cogito, ergo sum."), +scf(1.61803), and +reshape(v2(3L,4L),apv(12L,11L,1L)).

+ +
+ +

Types

+ +If x is an array, its type AT(x) specifies +how the atoms starting at AV(x) are to be interpreted. +In C programming terms, AV(x) must be cast to a +pointer of the appropriate C type:
+

+           C Data
+   AT(x)    Type                    Description
+
+   B01       B          Boolean (BOOL has a name conflict)                    
+   LIT       C          literal (character; CHAR has a name conflict)        
+   INT       I          integer                     
+   FL        D          double (IEEE floating point)
+   CMPX      Z          complex                   
+   BOX       A          boxed                      
+   XNUM      X          extended precision integer
+   RAT       Q          rational number          
+
+   SB01      P          sparse boolean        
+   SLIT      P          sparse literal (character)
+   SINT      P          sparse integer       
+   SFL       P          sparse floating point
+   SCMPX     P          sparse complex        
+   SBOX      P          sparse boxed             
+
+   VERB      V          verb                    
+   ADV       V          adverb                  
+   CONJ      V          conjunction   
+         
+   ASGN      I          assignment              
+   MARK      I          marker     
+   SYMB      L          locale (symbol table)     
+   CONW      CW         control word             
+   NAME      NM         name                     
+   LPAR      I          left  parenthesis        
+   RPAR      I          right parenthesis       
+
+For example, if x is literal and s=(C*)AV(x), +then s[i] is character i of x. The C data types +in the table are all typedef's found in file jtype.h; +the data type V is explained in the +Verbs section.

+ +Types are fullword integers, and are powers of 2 to permit convenient +tests for "composite" types. For example, if:
+ +
+   #define NUMERIC (B01+INT+FL+CMPX+XNUM+RAT+SB01+SINT+SFL+SCMPX)
+   #define NOUN    (NUMERIC+LIT+SLIT+BOX+SBOX)
+
+Then the phrase NUMERIC&AT(x) tests for numeric arrays, +and the phrase NOUN&AT(x) tests for nouns. Such comparisons +play a key role in the parser.

+ +A numeric array is accepted as argument by a primitive, +regardless of its type, if it is mathematically within the domain +of the primitive. For example, a primitive with integral domain +would accept integers in an array of type FL, CMPX, +and B01, and of course INT. +(This analytic property does not extend to functions internal to +the implementation.) Functions in the file k.c convert between numeric types. +A converted result is an array of the target type equal to the +argument within fuzz. +The following functions are available:

+ + + + + + + + + + + + + + + + + + +
   cvt(t,x)    Convert x to type t; signal error if not possible
pcvt(t,x)Convert x to type t; return x if not possible
icvt(t,x)Convert floating x to INT if the values are in range; + otherwise just return x
bcvt(t,x)Convert x to the "lowest" type

+ +The utility bp in file u.c applies to a type, +and returns the number of bytes per atom of that type. Thus bp(INT) +is 4; bp(AT(x)) is the number of bytes per atom of x; +and 28+(4*AR(x))+AN(x)*bp(AT(x)) is the number of bytes +required by x — 4 bytes each +for k,flag,m,t,c,n,r; +4 bytes each for the AR(x) elements of the shape; +and bp(AT(x)) bytes each for AN(x) atoms.

+ +The atoms of a boxed array are pointers to other arrays, and are +accessible through (A*)AV(x), as the following +example illustrates. aib applies to a boxed array x, +and returns the number of atoms in each box of x:
+ +
+   #define R  return
+
+   A aib(A x){A*u,z;I j,*v;
+    GA(z,INT,AN(x),AR(x),AS(x));       /* 1 */
+    u=(A*)AV(x); v=AV(z);              /* 2 */
+    for(j=0;AN(x)>j;++j)*v++=AN(*u++); /* 3 */
+    R z;
+   }
+
+ +Line 1 creates an integer array z having the same rank +and shape as x. +Line 2 initializes pointer values u and v +for traversing x and z . +Line 3 runs through the atoms of x, through u, +and records the number of atoms in each. Since the data type of u +is A*, the data type of *u is A and +are subject to AN, AT, AV, etc.

+ +
+ +

Memory Management

+ +When an array is created, malloc is +called to obtain the requisite storage; +when this storage is no longer needed, free is +called to return it to the +underlying system. No "garbage collection" is done. The performance +of this strategy is adequate on modern virtual memory systems. +To facilitate the implementation of alternative strategies, +the use of malloc and free is limited to a single +instance of each, in the file m.c.

+ +The reference count of an array is incremented when it is assigned +a name, directly or indirectly, and is decremented when the name is +reassigned or erased; when the reference count of an array reaches 0, +its storage is freed.

+ +When an array is created, a pointer to it is entered in a "temp stack" +(tstack in file m.c.) +A temp is an array on this stack with a reference count of one. +The temp stack plays an important role in the +main execution loop. +In an iteration of the loop,

+ +   • The top of the temp stack is recorded;
+   • A line of user-input is executed; and
+   • Temps from the current top-of-stack to the old top-of-stack +recorded above, are freed.

+ +This device permits functions to be written without explicit +memory management code. For example, the monad ~. is written:
+ +

+   F1(jtnub){R repeat(nubsieve(w),w);}
+
+ +And nub need not be concerned with temps used +in repeat or nubsieve, +because they are accounted for in the main loop.

+ +On the other hand, a function may account for temps: +On entry into the function, the current top-of-stack is recorded; +on exit, temps are freed down to the recorded point. +(These actions are mediated by the +macros PROLOG and EPILOG.) +Whether a function accounts for temps does not affect the logic of +functions that it calls, nor functions that call it.

+ +
+ +

Global Variables

+ +The only global variables used in the system are +constants which are assigned exactly once. +(For example, the array constant zero and the internal complex +number zeroZ.) All other variables non-local to functions +are accessed through the parameter jt.

+ +jt has defined type J, a pointer to +a struct defined in file jt.h. +Nearly all functions in the system has jt +as its first function argument, +and all such functions have the letters jt as a prefix in their names. +The file ja.h defines aliases for these names, so that a call to a +function jtxyz(jt,a,w,h) is +actually written as xyz(a,w,h). +For example, the conjunction &, +described in Adverbs and Conjunctions, +is implemented by a function +defined and declared as jtamp, +having prototype A jtamp(J jt,A a,A w), but calls to this +function are written as amp(a,w), +and discussions on this function refer to it as amp.

+ +jt makes it possible to execute multiple instances +of J in the same process.

+ +
+


+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojRep.htm b/docs/ioj/iojRep.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojRep.htm @@ -0,0 +1,526 @@ + + + +An Implementation of J -- Representation + + + + +

Representation
+An Implementation of J

+ +Atomic Representation
+Boxed Representation
+Tree Representation
+Linear Representation

+ +
+
+ +Atomic Representation

+ +5!:1 is a verb that applies to a boxed name, and produces +the atomic representation of the named object. +Gerunds (results of the ` conjunction) +are arrays of atomic representations. +The adverb 5!:0 defines an object from its representation.

+ +The atomic representation is a boxed list of two boxes:
+ + + + + + +
   noun symbol value
verb symbol arguments
adverb symbol arguments
conjunction        symbol arguments

+ +The symbol is a string computed by +function
spellout in file ws.c. +For a primitive with an assigned symbol +(for example + or /.), +the symbol is simply that word; for those without, the symbol is +one of the following:

+ +
+   '0'           noun
+   '2'           hook
+   '3'           fork
+   '4'           bonded conjunction
+   '5'           2-element a-train or c-train
+   '6'           3-element a-train or c-train
+
+ +The "value" in the representation of a noun is just the noun itself; +arguments in the representation of a verb, adverb, or conjunction are +themselves atomic representations. If an object is uniquely identified +by the symbol alone, then the second box is elided, and the representation +is the boxed symbol alone.

+ +The following examples illustrate atomic representation:

+
+   ar=: 5!:1
+
+   plus=: +          sum=: +/          mean=: +/ % #
+   ar <'plus'        ar <'sum'         ar <'mean'
+ŚÄæ               ŚÄÄÄÄÄÄÄæ         ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ
+³+³               ³ŚÄĀÄÄÄæ³         ³ŚÄĀÄÄÄÄÄÄÄÄÄÄÄÄÄæ³
+ĄÄŁ               ³³/³ŚÄæ³³         ³³3³ŚÄÄÄÄÄÄÄĀÄĀÄæ³³
+                  ³³ ³³+³³³         ³³ ³³ŚÄĀÄÄÄæ³%³#³³³
+                  ³³ ³ĄÄٳ³         ³³ ³³³/³ŚÄæ³³ ³ ³³³
+                  ³ĄÄĮÄÄÄŁ³         ³³ ³³³ ³³+³³³ ³ ³³³
+                  ĄÄÄÄÄÄÄÄŁ         ³³ ³³³ ³ĄÄٳ³ ³ ³³³
+                                    ³³ ³³ĄÄĮÄÄÄŁ³ ³ ³³³
+                                    ³³ ³ĄÄÄÄÄÄÄÄĮÄĮÄŁ³³
+                                    ³ĄÄĮÄÄÄÄÄÄÄÄÄÄÄÄÄŁ³
+                                    ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ
+   +`(+/)`(+/ % #)
+ŚÄĀÄÄÄÄÄÄÄĀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ
+³+³ŚÄĀÄÄÄæ³ŚÄĀÄÄÄÄÄÄÄÄÄÄÄÄÄæ³
+³ ³³/³ŚÄæ³³³3³ŚÄÄÄÄÄÄÄĀÄĀÄæ³³
+³ ³³ ³³+³³³³ ³³ŚÄĀÄÄÄæ³%³#³³³
+³ ³³ ³ĄÄٳ³³ ³³³/³ŚÄæ³³ ³ ³³³
+³ ³ĄÄĮÄÄÄŁ³³ ³³³ ³³+³³³ ³ ³³³
+³ ³       ³³ ³³³ ³ĄÄٳ³ ³ ³³³
+³ ³       ³³ ³³ĄÄĮÄÄÄŁ³ ³ ³³³
+³ ³       ³³ ³ĄÄÄÄÄÄÄÄĮÄĮÄŁ³³
+³ ³       ³ĄÄĮÄÄÄÄÄÄÄÄÄÄÄÄÄŁ³
+ĄÄĮÄÄÄÄÄÄÄĮÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ
+   a=: 5             xenos=: !:
+   ar <'a'           ar <'xenos'       ar <'ar'
+ŚÄÄÄÄÄæ           ŚÄÄæ              ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ
+³ŚÄĀÄæ³           ³!:³              ³ŚÄÄĀÄÄÄÄÄÄÄÄÄÄÄÄÄæ³
+³³0³5³³           ĄÄÄŁ              ³³!:³ŚÄÄÄÄÄĀÄÄÄÄÄæ³³
+³ĄÄĮÄŁ³                             ³³  ³³ŚÄĀÄæ³ŚÄĀÄæ³³³
+ĄÄÄÄÄÄŁ                             ³³  ³³³0³5³³³0³1³³³³
+                                    ³³  ³³ĄÄĮÄŁ³ĄÄĮÄŁ³³³
+                                    ³³  ³ĄÄÄÄÄÄĮÄÄÄÄÄŁ³³
+                                    ³ĄÄÄĮÄÄÄÄÄÄÄÄÄÄÄÄÄŁ³
+                                    ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ
+   lgamma=: ^.@!@<:
+   ar <'lgamma'
+ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ
+³ŚÄĀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ³
+³³@³ŚÄÄÄÄÄÄÄÄÄÄĀÄÄæ³³
+³³ ³³ŚÄĀÄÄÄÄÄÄæ³<:³³³
+³³ ³³³@³ŚÄÄĀÄæ³³  ³³³
+³³ ³³³ ³³^.³!³³³  ³³³
+³³ ³³³ ³ĄÄÄĮÄŁ³³  ³³³
+³³ ³³ĄÄĮÄÄÄÄÄÄŁ³  ³³³
+³³ ³ĄÄÄÄÄÄÄÄÄÄÄĮÄÄŁ³³
+³ĄÄĮÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ³
+ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ
+
+
+ +Boxed Representation

+ +5!:2 is a verb that applies to a boxed name, and produces +the boxed representation of the named object. The representation +can be modelled as follows:

+ +
+ar     =: 5!:1
+boxed  =: 32&=@(3!:0)
+oarg   =: >@(1&{)
+
+bxroot =: (<1 0)&C.@,`] @. (e.&(,&.>'0123456789')@[)
+
+bxx    =: {. bxroot bx&.>@oarg
+bxgl   =: {. bxroot (bxx&.>@{. , bx &.>@}.)@oarg
+bxgr   =: {. bxroot (bx &.>@{. , bxx&.>@}.)@oarg
+bxg    =: bxgr`bxgl`bxx @. (i.&(<,'`')@oarg)
+bxtil  =: bxx`(oarg@>@{.@oarg) @. ((<,'0')&=@{.@>@{.@oarg)
+bxcase =: oarg`bxgl`bxgl`bxg`bxtil`bxx @. ((;:'0@.`:4~')&i.@{.)
+bx     =: ]`bxcase @. boxed
+
+brep   =: ,@<`[ @. boxed @ bx @ > @ ar
+
+   brep <'brep'
+ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĀÄĀÄÄæ
+³ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĀÄĀÄæ³@³ar³
+³³ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĀÄĀÄÄæ³@³>³³ ³  ³
+³³³ŚÄÄÄÄÄÄÄÄÄÄÄĀÄÄĀÄÄÄÄÄæ³@³bx³³ ³ ³³ ³  ³
+³³³³ŚÄÄÄÄÄÄÄĀÄæ³@.³boxed³³ ³  ³³ ³ ³³ ³  ³
+³³³³³ŚÄĀÄĀÄæ³[³³  ³     ³³ ³  ³³ ³ ³³ ³  ³
+³³³³³³,³@³<³³ ³³  ³     ³³ ³  ³³ ³ ³³ ³  ³
+³³³³³ĄÄĮÄĮÄŁ³ ³³  ³     ³³ ³  ³³ ³ ³³ ³  ³
+³³³³ĄÄÄÄÄÄÄÄĮÄŁ³  ³     ³³ ³  ³³ ³ ³³ ³  ³
+³³³ĄÄÄÄÄÄÄÄÄÄÄÄĮÄÄĮÄÄÄÄÄŁ³ ³  ³³ ³ ³³ ³  ³
+³³ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĮÄĮÄÄŁ³ ³ ³³ ³  ³
+³ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĮÄĮÄŁ³ ³  ³
+ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĮÄĮÄÄŁ
+
+ +The model is divided into groups of verbs. +The first group are utilities:
+ + + + + + + + + + + + + +
    ar             atomic representation
boxed1 if boxed
oargopen the second element of the list argument
+
+ +bxroot produces an infix representation from a +root r and its list of arguments a. +If r is a digit, it denotes a primitive without an assigned word +(e.g. '3' denotes a fork; +see Atomic Representation), +and the result of bxroot is a; +otherwise, r bxroot a produces:
+ + + + + + + + + + + + + + +
    a,rif one argument
({.a),r,(}.a)  if two arguments
rif no arguments (primitive)
+
+ +The other verbs named with the bx prefix apply to the +opened atomic representation, and embody logic to effect "nice" +displays for various special cases. The agenda items +in bxcase are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ID      Agenda
0      oarg   noun (leaf)
@.bxglgerundial left subtree
`:bxglgerundial left subtree
4bxgbonded conjunction; gerundial left or right subtree
~bxtilpossible instance of evoke
otherbxxnone of the above
+
+ +brep is a model of 5!:2.

+ +
+ +

Tree Representation

+ +5!:4 is a verb that applies to a boxed name, and produces a literal +table of the tree representation of the named object. Thus:

+ +

+   tree=: connect @ > @ (,.&.>/) @ ('0'&root ; ]) @ (tr@>@ar)
+   5!:4 <'tree'
+                        ŚÄ connect     
+                  ŚÄ @ ÄĮÄ >           
+            ŚÄ @ Ä“               ŚÄ ,.
+            ³     ĄÄ / ÄÄÄ &. ÄÄÄÄĮÄ > 
+            ³                          
+      ŚÄ @ Ä“           ŚÄ '0'         
+      ³     ³     ŚÄ & ÄĮÄ root        
+      ³     ĄÄÄÄÄÄÅÄ ;                 
+      ³           ĄÄ ]                 
+ÄÄ @ Ä“                                
+      ³           ŚÄ tr                
+      ³     ŚÄ @ ÄĮÄ >                 
+      ĄÄ @ ÄĮÄ ar                      
+
+ +The tree representation can be modelled as follows:

+ +
+ar      =: 5!:1
+lr      =: 3 : '5!:5 <''y.'''
+boxed   =: 32&= @ (3!:0)
+mt      =: 0&e.@$
+oarg    =: >@(1&{)
+shr     =: |.!.''
+shl     =: 1&(|.!.'')
+mat     =: (1 1&}.)@(_1 _1&}.)@":@<
+boxc    =: {. 9!:6 ''
+dash    =: 10{boxc
+
+extent  =: (+./\ *. +./\.) @ (' '&~:) @: ({."1)
+limb1   =: 1&|.@$ 1&~: }. (10 6 0{boxc)&,@($&(9{boxc))
+limb    =: -@(i.&1)@[ |. #@[ {. limb1@]
+pfx     =: (limb +/)@extent ,. ]
+pad     =: [ {. ] ,. dash&=@({:"1)@] {  ' '&,:@($&dash)@(-&{: $)
+take    =: pad`($&' '@[) @. (mt@])
+rc      =: #@>@{."1 ; >./@:({:@$@>)
+kernt   =: (0{boxc)&=@shl@[ *. ' '&~:@]
+kernb   =: (6{boxc)&=@] *. ' '&~:@shl@[
+kern    =: (<0 0)&{&>"2 (kernt +./"1@:+. kernb) (<_1 0)&{&>"2
+gap     =: ,&.>"_1 {&((0 1$' ');1 1$' ')@kern
+graft   =: (pfx&.>@{. 0} ]) @ (,&.>/) @ gap @ ({@rc take&.> ])
+
+lab     =: ,: @ (2&|.) @ ((' ',dash,dash,' ')&,)
+label   =: lab`((,.dash)&[) @. (e.&'0123456789'@{.)
+center  =: ((i.&1) -@+ <.@-:@(+/))@] |. #@] {. [
+root    =: label@[ center extent@>@{.@]
+
+leaf    =: ,@<@(((,:dash,' ')&[ center $&1@#) ,. ])@mat@":
+
+trx     =: >@{. (root ; ]) graft@:(tr@>)@oarg
+trgl    =: >@{. (root ; ]) graft@:(trx@>@{. , tr @>@}.)@oarg
+trgr    =: >@{. (root ; ]) graft@:(tr @>@{. , trx@>@}.)@oarg
+trg     =: trgr`trgl`trx @. (i.&(<,'`')@oarg)
+trtil   =: trx`(leaf@oarg@>@{.@oarg) @. ((<,'0')&=@{.@>@{.@oarg)
+trnoun  =: leaf @ lr @ oarg
+trcase  =: trnoun`trgl`trgl`trg`trtil`trx @. ((;:'0@.`:4~')&i.@{.)
+tr      =: leaf`trcase @. boxed
+
+rep     =: [. & (((# i.@#)@,@) (@])})
+right   =: (5{boxc) rep (e.&(9{boxc) *. shr"1@(e.&dash))
+cross   =: (4{boxc) rep (e.&(5{boxc) *. shl"1@(e.&dash))
+left    =: (3{boxc) rep (e.&(9{boxc) *. shl"1@(e.&dash))
+bot     =: (7{boxc) rep (e.&(6{boxc) *. shr"1@(e.&dash))
+connect =: bot @ left @ cross @ right
+
+tree    =: connect @ > @ (,.&.>/) @ ('0'&root ; ]) @ (tr@>@ar)
+
+ +The model is divided into groups of definitions +(which are verbs unless indicated otherwise). +The first group are utilities:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ar        atomic representation
boxed1 if boxed
mt1 if empty
oargopen the second element of the list argument
shrshift right
shlshift left
mata literal matrix image of the argument
boxc(noun) box drawing characters
dash(noun) the "dash" in the set of box drawing characters

+ +A "generational tree" (GT) is a list of boxed literal +tables having the same number of rows, such that nodes at the same depth +are in the same box. For example, the GT for tree +is:
   ŚÄÄÄÄÄÄĀÄÄÄÄÄÄĀÄÄÄÄÄÄĀÄÄÄÄÄÄĀÄÄÄÄÄÄÄÄÄÄĀÄÄÄÄÄæ
+   ³      ³      ³      ³      ³ŚÄ connect³     ³
+   ³      ³      ³      ³ŚÄ @ ijĄÄ >      ³     ³
+   ³      ³      ³ŚÄ @ ij³     ³          ³ŚÄ ,.³
+   ³      ³      ³³     ³ĄÄ / ijÄÄ &. ÄÄÄijĄÄ > ³
+   ³      ³      ³³     ³      ³          ³     ³
+   ³      ³ŚÄ @ ij³     ³      ³ŚÄ '0'    ³     ³
+   ³      ³³     ³³     ³ŚÄ & ijĄÄ root   ³     ³
+   ³      ³³     ³ĄÄÄÄÄij³Ä ;  ³          ³     ³
+   ³      ³³     ³      ³ĄÄ ]  ³          ³     ³
+   ³ÄÄ @ ij³     ³      ³      ³          ³     ³
+   ³      ³³     ³      ³ŚÄ tr ³          ³     ³
+   ³      ³³     ³ŚÄ @ ijĄÄ >  ³          ³     ³
+   ³      ³ĄÄ @ ijĄÄ ar ³      ³          ³     ³
+   ĄÄÄÄÄÄÄĮÄÄÄÄÄÄĮÄÄÄÄÄÄĮÄÄÄÄÄÄĮÄÄÄÄÄÄÄÄÄÄĮÄÄÄÄÄŁ
+
+ +graft is the main verb in the next group. +The argument is a table whose rows are GTs +for the nodes at the same depth. +The result is a GT.

+ +root accepts a string left argument and a GT right argument. +The result is a literal matrix +with the string centered relative to the GT.

+ +leaf computes a unitary (single-element) GT from its argument.

+ +tr applies to the opened atomic representation of an object +and produces a GT. The verbs named with the tr prefix embody +logic to effect "nice" displays for various special cases. +The agenda items in trcase are:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    
ID            Agenda
0        leaf@oarg   noun (leaf)
@.trglgerundial left subtree
`:trglgerundial left subtree
4trgbonded conjunction; gerund left or right
~trtilpossible instance of evoke
othertrxnone of the above

+ +rep is a conjunction whose left argument is +a single literal c and whose right argument is +a proposition p, +deriving a verb such that the phrase c rep p y +replaces with c the positions +in y marked by p y. +connect substitutes +Į (bot), +Ć (left), +Å (cross), and + (right) +at nexuses of the tree.

+ +tree is a model of 5!:4.

+
+ +

Linear Representation

+ +5!:5 is a verb that applies to a boxed name, and produces a literal list +of the linear representation of the named object. Thus:

+ +

+   lrep=: lr @ > @ ar
+
+   5!:5 <'lrep'
+lr@>@ar
+   $ 5!:5 <'lrep'
+7
+
+ +The linear representation can be modelled as follows:

+ +
+ar     =: 5!:1
+boxed  =: 32&= @ (3!:0)
+oarg   =: >@(1&{)
+mtv    =: i.@0:
+paren  =: ('('&,)@(,&')')
+symb   =: $&' '@(e.&'.:')@{. , ]
+quote  =: ''''
+alp    =: (,65 97+/i.26){a.
+dig    =: '0123456789'
+
+slist  =: $&','@(1&=)
+shape  =: mtv`slist`(,&'$'@":)@.(2&<.@#)`('i.'&,@":) @. (0&e.) @ $
+vchar  =: >:@(quote&=)@, quote&,@(,"e)@# ,
+vbox   =: }. @ ; @: (','&,@paren@('<'&,)@lnoun&.>)
+value  =: vchar`vbox`(":!.18@,) @. (2 32&i.@(type * *@(*/)@$))
+lnoun  =: shape , value
+
+dotco  =: 2&=@# *. e.&'.:'@{:
+name   =: e.&alp@{. *. *./@(e.&(alp,dig,'_'))@}: *. e.&(alp,dig,'_.:')@{:
+num    =: e.&(dig,'_')@{. *. *./@(e.&(dig,'_ .ejdr'))
+qstr   =: mtv -: -.@(~:/\)@(e."e) -."e@# ]
+pstr   =: -.@(0&e.)@}:@(+/\)@({&1 _1 0)@('()'&i.)
+nopar  =: 1&=@# +. dotco +. name +. num +. qstr +. pstr
+cp     =: paren`] @. nopar
+
+bp     =: ]`cp@.(' '&e.)
+hfork  =: }.@;@:(' '&,@bp&.>)@]
+left   =: bp@>@{.
+right  =: mtv`(cp@>@{:)@.(1&<@#)
+ins    =: left@] , symb@>@[ , right@]
+act    =: ;@:(cp&.>)@]
+insert =: hfork`hfork`act`act`act`ins @. ('23456'&i.@{.@>@[)
+
+lx     =: {. insert lr&.>@oarg
+ltie   =: lr`(}.@;@:('`'&,@cp@lr&.>)@oarg) @. ((<,'0')&=@{.)
+lgl    =: {. insert (ltie&.>@{. , lr  &.>@}.)@oarg
+lgr    =: {. insert (lr  &.>@{. , ltie&.>@}.)@oarg
+lg     =: lgr`lgl`lx @. (i.&(<,'`')@oarg)
+ltil   =: lx`(oarg@>@{.@oarg) @. ((<,'0')&=@{.@>@{.@oarg)
+lcase  =: (cp@lnoun@oarg)`lgl`lgl`lg`ltil`lx @. ((;:'0@.`:4~')&i.@{.)
+lr     =: symb`lcase@.boxed
+
+lrep   =: lr @ > @ ar
+
+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojSent.htm b/docs/ioj/iojSent.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojSent.htm @@ -0,0 +1,331 @@ + + + +An Implementation of J -- Interpreting a Sentence + + + + +

Interpreting a Sentence
+An Implementation of J

+ +Word Formation
+Parsing
+Trains
+Name Resolution

+ +
+
+ +Word Formation

+ +Words are expressed in the standard ASCII alphabet. +Primitive words are spelled with one or two letters; +two letter words end with a period or a colon. +The entire spelling scheme is shown in the system summary. +The verb ;: facilitates exploration of the rhematic rules. Thus:

+ +
+   ;: 'sum =:+/_6.95*i.3 4'
+ŚÄÄÄĀÄÄĀÄĀÄĀÄÄÄÄÄĀÄĀÄÄĀÄÄÄæ
+³sum³=:³+³/³_6.95³*³i.³3 4³
+ĄÄÄÄĮÄÄĮÄĮÄĮÄÄÄÄÄĮÄĮÄÄĮÄÄÄŁ
+The source code for word formation is in the files w*.c. +The process is controlled by the function wordil (word index and length) +and the table state. Rows of state correspond +to 10 states; columns to 9 character classes. +Each table entry is a (new state, function) pair. +Starting at state S, a sentence is scanned from left to right +one character at a time; the table entry corresponding to the +current state and character class is applied.

+ +           New State/Function +                                     States +                                  Character Classes +
+XN  S   AN  NN  AN  9N  XN  XN  QN     S  Space              X  Other
+XI  SI  AI  NI  AI  9I  X   X   QI     X  Other              S  Space
+XI  SI  A   A   A   A   X   X   QI     A  Alphanumeric       A  Letters excl. NB
+XI  SI  A   A   NB  A   X   X   QI     N  N                  N  The letter N
+XI  SI  A   A   A   A   NZ  X   QI     NB NB                 B  The letter B
+Z   Z   Z   Z   Z   Z   X   X   Z      NZ NB.                9  Digits and _
+XI  SI  9   9   9   9   9   X   QI     9  Numeric            D  . Period
+Q   Q   Q   Q   Q   Q   Q   Q   QQ     Q  Quote              C  : Colon
+XI  SI  AI  NI  AI  9I  XI  XI  Q      QQ Even Quotes        Q  ' Quote
+Z   Z   Z   Z   Z   Z   Z   Z   Z      Z  Trailing Comment
+
+X   S   A   N   B   9   D   C   Q       Function
+                                       I  j=:i [ Emit(j,i-1)
+                                       N  j=:i
+
+ +Emit(j,i-1) produces a pair of indices delimiting a word +in the string. i is the current index, and j is an internal +register; if the current word is a number immediately following a numeric +list (one or more numbers), Emit combines their indices to form +a single word. At the end of the string, Emit(j,i-1) is executed.

+ +As an example, this process is applied +to sum =:+/_6.95*i.3 4, the sentence used above. +In the following table, the columns are: +index, character in the string, +the (current state, character class) pair, +the (new state, function) pair, +and the action. For example, the first step is step 0, +the letter is s, the current (and initial) state +is S, and the character class is A. From +the table, the entry in row S and +column A is AN, meaing the new state +is A and the function code is N. The action +assigns 0 to j.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  State /New State / 
i    CharChar ClassFunctionAction
0 s S A AN j=:0
1 u A A
2 m A A
3 A S SI j=:3 [ Emit(0,2)   sum
4 = S X XN j=:4
5 : X C
6 + X X XI j=:6 [ Emit(4,5)   =:
7 / X X XI j=:7 [ Emit(6,6)   +
8 _ X 9 9I j=:8 [ Emit(7,7)   /
9 6 9 9
10 . 9 D
11 9 9 9
12 5 9 9
13 * 9 X XI j=:13 [ Emit(8,12)   _6.95
14 i X A AI j=:14 [ Emit(13,13)   *
15 . A D
16 3 X 9 9I j=:16 [ Emit(14,15)   i.
17 9 S SI j=:17 [ Emit(16,16)   3
18 4 S 9 9N j=:18
19         Emit(18,18)   4

+ +Every primitive word has an ID (a unique byte value) +defined in file jc.h. +The ID for the first 128 ASCII characters are simply the byte values 0 to 127; +other IDs are arbitrary assignments in "dictionary order". + +
+    ...
+   #define CLPAR      '('          /*  40 050 28       */
+   #define CRPAR      ')'          /*  41 051 29       */
+   #define CSTAR      '*'          /*  42 052 2a       */
+   #define CPLUS      '+'          /*  43 053 2b       */
+    ...
+   #define CASGN      '\200'       /* 128 200 80 =.    */
+   #define CGASGN     '\201'       /* 129 201 81 =:    */
+   #define CFLOOR     '\202'       /* 130 202 82 <.    */
+   #define CMIN       '\202'       /* 130 202 82 <.    */
+   #define CLE        '\203'       /* 131 203 83 <:    */
+   #define CCEIL      '\204'       /* 132 204 84 >.    */
+   #define CMAX       '\204'       /* 132 204 84 >.    */
+   #define CGE        '\205'       /* 133 205 85 >:    */
+    ...
+
+ +Using mnemonics such as CPLUS and CASGN instead +of '+' and '\200' makes the source code more readable +and more amenable to automatic manipulation.

+ +The 3-row table spell in file ws.c associates letter +sequences with IDs. +The rows correspond to letters in the range ASCII 32 to 127, +those letters inflected by a period, +and those letters inflected by a colon; +table entries are IDs. Thus:

+ +
+   static C spell[3][68]={
+    '=',     '<',     '>',     '_',     '+',     '*',      ...,
+    CASGN,   CFLOOR,  CCEIL,   1,       CPLUSDOT,CSTARDOT, ...,
+    CGASGN,  CLE,     CGE,     CFCONS,  CPLUSCO, CSTARCO,  ...,
+   };
+
+ +For example, the first column specifies that =. has the +ID CASGN (assignment) and =: the ID CGASGN +(global assignment).

+ +spell is used by functions spellin +and spellout: +given a string (e.g. =:), spellin computes the +ID (CASGN); given the ID, spellout computes the +corresponding string.

+ +Using the information computed by wordil, +functions tokens +and enqueue transform a string into a list of nouns, verbs, +adverbs, conjunctions, etc. The next step is to parse this "tokenized" +form of the sentence.

+ +
+ +

Parsing

+ +Parsing occurs after word formation and is controlled by +function parse and table cases in file p.c. cases +is a direct translation of the parse table in Section II E of the dictionary: + +

+   #define AVN   (     ADV+VERB+NOUN)
+   #define CAVN  (CONJ+ADV+VERB+NOUN)
+   #define EDGE  (MARK+ASGN+LPAR)
+
+   PT cases[] = {
+    EDGE,      VERB,      NOUN, ANY,       monad,   ..., 1,2, ...,
+    EDGE+AVN,  VERB,      VERB, NOUN,      monad,   ..., 2,3, ...,
+    EDGE+AVN,  NOUN,      VERB, NOUN,      dyad,    ..., 1,3, ...,
+    EDGE+AVN,  VERB+NOUN, ADV,  ANY,       adv,     ..., 1,2, ...,
+    EDGE+AVN,  VERB+NOUN, CONJ, VERB+NOUN, conj,    ..., 1,3, ...,
+    EDGE+AVN,  VERB,      VERB, VERB,      trident, ..., 1,3, ...,
+    EDGE,      CAVN,      CAVN, CAVN,      trident, ..., 1,3, ...,
+    EDGE,      CAVN,      CAVN, ANY,       bident,  ..., 1,2, ...,
+    NAME+NOUN, ASGN,      CAVN, ANY,       is,      ..., 0,2, ...,
+    LPAR,      CAVN,      RPAR, ANY,       punc,    ..., 0,2, ...,
+   };
+
+ +The sentence to be parsed is prefaced with a marker and placed on a queue, +and as parsing proceeds words are moved from the right end of +the queue onto a stack. The classes of the first four words on the stack +are compared to the patterns in columns 0 to 3 of cases. +The first row matching in all four columns is selected; +the action in column 4 is applied to the words on the stack indicated by +the inclusive indices in columns 8 and 9, with the result replacing +those words. If none of the rows match, the word at the end of the queue +is moved onto the stack by the function move. +Scanning for a matching pattern then begins anew. +The process terminates when the queue is empty and none of the rules +are applicable. +At that time, the stack should have exactly two words: +the marker and a noun, verb, adverb, or conjunction; +anything else signals syntax error.

+ +This parsing method was first described in +Iverson [1983]. +The parse table is a compact representation of a large amount +of information; it has guided both the evolution of the language +and its implementation. The following example illustrates parsing +on the sentence ((i.#y)=i.~y)#y where y=:'abc'. +(§ denotes the marker.)

+                                                                         Rule/
+      Queue +                                     Stack +         Action +           Comment +
+§((i.#y)=i.~y)#y                               original sentence
+§((i.#y)=i.~y)#            'aba'   13 move
+§((i.#y)=i.~y)            #'aba'   13 move
+§((i.#y)=i.~y            )#'aba'   13 move
+§((i.#y)=i.~        'aba')#'aba'   13 move
+
+§((i.#y)=i.        ~'aba')#'aba'   13 move
+§((i.#y)=        i.~'aba')#'aba'   13 move
+§((i.#y)        =i.~'aba')#'aba'   13 move
+§((i.#y)        =v0 'aba')#'aba'    3 adv      v0=: i.~
+§((i.#y        )=v0 'aba')#'aba'   13 move
+
+§((i.#    'aba')=v0 'aba')#'aba'   13 move
+§((i.    #'aba')=v0 'aba')#'aba'   13 move
+§((    i.#'aba')=v0 'aba')#'aba'   13 move
+§(    (i.#'aba')=v0 'aba')#'aba'   13 move
+§(         (i.3)=v0 'aba')#'aba'    1 monad    3 -: #'aba'
+
+§(       (0 1 2)=v0 'aba')#'aba'    0 monad    0 1 2 -: i.3
+§(         0 1 2=v0 'aba')#'aba'   12 punc
+§(            0 1 2=0 1 0)#'aba'    1 monad    0 1 0 -: v0 'aba'
+§            (0 1 2=0 1 0)#'aba'   13 move
+§                  (1 1 0)#'aba'    2 dyad     1 1 0 -: 0 1 2=0 1 0
+
+§                    1 1 0#'aba'   12 punc
+                    §1 1 0#'aba'   13 move
+                           §'ab'    2 dyad
+
+
+ +

Trains

+ +A train is an isolated phrase not interpreted by the parsing +rules pertaining to verbs, adverbs, and conjunctions, and +(as a matter of language design) may be assigned any meaning whatsoever. +Iverson and McDonnell [1989] +defined a train of three verbs as a +fork and a train of +two verbs as a hook. That is, +if f, g, and h are verbs, then +so are (f g h) and (g h), and:
+ +

+         Fork                      Hook
+     g          g              g          g
+    / \        / \            / \        / \
+   f   h      f   h          y   h      x   h
+   |   |     /\   /\             |          |
+   y   y    x  y x  y            y          y
+
+ +Parsing rules 5, 6, and 7 deal with trains. +(See Parsing.) +A consequence of the rules is that a train of verbs is resolved +by repeated forming a fork from the rightmost three verbs, with a +final hook if the train is of even length. Likewise, a train +of adverbs and conjunctions is assigned a meaning, and is +resolved by repeatedly forming a +group from the leftmost three adverbs or conjunctions, +with a final group of two if the train is of even length. +Trains are implemented by functions and variables of file cf.c. +The main functions are folk +and hook. (fork conflicts with UNIX usage.)

+ +
+ +

Name Resolution

+ +During parsing, words are moved from the queue to the stack. +Suppose a name xyz is being moved. +If xyz is immediately to the left of a copula, it (as a name) +is put on the stack. Otherwise, if xyz denotes a noun, +that noun is put on the stack; if xyz denotes a verb, +adverb, or conjunction, 'xyz'~ is put on the stack, +to be evaluated when the verb, adverb, or conjunction is applied.

+ +Names and their assigned values are stored in symbol tables. +A symbol table is an array of type SYMB whose atoms +are pairs (name,value). Functions and variables in the files s*.c work with +symbols tables. In particular, symbis(a,w,symb) assigns +the name a to w in the symbol table symb, +and symbrd(w) "reads" the value of the name w.

+ +
+


+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojSp.htm b/docs/ioj/iojSp.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojSp.htm @@ -0,0 +1,321 @@ + + + +An Implementation of J -- Special Code + + + + +

Special Code
+An Implementation of J

+ +
+
+ +Many primitives contain special code for certain arguments +to effect time and/or space savings not available to +general arguments. +Moreover, some phrases are "recognized" +and are supported by special code. +For example, the dyad of the hook ($,) +is exactly the reshape of APL (denoted by r); +its implementation avoids actually ravelling the right argument, +and in so doing saves both time and space:

+ +
+   ts=: 6!:2 , 7!:2@]
+   x=: 11 13 17 19 23
+   y=: 29 7 23 11 19$'sesquipedalian'
+
+   (x ($,) y) -: x $, y
+1
+
+   ts 'x ($,) y'
+0.00773981 2.09818e6
+   ts 'x $, y'
+0.0170125 3.14662e6
+
+ +Instances of such special code are listed below:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                        
=dyadword-parallel operation +on Boolean arguments for the following verbs:
+= < <. <: > >. >: +. +: * *. *: ^ ~: | !
<.@fbothavoids non-integer intermediate results on extended precision integers
>.@fbothavoids non-integer intermediate results on extended precision integers
+dyadalso * and -; on Windows, +assembly code for integer arguments +for the vector-vector, +vector-scalar, and scalar-vector cases
^dyadx^y works by repeated multiplication if x is real +and y is integral +
m&|@^dyadavoids exponentiation for extended precision arguments
m&|@(n&^)monadavoids exponentiation for extended precision arguments
+/ .*dyadspecial code
-/ .*monadspecial code in general; special code for square matrices; +special code for arrays of 2-by-2 matrices
$,dyadalso ($,)"r; avoids ravel
f;.1bothalso f;._1 f;.2 f;._2; +avoids building argument cells for several verbs: < $ , # [ ] {. {: +<@}. <@}: ; also <&}. <@:}. etc.
f;.3bothalso f;._3; +special code for matrix right arguments
#dyadspecial code for Boolean left arguments
# i.@#monadalso (# i.&#), etc.; +avoids i. on Boolean arguments
#: i.@(*/)monadalso (#: i.&(*/)), etc.; +special code for non-negative integer vectors
=/monadalso < <: > >: +. +: * *. *: ~:; +word-parallel operations on Boolean arguments
+/monadalso * and -; on Windows, +assembly code for integer arguments
,/monadlinear time
,./monadlinear time
,.&.>/monadlinear time
;/monadlinear time
f/@,monadalso f/@:, f/&, f/&:,; avoids ravel
#/.dyadavoids building argument cells
/:bothalso \:; special code for several data types; +special code for arguments with 5 items or less
=/\monadalso +. *. ~:; +word-parallel operations on Boolean arguments
+/\monadalso * and -; on Windows, +assembly code for integer arguments
=/\.monadalso < <: > >: +. +: *. *: ~:; +word-parallel operations on Boolean arguments
+/\.monadalso * and -; on Windows, +assembly code for integer arguments
{dyadspecial code for right arguments of several data types; +special code for integer left arguments; +special code for indexing first two axes
<"1@[ { ]dyadavoids <"1 if left argument is integer array
a=: c}x,y,:z-avoids catenation and lamination; +in-place if c is Boolean +and a is x or y
y=: x i}y-in-place
f"rbothnumerous verbs have integrated rank support:
+= < <. <: > >. >: + +. +: * *. *: - -: % ^ ~: | |. |: $ , ,. ,: # ! +[ ] { {. {: }. }: / /: \ \. \: e. i. i: o. p. p: +
?monadalso ?.; special code if argument is identically 2
?dyadalso ?.; special code if left argument is much smaller +than right argument
E.monadspecial code for Boolean and literal vector arguments
i.monadalso i:; special case for length-1 arguments
i.dyadalso e. and i:; special code for several data types; +special code for i.!.0; +special code for arguments with many identical columns

+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojSumm.htm b/docs/ioj/iojSumm.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojSumm.htm @@ -0,0 +1,308 @@ + + + +An Implementation of J -- System Summary + + + + +

System Summary
+An Implementation of J

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                                                                                            
=sclass eq is is
<box lt floor1 minimum decrem le
>ope gt ceil1 maximum increm ge
_connum connum num1 num2
    
+conjug plus rect gcd duble nor
*signum tymes polar lcm square nand
-negate minus not less halve match
%recip divide minv mdiv sqroot root
    
%expn1 expn2 logar1 logar2 powop
$shape reitem sparse1 sparse2 self1 self2
~swap nub   nubsieve ne
|mag residue reverse rotate cant1 cant2
    
. dot even odd
: colon obverse adverse
,ravel over table stitch lamin1 lamin2
;raze link cut words  
    
#tally repeat base1 base2 abase1 abase2
!fact outof fit foreign
/slash sldot grade1 grade2
\bslash bsdot dgrade1 dgrade2
    
[right1 left2 lev  
]right1 right2 dex ida
{catalog from head take tail  
}rbrace behead drop curtail  
    
" qq exec1 exec2 thorn1 thorn2
` tie   evger
@ atop agenda atco
& amp under ampco
?roll deal rollx dealx  
    
{::map fetch }:: emend   &.: undco
    
a.alp A.  adot1 adot2 b.  bdot  
c.eig1 eig2 C.  cdot1 cdot2 d.  ddot
D. dcap D:  dcapco e.  razein eps
E. ebar f.  fix H.  hgeom
    
i.iota indexof i:  jico1 jico2 I.  icap
j.jdot1 jdot2 L.  level1 L:  lco
m.xd n.  xd o.  pix circle
p.poly1 poly2 p:  prime   q:  factor qco2
    
r.rdot1 rdot2 S:  sco t.  tdot
t:tco T.  tcap u.  xd
v.xd x.  xd x:  xco1 xco2
y.xd    
+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojTest.htm b/docs/ioj/iojTest.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojTest.htm @@ -0,0 +1,206 @@ + + + + + +An Implementation of J -- Test Scripts + + + + +

Test Scripts
+An Implementation of J

+ +
+
+ +A script is an ASCII text file containing J sentences; +a test script is script which contains purportedly +true J sentences.

+ +The J test scripts are a set of about 280 scripts that +test the J interpreter. Each script tests a particular +aspect, usually a single primitive. The scripts have names of the +form gxxx.ijs, where xxx +is an encoding based on the vocabulary page of +the J dictionary. For example, the +script g022.ijs +tests the primitive >: +(increment / larger or equal), named on the basis +that >: is group 0, row 2, and column 2.

+ +Test scripts require the utilities in the script tsu.ijs. +Test scripts can be run with either the 0!:2 or +the 0!:3 primitive.

+ +0!:2 runs a test script with output, stopping at the first result +which is not all 1s, or at the first (untrapped) error. +For example:

+ +
+   0!:0 <'\dev\js\tsu.ijs'
+   0!:2 <'\dev\js\g022.ijs'
+   NB. >:y -----------------------------------------------------------------
+   
+   (>: -: 1&+) 1=?2 3 4$2
+1
+   (>: -: 1&+) _1e9+?2 3 4$2e9
+1
+   (>: -: 1&+) o._1e9+?2 3 4$2e9
+1
+   (>: -: 1&+) j./?2 3 4$2e9
+1
+   
+   _1 0 1 2 3  -: >: _2 _1 0 1 2
+1
+   2147483648  -: >: 2147483647
+1
+   _2147483647 -: >:_2147483648
+1
+   
+   t -: [&.>: t=._1e9+?2 3 4$2e9
+1
+   
+   'domain error' -: >: etx 'abc' 
+1
+   'domain error' -: >: etx <'abc'  
+1
+   
+   
+   NB. x>:y ----------------------------------------------------------------
+   
+   1 0 1 1 -: 0 0 1 1 >: 0 1 0 1
+1
+   
+   'domain error' -: 'abc' >: etx 3 4 5
+1
+   'domain error' -: 'abc' >:~etx 3 4 5 
+1
+   'domain error' -: 3j4   >: etx 3 4 5 
+1
+   'domain error' -: 3j4   >:~etx 3 4 5
+1
+   'domain error' -: (<34) >: etx 3 4 5
+1
+   'domain error' -: (<34) >:~etx 3 4 5 
+1
+   
+   'length error' -: 3 4     >: etx 5 6 7
+1
+
+   'length error' -: 3 4     >:~etx 5 6 7
+1
+   'length error' -: (i.3 4) >: etx i.5 4
+1
+   'length error' -: (i.3 4) >:~etx i.5 4  
+1
+
+   4!:55 ;:'t'
+1
+
+ +0!:3 runs a test script without output, returning a result of 0 +if the script had a result which is not all 1s +or if it contained an (untrapped) error, and a result of 1 otherwise. +For example:
+ +
+   0!:0 <'\dev\js\tsu.ijs'
+   0!:3 <'\dev\js\g022.ijs'
+1
+
+ +The J test scripts are divided into three groups (running times are +seconds on a Pentium III 500 MHz computer):
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
    Type    Number    Name List      Run    Time (Seconds)
Ordinary 240 ddall rundd.ijs 113
Sparse Arrays 27 ssall runss.ijs 1140
Mapped Boxed Arrays 12 mbxall runmbx.ijs 3
+ +
+For example, the "ordinary" test scripts can be run as follows:
+
+
+   0!:2 <'\dev\js\rundd.ijs'
+   NB. run dd test scripts
+
+   0!:0 <'d:\dev\js\tsu.ijs'               NB. define utilities
+   jsts0=: 6!:0 ''                         NB. timestamp at start
+   ddall=: 3!:2 (1!:1) <'d:\dev\js\ddall'  NB. define namelist
+   ] bbb=: 0!:3 ddall                      NB. run the test scripts
+1 1 1 1 1 1 1 1 1 1 1 1 1 ...
+   jsts1=: 6!:0 ''                         NB. timestamp at end
+
+ +The rundd.ijs script first runs +the tsu.ijs script +(to define the requisite utilities), then +defines ddall, the list +of test script names, then runs the test scripts. The boolean +vector bbb has the same shape +as ddall, and can be used +to detect which test scripts have failed. +The bad scripts (-.b)#ddall can +be run using the 0!:2 +primitive to narrow in on the offending expressions.

+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + diff --git a/docs/ioj/iojVerb.htm b/docs/ioj/iojVerb.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojVerb.htm @@ -0,0 +1,596 @@ + + + +An Implementation of J -- Verbs + + + + +

Verbs
+An Implementation of J

+ +Anatomy of a Verb
+Rank
+Atomic (Scalar) Verbs
+Obverses, Identities, and Variants
+Error Handling

+ +
+
+ +Anatomy of a Verb

+ +Verbs are implemented as functions. A verb applies to a noun +(if used monadically) or to two nouns (if used dyadically), +and produces a noun result. +The defined type AF and the +macros F1 and F2 +codify these properties:

+ +
+   typedef A(*AF)();
+
+   #define F1(f)  A f(J jt,    A w); 
+   #define F2(f)  A f(J jt,A a,A w); 
+
+AF is the data type of a function having these properties. +F1 and F2 are used to specify the headers of functions +implementing verbs (and adverbs and conjunctions); +the majority of functions in the implementation are so specified. +(jt is the global variables +parameter; a and w denote a +and w, traditionally the names given to +the left and right arguments of APL functions.) +Verbs are represented by arrays of type VERB; +the details of this representation are discussed in +Adverbs and Conjunctions.

+ +The verb j. is used here to illustrate the relationship +among relevant system components. j. has monad 0j1&*"0 +and dyad (+j.)"0. There are three main steps in +the implementation:

+ +1. Define and declare functions which implement the monad and the dyad.
+2. Associate j. with the functions and other information.
+3. Specify obverses, identity functions, and variants (if any).

+ +These steps are executed as follows:

+ +1. Functions which implement the monad and the dyad j. are added +to file vm.c (or to one of the v*.c files), and declarations are +added to je.h:

+ + + + + + + + + + + + + + + + +
   File vm.c    File je.h
 F1(jtjdot1){R tymes(a0j1,w);}  extern F1(jtjdot1); +
 F2(jtjdot2){R plus(a,tymes(a0j1,w));}  extern F2(jtjdot2);

+ +2. The association between j. and jdot1 and jdot2 +is established +in the table pst, initialized by +functions pinit +and pdef in file t.c. +pst is declared as A pst[256]; , +a 256-element vector of type A, +and pst[x] contains the information for the primitive whose +ID is unsigned byte x. The ID +for j. is CJDOT, therefore the information +for j. can be found in pst[(UC)CJDOT]. +The surrounding entries in pst are initialized as follows; +the entry for j. indicates that it is a verb, with +monad jdot1, dyad jdot2, +and zero monadic, left, and right ranks:

+ +
+   /*  i: */  pdef(CICO,    VERB, jtjico1,   jtjico2,  0L,  RMAX,RMAX);
+   /*  I. */  pdef(CICAP,   ADV,  jticap,    0L,       0L,  0L,  0L  );
+   /*  j. */  pdef(CJDOT,   VERB, jtjdot1,   jtjdot2,  0L,  0L,  0L  );
+   /*  L. */  pdef(CLDOT,   VERB, jtlevel1,  0L,       RMAX,0L,  0L  );
+   /*  L: */  pdef(CLCO,    CONJ, 0L,        jtlco,    0L,  0L,  0L  );
+
+ +The macro ds(x) is defined +as pst[(UC)(x)], +and is a convenient reference for a primitive; +for example, ds(CJDOT) is the verb j. as an array +(in short, ds(CJDOT) is j.).

+ +3. A verb may have information additional to that in pst, +embodied in functions inv and invamp (obverses) in file +ai.c, iden (identity functions) in ai.c, and fit +(variants) in cf.c. +See Obverse, Identities, and Variants.

+ +The obverses associated with j. are:

+ +
+   j.       %&0j1          
+   n&j.     %&0j1@(-&n) 
+   j.&n     -&(j.n)
+
+ +The obverse of j. is implemented +as case CJDOT in inv; those +for n&j. and j.&n are implemented +as case CJDOT in invamp. +The identity function for j. is $&0@(}.@$), +and is implemented +as case CJDOT in iden. j. +has no variants; the implementation of a variant would have +required a case in fit.

+ +
+ +

Rank

+ +Verb (function) rank was introduced by Iverson [1978 §6], +further developed in Iverson [1983, 1987, 1995], +and implemented in SHARP APL, SHARP APL/HP, SAX, A, and J +(see Bernecky et al. [1983, 1987], Hodgkinson [1986], +Steinbrook [1986], Whitney [1989], and Hui et al. [1990], +respectively). This description first appeared in Hui [1995].

+ +A verb of rank r is defined on arguments +with rank bounded by r; +the extension to higher-rank arguments is the same for all verbs. +The rank conjunction " (operator) augments the default ranks of +a verb by user-specified ranks. It provides for the +generalization of a verb to higher-rank arrays, +and could justifiably be called the generalization +or extension operator; it also provides for consistent application +to lower-rank arrays, subsuming and superseding +the anomalous bracket-axis operator.

+ +Various aspects of rank are here discussed in terms of a model in J, +updated from Hui [1987 §A.2].

+ +Frames and Cells. A rank r splits the argument shape into +the frame and the cell shape; a positive r specifies the number +of trailing cell axes, while a negative r specifies the +negative of the number of leading frame axes.

+ +

+rk    =: #@$
+er    =: (0:>.(+rk))`(<.rk) @. (0:<:[)
+fr    =: -@er }. $@]
+cs    =: -@er {. $@]
+boxr  =: ]`(<@$ , [ $: */@[}.])@.(*@#@])
+cells =: fr $ cs boxr ,@]
+
+ +For rank r and argument y, +the phrase r er y computes +the effective rank (non-negative and bounded by #$y); +r fr y computes the frame and r cs y the cell shape; +and r cells y computes the array of +cells with shape r fr y, +each cell individually boxed and shaped s=: r cs y +(r cells y is <"r y). +The recursively-defined verb s boxr y +produces the list of such cells.

+ +The model is shown in action on x*"0 _1 y, +the atoms (scalars) of x times the items of y:

+ +
+   x=:1 2 3
+   y=:i.3 2
+   y                        x*"0 _1 y
+0 1                      0  1
+2 3                      4  6
+4 5                      12 15
+   0 er x                   _1 er y
+0                        1
+   0 fr x                   _1 fr y
+3                        3
+   0 cs x                   _1 cs y
+                         2
+   0 cells x                _1 cells y
+ŚÄĀÄĀÄæ                  ŚÄÄÄĀÄÄÄĀÄÄÄæ
+³1³2³3³                  ³0 1³2 3³4 5³
+ĄÄĮÄĮÄŁ                  ĄÄÄÄĮÄÄÄĮÄÄÄŁ
+
+ +Agreement. In the dyad v"r, commonly the left and +right frames match, that is, the two cell arrays have the same shape; +if not, several design choices are possible: + +In scalar agreement, one frame must be empty, +and the single cell is reshaped using the other frame; +in suffix agreement, one frame must be a suffix of the other, +and again the list of cells is reshaped using the other frame; +finally, in prefix agreement, one frame must be a prefix of the other, +and each cell is reshaped with the excess in the other frame. +All three agreements are proper generalizations +of scalar extension in APL\360, with cells acting the role of scalars. +Agreement results in the two cell +arrays having the same shape ("the frame").

+ +Prefix agreement is adopted in J as suggested by Whitney [1992], +because it best fits the emphasis on leading axes.

+ +
+pfx   =: <.&rk
+agree =: (pfx {. $@[) -: (pfx {. $@])
+frame =: [:`($@([^:(>&rk))) @. agree
+rag   =: frame $ ([: */ rk@]}.$@[) # ,@]
+lag   =: rag~
+
+ +rag and lag apply to both cell arrays +(the results of cells in the previous section), +producing cell arrays with the same shape. +If v"r itself were used in the model, rag could +be defined more +directly from the specification: (rk@]}.$@[) $"1 0 ] — +each cell is reshaped with the excess in the other frame. +In the continuing example, rag and lag have no effect because +the left and right frames match.

+ +
+   [xc=.0 cells x           [yc=._1 cells y
+ŚÄĀÄĀÄæ                  ŚÄÄÄĀÄÄÄĀÄÄÄæ
+³1³2³3³                  ³0 1³2 3³4 5³
+ĄÄĮÄĮÄŁ                  ĄÄÄÄĮÄÄÄĮÄÄÄŁ
+   [xa=.xc lag yc           [ya=.xc rag yc
+ŚÄĀÄĀÄæ                  ŚÄÄÄĀÄÄÄĀÄÄÄæ
+³1³2³3³                  ³0 1³2 3³4 5³
+ĄÄĮÄĮÄŁ                  ĄÄÄÄĮÄÄÄĮÄÄÄŁ
+
+ +Assembly. After agreement, the phrase v&.> applies v +under > to corresponding boxed left and right argument cells, +to produce an array of boxed result cells. +It remains to assemble the overall result from the individual results.

+ +Cells are brought to a common rank by adding leading unit axes, +then to a common shape by padding. +The overall shape is fm,sir, +where fm is the frame and sir is the common shape +of the individual results. +This is a design choice: the individual results could be required +to have a common shape without further intervention, +but this permissive assembly proves useful. For example, +open > on a list of boxed words yields a matrix with the words +padded to a common length.

+ +
+mrk   =: >./@:(rk&>)@,
+crank =: mrk ,:@]^:(-rk)&.> ]
+msh   =: >./@:( $&>)@,
+cshape=: <@msh {.&.> ]
+asm   =: > @ cshape @ crank
+rank  =: 2 : 0
+ 'm l r'=.3&$&.|.y.
+ ([: asm [: x.&.> m&cells) : ([: asm l&cells@[ (lag x.&.> rag) r&cells@])
+)
+
+ +The conjunction rank integrates the model components. +The left argument x. is the verb v; +the right argument y. +is reshaped from the right to exactly 3 numbers +and assigned to m, l, and r.

+ +
+   [ za=. xa *&.> ya
+ŚÄÄÄĀÄÄÄĀÄÄÄÄÄæ
+³0 1³4 6³12 15³
+ĄÄÄÄĮÄÄÄĮÄÄÄÄÄŁ
+   asm za
+ 0  1
+ 4  6
+12 15
+   x * rank 0 _1 y
+ 0  1
+ 4  6
+12 15
+
+ +Zero Frame. If the frame contains 0 (as in 3*"1 i.0 4), +there are no argument cells to apply v to, +and the shape of a result cell (the value of sir) +is indeterminate. +Pesch [1986] describes a variety of strategies to address this problem. +In J, the shape is calculated if v is uniform (see below); +otherwise v is applied to a cell of fills.

+ +Implementation. Rank is implemented by +functions rank1ex +and rank2ex ("rank execution") in file cr.c. +A function f has access to the entire arguments of the verb +that it implements, regardless of the ranks of the verb. +Within f, rank effects can be achieved by +invoking rank1ex and rank2ex, mediated +by the +macros F1RANK +and F2RANK:

+ +
+   A rank1ex(    A w,A self,I m,    AF f1);
+   A rank2ex(A a,A w,A self,I l,I r,AF f2);
+
+   F1RANK(m,  f1,self);
+   F2RANK(l,r,f2,self);
+
+ +a and w are the left and right arguments of the +verb; f1 and f2 are functions which implement +the monad and dyad; m,l,r are ranks; +and self is an +array representing the verb. +For example, the dyad ": has ranks 1 _ +and is implemented by the function thorn2, +which uses F2RANK as follows:

+ +
+   F2(jtthorn2){PROLOG;A da,ea,h,ma,s,y,*yv,z;B e,*ev; ...
+    F2RANK(1,RMAX,jtthorn2,0);
+    an=AN(a); t=AT(w);
+    ...
+   }
+
+If the argument ranks are not greater than the verb ranks, +then F2RANK (F1RANK) does nothing, +and execution proceeds to the statement following the macro; +if the argument ranks are greater, +then F2RANK (F1RANK) +invokes rank2ex (rank1ex), +and on return therefrom exits f with the result +obtained therefrom. +In this scheme, rank2ex (rank1ex) +invokes f repeatedly, but with arguments of +rank bounded by the verb ranks.

+ +A function may implement rank by other means. For example, +the dyad { has ranks 0 _ and is implemented +by the function from, which +eschews rank2ex on numeric left arguments wherein rank +effects are uniform and rather simple. (from +does use rank2ex on boxed left arguments.) +Atomic verbs +also implement rank independently to exploit the special properties +of such verbs.

+ +Verbs derived from adverbs and conjunctions are always invoked +with self. The +macros PREF1 and PREF2 +are used in such cases, +wherein rank1ex and rank2ex are invoked with +ranks extracted from self, and not with constants +as in the use of F1RANK and F2RANK +for primitive verbs.

+ +
+ +

Atomic (Scalar) Verbs

+ +Not Yet Available

+
+ +

Obverses, Identities, and Variants

+ +Verbs have additional parts — obverse, identity, and variants — +which can not be specified as static data structures. +Such information is embodied in functions.

+ +• Obverses

+ +A verb u is an obverse (usually the inverse) of a verb v +if x=u v x +for a significant subdomain of v. +The obverse is used in the conjunctions under +(&.) and power (^:). +For example, exponential ^ and logarithm ^. +are obverses, and:

+ +

+   3 +&.^. 4  is  ^ (^.3) + ^.4        ^ ^:_1  is  ^.
+   3 *&.^  4  is  ^.(^ 3) * ^ 4        ^.^:_1  is  ^
+
+ +Obverses are produced by the function inv +in file ai.c. (inv implements ^:_1.) +The logic is a combination of table look-up and nested +branch tables (switch/case).

+ +Primitives. If the obverse of a primitive verb is itself primitive, +the information is recorded in the +2-row table invf in file ai.c.

+ +Bonded Verbs. Bonding (Currying) is fixing an argument of +a dyad to derive a monad: n&v or v&n. +For example, 10&^. is base-10 log +and ^&0.5 is square root. +The obverse of a bonded verb is computed by the +subfunction invamp in file ai.c, +invoked by inv as appropriate.

+ +Prefix and Suffix. Sum prefix +/\ and sum +suffix +/\. can be +expressed as pre-multiplication by matrices obtained by +applying +/\ and +/\. on the identity matrix; +the obverse is therefore pre-multiplication by the +matrix inverse of these matrices. +(The actual obverse is a more efficient equivalent derived therefrom.) +Similar reasoning applies to -, *, %, +and to = and ~: +on Boolean arguments. The logic is embodied as a sub-switch +in inv, +under case CBSLASH and case CBSDOT.

+ +Reflex (~). The monad v~ computes +y v y; for example, +~ is double. +The obverses of a few such verbs are implemented by +a sub-switch in inv, +under case CTILDE.

+ +Assigned Obverse. A verb may be assigned an obverse with +the obverse conjunction (:.). +f=: u :.v +is like u but the obverse of f is v.

+ +Other Verbs. inv applies to a few other verbs, +including u@v and u&v, whose obverses are +(v inv)@(u inv) and (v inv)&(u inv).

+ + +• Identities

+ +u/y applies the dyad between the items of y. +When y has zero items, +the result of u/y obtains by applying +to y the identity function ui +of u, so-called because +(iu y) u y or y u (iu y) is y +for a significant subdomain of u.

+ +Identity functions are computed by +function iden +in file ai.c. iden behaves like an adverb, applying +to verbs and producing verbs. +The logic is implemented as a branch table +(switch/case). +Not all verbs have identity functions; +iden signals error in such cases.

+ + +• Variants +

+ +Variants of a verb are produced by the fit +conjunction !., and are used to effect +tolerant comparison +(= < <. and so forth), formatting to +a specific precision (":), +shifts (|.), +and factorial polynomials (^).

+ +!. is implemented by function fit in file cf.c. +The logic is implemented as a branch +table (switch/case). +Not all verbs have variants; fit signals error in such cases.

+ +
+ +

Error Handling

+ +When an error is encountered in a function, the global +variable jerr is set to an error number, and zero is returned. +Therefore, when calling a function that can not have zero as a valid result +(but does return a result), the returned value must be checked for zero; +when calling a "void" function or one whose range +includes zero, jerr must be inspected.

+ +Error numbers range between 1 and NEVM, +and are referenced by the EV* names (file jerr.h). +The function jsignal (d.c) +applies to an error number, sets jerr to this number, and +displays the appropriate error message; jsignal exits +immediately if jerr is already nonzero. +evm is a list of the error messages. +These messages are initialized by +function evinit (file i.c), +and may be inspected and changed by the user +through 9!:8 and 9!:9.

+ +The macro ASSERT (file j.h) is used +extensively in argument validation. +It applies to a proposition and an error number. For example, +the following statements check whether w is a literal atom:

+ +

+   ASSERT(!AR(w),EVRANK);
+   ASSERT(LIT&AT(w),EVDOMAIN);
+
+ +If the proposition is nonzero, execution proceeds to the next statement; +otherwise, the indicated error is jsignal-ed and a zero is returned. +The macros RZ and RE +(file j.h) are used in function calls. RZ returns zero +if its argument is zero; RE evaluates its argument, +and returns zero if jerr is nonzero. For example, +the function iota (implementing the +monad i.) exploits RZ as follows: +

+ +
+   F1(jtiota){A z;I m,n,*v;
+    F1RANK(1,jtiota,0);
+    if(AT(w)&XNUM+RAT)R cvt(XNUM,iota(vi(w)));
+    RZ(w=vi(w)); n=AN(w); v=AV(w);
+    if(1==n){m=*v; R 0>m?apv(-m,-m-1,-1L):apv(m,0L,1L);}
+    m=prod(n,v); z=reshape(mag(w),apv(ABS(m),0L,1L));
+    DO(n, if(0>v[i])z=irs1(z,0L,n-i,jtreverse););
+    R z;
+   }
+
+ +The arguments of a function may be the result of another function; +the convention is that a function checks its arguments for zero +and returns zero immediately in such cases. Thus, in iota above:

+ +
+   z=reshape(mag(w),apv(ABS(m),0L,1L));
+
+ +If reshape did not check for zero arguments, +the statement would have to be elaborated:

+ +
+   RZ(t0=mag(w));
+   RZ(t1=apv(ABS(m),0L,1L));
+   z=reshape(t0,t1);
+
+ +A conventional function is a +function that follows the conventions +described herein — return zero on zero arguments and on errors. +The defined type AF (file jtype.h) typifies a +conventional function. Most functions in the system are conventional; +in particular, all functions implementing primitives are conventional. +Expressions and statements that use only conventional functions +need not employ RZ or RE, and the resulting +programs are neater. +For example, consider functions shape and nub (file v.c), +implementing the monads $ and ~., respectively:

+ +
+   F1(jtshape){RZ(w); R vec(INT,AR(w),AS(w));}
+   F1(jtnub){R repeat(nubsieve(w),w);}
+
+ +shape must check for zero arguments RZ(w), +because it +applies the unconventional macros AR and AS to +the argument w. In contrast, nub applies only +conventional functions to its argument and to +results of conventional functions on that argument.

+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/ioj/iojXenos.htm b/docs/ioj/iojXenos.htm new file mode 100644 --- /dev/null +++ b/docs/ioj/iojXenos.htm @@ -0,0 +1,186 @@ + + + +An Implementation of J -- Foreign Conjunction + + + + +

Foreign Conjunction
+An Implementation of J

+ +
+
+ +
+0!:0    scm00     • scd00   
+0!:1    scm01     • scd01   
+0!:2    sct1      • sct2    
+0!:3    scz1      • scz2    
+0!:10   scm10     • scd10   
+0!:11   scm11     • scd11   
+0!:100  scm00     • scd00   
+0!:101  scm01     • scd01   
+0!:110  scm10     • scd10   
+0!:111  scm11     • scd11   
+
+1!:0    jdir      •         
+1!:1    jfread    •         
+1!:2              • jfwrite 
+1!:3              • jfappend
+1!:4    jfsize    •         
+1!:5    jmkdir    •         
+1!:6    jfatt1    • jfatt2  
+1!:7    jfperm1   • jfperm2 
+1!:11   jiread    •         
+1!:12             • jiwrite 
+1!:20   jfiles    •         
+1!:21   jopen     •         
+1!:22   jclose    •         
+1!:30   jlocks    •         
+1!:31   jlock     •         
+1!:32   junlock   •         
+1!:40   pathapp   •         
+1!:41   pathdll   •         
+1!:42   pathlib   •         
+1!:55   jferase   •         
+
+2!:0    host      •         
+2!:1    hostne    •         
+2!:2    hostio    •         
+2!:3    jwait     •         
+2!:4    jargv     •         
+2!:5    jgetenv   •         
+2!:55   joff      •         
+
+3!:0    stype     •         
+3!:1    ir        •         
+3!:2    ri        •         
+3!:3    irx       •         
+3!:4              • ic2     
+3!:5              • fc2     
+
+4!:0    nc        •         
+4!:1    nl1       • nl2     
+4!:3    snl       •         
+4!:4    scind     •         
+4!:5    nch       •         
+4!:55   ex        •         
+4!:56   exall     •         
+
+5!:0    fxx       •         
+5!:1    arx       •         
+5!:2    drx       •         
+5!:4    trx       •         
+5!:5    lrx       •         
+5!:6    prx       •         
+
+6!:0    ts        •         
+6!:1    tss       •         
+6!:2    tsit1     • tsit2   
+6!:3    dl        •         
+6!:8    qpfreq    •         
+6!:9    qpctr     •         
+6!:10   pmarea1   • pmarea2 
+6!:11   pmunpack  •         
+6!:12   pmctr     •         
+6!:13   pmstats   •         
+
+7!:0    sp        •         
+7!:1    sps       •         
+7!:2    spit      •         
+7!:3    spcount   •         
+7!:4    spfree    •         
+
+9!:0    rlq       •         
+9!:1    rls       •         
+9!:2    dispq     •         
+9!:3    disps     •         
+9!:4    promptq   •         
+9!:5    prompts   •         
+9!:6    boxq      •         
+9!:7    boxs      •         
+9!:8    evmq      •         
+9!:9    evms      •         
+9!:10   ppq       •         
+9!:11   pps       •         
+9!:12   sysq      •         
+9!:14   versq     •         
+9!:16   posq      •         
+9!:17   poss      •         
+9!:18   ctq       •         
+9!:19   cts       •         
+9!:20   mmaxq     •         
+9!:21   mmaxs     •         
+9!:22   numdefq   •         
+9!:23   numdefs   •         
+9!:24   seclevq   •         
+9!:25   seclevs   •         
+9!:26   ilxq      •         
+9!:27   ilxs      •         
+9!:28   doilxq    •         
+9!:29   doilxs    •         
+
+11!:x   wd        •         
+
+13!:0   dbc       •         
+13!:1   dbs       •         
+13!:2   dbsq      •         
+13!:3   dbss      •         
+13!:4   dbrun     •         
+13!:5   dbnext    •         
+13!:6   dbret     •         
+13!:7   dbjump    •         
+13!:8   dbsig1    • dbsig2  
+13!:9   dbrr1     • dbrr2   
+13!:10  dbrrx1    • dbrrx2  
+13!:11  dberr     •         
+13!:12  dbetx     •         
+13!:13  dbcall    •         
+13!:14  dbtrapq   •         
+13!:15  dbtraps   •         
+13!:16  J         •         
+13!:17  dbq       •         
+13!:18  dbsz      •         
+13!:31            • colaux  
+
+15!:0             • cd      
+15!:1   memr      •         
+15!:2             • memw    
+15!:3   mema      •         
+15!:4   memf      •         
+15!:5   cdf       •         
+15!:6   symget    •         
+15!:7   symset    •         
+15!:8   gh15      •         
+15!:9   fh15      •         
+15!:10  cder      •         
+15!:11  cderx     •         
+15!:12  smmblks   •         
+
+18!:0   locnc     •         
+18!:1   locnl1    • locnl2  
+18!:2   locpath1  • locpath2
+18!:3   loccreate •         
+18!:4   locswitch •         
+18!:5   locname   •         
+18!:55  locexmark •         
+
+128!:0  qr        •         
+128!:1  rinv      •         
+
+ +
+
+ +Next + • +Previous + • +Index + • +Table of Contents +
+ + + \ No newline at end of file diff --git a/docs/license.txt b/docs/license.txt new file mode 100644 --- /dev/null +++ b/docs/license.txt @@ -0,0 +1,15 @@ + +JSOFTWARE SOURCES refers to all files in this Jsoftware release +package except for file gpl3.txt. + +JSOFTWARE SOURCES are: +Copyright 1990-2011, Jsoftware Inc. All rights reserved. + +JSOFTWARE SOURCES are: +Licensed under GNU General Public License as published by the +Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +See gpl3.txt for GNU General Public License version 3. +Additional info at http://www.gnu.org/licenses. + diff --git a/docs/readme.txt b/docs/readme.txt new file mode 100644 --- /dev/null +++ b/docs/readme.txt @@ -0,0 +1,142 @@ + +Building J from Jsoftware (www.jsoftware.com) source released under GPL +version 3. + +*** copyright and license + +JSOFTWARE SOURCES refers to all files in this Jsoftware release package +except for file gpl3.txt. + +JSOFTWARE SOURCES are: Copyright 1990-2011, Jsoftware Inc. All rights +reserved. + +JSOFTWARE SOURCES are: Licensed under GNU General Public License as +published by the Free Software Foundation, either version 3 of the License, +or (at your option) any later version. + +See gpl3.txt for GNU General Public License version 3. Additional info at +http://www.gnu.org/licenses. + +(above also appears in copyright.txt and license.txt) + +*** overview + +Unpack J source release tar.gz file. Following assumes tar unpack is done +in ~ and creates ~/jgplsrc. + +Familiarity with J provides essential background and context for working +with the source. + +Development has been primarily in Windows and work on other platforms has +been done with limited resources and limited understanding of normal Unix +practices. The shell scripts, make files, and configuration are eccentric +at best and may need work to fit comfortably in the open source world. + +This release is targeted at Unix. Windows VC++ project files are not +included (they could be created by those familiar with Windows +development). Additional source files required for the Windows COM wrapper +for j.dll in jgplsrc/win. + +If you are playing with a supported platform or are doing a port to a +'nearby' platform then the current packaging might meet your needs. An +example of a 'nearby' platform would be Linux/ARM as differences are minor +from already supported platforms. Further afield, for example other than +Linux/Mac/Windows, will require more work. + +*** folders + +jgplsrc - *.c *.h + +jgplsrc/bin - bash scripts + +jgplsrc/defs - files for building netdefs.ijs and hostdefs.ijs + +jgplsrc/docs - text files + +jgplsrc/docs/ioj - 'Implementation of J' by Roger Hui (out of date, but +useful) + +jgplsrc/j - minimal J environment to test new new binaries + +jgplsrc/test - test scripts to validate binaries + +jgplsrc/win - additional source for win com server + + +*** configuration + +bin/jconfig configs for 32/64bit and whether jconsole has line recall. + +Configuration is driven largely by Unix uname and jconfig insists on uname +of Linux or Darwin. If building for a different uname, you will have to +edit jconfig and perhaps make changes to j.h, js.h, and other files. + +Key platform differences are Unix/Windows, 32/64bits, intel byte +order/non-intel byte order, and XNAN and XINF double bit patterns. + +Buildling Linux/Mac on Intel could be fairly smooth. + +jconfig as distributed sets 32bit and no line recall. Edit jconfig as +required. + +*** touch *.c + +The makes are naive and don't handle h file or config changes. You may need +touch to get a clean build. + +*** build_jconsole - build jconsole binary + +$ cd ~/jgplsrc $ bin/build_jconsole + +*** build_libj - build libj.so or libj.dylib binary $ bin/build_libj + +If build_jconsole and build_libj succeed, the binaries have been copied to +j/bin and you can start J with: + +$ j/bin/jconsole + i.5 + +Congratulations if your J runs! + +*** build_tsdll + +J shared library calls (for example, sockets or memory mapped files) can +require J constants defined from C header files. These values are defined +by netdefs and hostdefs ijs files. Build these with: + +$ bin/build_defs + +*** build_tsdll + +Build tsdll (shared library used to test J calls) with: + +$ bin/build_tsdll + +*** test suite + +A test suite validates a J system. Read test/test.ijs and test/tsu.ijs for +more info. + +$ j/bin/jconsole + load 'test/test.ijs' + bad=: TEST ddall NB. run all tests + BAD ddall NB. report tests that failed + +TEST displays the script name before it is run. If you crash, the last name +displayed is the script that caused the crash. You can narrow down the +cause by displaying each line in the script as it is run: + +$ j/bin/jconsole + load 'test/test.ijs' + TESTX SNS 'gintovfl' NB. display and run each line of gintovfl.ijs + +Get more info about a BAD script the same way: + +A script can fail because of particular random numbers. If rerunning is +clean things are probably OK, but this is an area for caution. + +A script can fail because of a timing sensitvity. For example, comparing +timings of two methods to a threshold. Rerunning may show it sometimes runs +clean and sometimes fails on a timing test. You can ignore timing threshold +failures. + diff --git a/dss.c b/dss.c new file mode 100644 --- /dev/null +++ b/dss.c @@ -0,0 +1,56 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Debug: Single Step */ + +#include "j.h" +#include "d.h" + + +/* d->dcss - single step code in current function */ +/* jt->dbssd - the d whose dcss is non-zero */ +/* jt->dbss - single step code for propagation to appropriate function */ + + +DC jtssnext(J jt,DC d,C c){ + d=d->dclnk; + while(d&&DCCALL!=d->dctype)d=d->dclnk; /* find next call */ + if(d&&!d->dcsusp){d->dcss=c; jt->dbssd=d;} + else {d=0; jt->dbssd=0;} + R d; +} /* set dcss for next stack level */ + +static A jtssdo(J jt,A a,A w,C c){DC d,e;I n,*v; + RZ(w=vs(w)); + ASSERT(jt->db,EVDOMAIN); + d=jt->sitop; /* cut back to topmost suspension */ + while(d&&!d->dcsusp){ /* do until topmost suspension */ + if(d->dctype==DCCALL)*(I*)(d->dci)=-2; /* terminate each call */ + d=d->dclnk; + } + ASSERT(d,EVDOMAIN); /* must have a suspension */ + while(d&&DCCALL!=d->dctype)d=d->dclnk; /* find topmost call */ + ASSERT(d,EVDOMAIN); /* must have a call */ + if(a)RE(n=lnumcw(i0(a),d->dcc)); /* source line # to cw line # */ + v=(I*)d->dci; /* pointer to line # */ + jt->dbsusact=SUSSS; + switch(c){ + case SSSTEPOVER: if(a)*v=n-1; else --*v; jt->dbss=d->dcss=c; jt->dbssd=d; break; + case SSSTEPINTO: if(a)*v=n-1; else --*v; jt->dbss=d->dcss=c; jt->dbssd=d; break; + case SSSTEPOUT: if(a)*v=n-1; else --*v; jt->dbss=d->dcss=0; ssnext(d,c); break; + case SSCUTBACK: *v=-2; jt->dbss=d->dcss=0; e=ssnext(d,c); if(e)--*(I*)e->dci; + } + fa(jt->dbssexec); jt->dbssexec=AN(w)?ra(w):0; + R mtm; /* 0 return to terminate call */ +} + +F1(jtdbcutback ){R ssdo(0L,w,SSCUTBACK );} /* 13!:19 */ + +F1(jtdbstepover1){R ssdo(0L,w,SSSTEPOVER);} /* 13!:20 */ +F2(jtdbstepover2){R ssdo(a, w,SSSTEPOVER);} + +F1(jtdbstepinto1){R ssdo(0L,w,SSSTEPINTO);} /* 13!:21 */ +F2(jtdbstepinto2){R ssdo(a, w,SSSTEPINTO);} + +F1(jtdbstepout1 ){R ssdo(0L,w,SSSTEPOUT );} /* 13!:22 */ +F2(jtdbstepout2 ){R ssdo(a, w,SSSTEPOUT );} diff --git a/dstop.c b/dstop.c new file mode 100644 --- /dev/null +++ b/dstop.c @@ -0,0 +1,59 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Debug: Stops */ + +#include "j.h" +#include "d.h" + + +/* check for stop before each function line; return 1 if stop requested */ +/* 0 or more repetitions of the following patterns, separated by */ +/* abc*yz m:d all names beginning with abc and ending with yz; */ +/* monad line numbers and dyad line numbers (* means all). */ +/* ~abc*yz m:d don't stop */ + +static B stopsub(C*p,C*nw,I md){C*q,*s;I n; + s=strchr(p,';'); if(!s)s=p+strlen(p); + q=strchr(p,':'); if(!q||q>s)q=s; + if(2==md){p=q; q=s; if(':'==*p)++p;} + s=strchr(p,'*'); if(s&&q>s)R 1; + n=strlen(nw); + while(q>p){ + while(' '==*p)++p; + if(!strncmp(p,nw,n)&&(q==p+n||' '==*(p+n)))R 1; + while(q>p&&' '!=*p)++p; + } + R 0; +} + +B jtdbstop(J jt,DC d,I i){A a;B b,c=0,e;C nw[11],*s,*t,*u,*v;I md,n,p,q; + if(!jt->dbss&&d->dcss){d->dcss=0; jt->dbssd=0; c=i!=d->dcstop; d->dcstop=i; R c;} + switch(jt->dbss){ + case SSSTEPOVER: jt->dbss=0; break; + case SSSTEPINTO: jt->dbss=SSSTEPINTOs; break; + case SSSTEPINTOs: jt->dbss=0; if(jt->dbssd){jt->dbssd->dcss=0; jt->dbssd=0;} + c=i!=d->dcstop; d->dcstop=i; R c; + } + if(i==d->dcstop){d->dcstop=-2; R 0;} /* not stopping if already stopped at the same place */ + RZ(jt->dbstops); s=CAV(jt->dbstops); sprintf(nw,FMTI,i); + a=d->dca; n=d->dcm; t=NAV(a)->s; md=d->dcx&&d->dcy?2:1; + while(s){ + while(' '==*s)++s; if(b='~'==*s)++s; while(' '==*s)++s; + u=strchr(s,'*'); v=strchr(s,' '); if(!v)break;; + if(!u||u>v)e=!strncmp(s,t,MAX(n,v-s)); + else{p=u-s; q=v-u-1; e=p<=n&&!strncmp(s,t,p)&&q<=n&&!strncmp(1+u,t+n-q,q);} + if(e){s=1+v; if(stopsub(s,nw,md)){if(b){c=0; break;} c=1;}} + s=strchr(s,';'); if(s)++s; + } + if(c){d->dcstop=i; d->dcss=jt->dbss=0; if(jt->dbssd){jt->dbssd->dcss=0; jt->dbssd=0;}} + else d->dcstop=-2; + R c; +} /* stop on line i? */ + + +F1(jtdbstopq){ASSERTMTV(w); R jt->dbstops?jt->dbstops:mtv;} + /* 13!:2 query stops */ + +F1(jtdbstops){RZ(w=vs(w)); fa(jt->dbstops); jt->dbstops=AN(w)?ra(w):0; R mtm;} + /* 13!:3 set stops */ diff --git a/dsusp.c b/dsusp.c new file mode 100644 --- /dev/null +++ b/dsusp.c @@ -0,0 +1,232 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Debug: Suspension */ + +#include "j.h" +#include "d.h" +#include "w.h" + + +/* deba() and debz() must be coded and executed in pairs */ +/* in particular, do NOT do error exits between them */ +/* e.g. the following is a NO NO: */ +/* d=deba(...); */ +/* ASSERT(blah,EVDOMAIN); */ +/* debz() */ + +DC jtdeba(J jt,C t,A x,A y,A fs){A q;DC d; + GA(q,LIT,sizeof(DST),1,0); d=(DC)AV(q); + memset(d,C0,sizeof(DST)); + d->dctype=t; d->dclnk=jt->sitop; jt->sitop=d; + switch(t){ + case DCPARSE: d->dcy=y; break; + case DCSCRIPT: d->dcy=y; d->dcm=(I)fs; break; + case DCCALL: + d->dcx=x; d->dcy=y; d->dcf=fs; + d->dca=jt->curname; d->dcm=NAV(jt->curname)->m; + d->dcn=(I)jt->cursymb; + d->dcstop=-2; + if(jt->dbss==SSSTEPINTO){d->dcss=SSSTEPINTO; jt->dbssd=d; jt->dbss=0;} + } + R d; +} /* create new top of si stack */ + +void jtdebz(J jt){jt->sitop=jt->sitop->dclnk;} + /* remove top of si stack */ + +F1(jtsiinfo){A z,*zv;DC d;I c=5,n,*s; + ASSERTMTV(w); + n=0; d=jt->sitop; while(d){++n; d=d->dclnk;} + GA(z,BOX,c*n,2,0); s=AS(z); s[0]=n; s[1]=c; zv=AAV(z); + d=jt->sitop; + while(d){ + RZ(zv[0]=sc(d->dctype)); + RZ(zv[1]=d->dcsusp?scc('*'):scc(' ')); + RZ(zv[2]=sc((I)d->dcss)); + RZ(zv[3]=d->dctype==DCCALL?sc(lnumsi(d)):mtv); + switch(d->dctype){ + case DCPARSE: RZ(zv[4]=unparse(d->dcy)); break; + case DCCALL: RZ(zv[4]=sfn(0,d->dca)); break; + case DCSCRIPT: zv[4]=d->dcy; break; + case DCJUNK: zv[4]=mtv; break; + } + zv+=c; d=d->dclnk; + } + R z; +} /* 13!:32 si info */ + +I lnumcw(I j,A w){CW*u; + if(0>j)R -2; + else if(!w)R j; + else{u=(CW*)AV(w); DO(AN(w), if(j<=u[i].source)R i;) R IMAX/2;} +} /* line number in CW corresp. to j */ + +I lnumsi(DC d){A c;I i; + if(c=d->dcc){i=*(I*)d->dci; R(MIN(i,AN(c)-1)+(CW*)AV(c))->source;}else R 0; +} /* source line number from stack entry */ + + + +static DC suspset(DC d){DC e; + while(d&&DCCALL!=d->dctype){e=d; d=d->dclnk;} /* find topmost call */ + if(!(d&&DCCALL==d->dctype))R 0; /* don't suspend if no such call */ + if(d->dcc)e->dcsusp=1; /* if explicit, set susp on line */ + else d->dcsusp=1; /* if not explicit, set susp on call */ + R d; +} /* find topmost call and set suspension flag */ + +static B jterrcap(J jt){A y,*yv; + jt->dbsusact=SUSCLEAR; + GA(y,BOX,4,1,0); yv=AAV(y); + RZ(yv[0]=sc(jt->jerr1)); + RZ(yv[1]=str(jt->etxn1,jt->etx)); + RZ(yv[2]=dbcall(mtv)); + RZ(yv[3]=locname(mtv)); + RZ(symbis(nfs(22L,"STACK_ERROR_INFO_base_"),y,mark)); + R 1; +} /* error capture */ + +static void jtsusp(J jt){B t;DC d;I old=jt->tbase+jt->ttop; + jt->dbsusact=SUSCONT; + d=jt->dcs; t=jt->tostdout; + jt->dcs=0; jt->tostdout=1; + jt->fdepn =MIN(NFDEP ,jt->fdepn +NFDEP /10); + jt->fcalln=MIN(NFCALL,jt->fcalln+NFCALL/10); + if (jt->dbssexec){RESETERR; immex(jt->dbssexec); tpop(old);} + else if(jt->dbtrap ){RESETERR; immex(jt->dbtrap ); tpop(old);} + while(jt->dbsusact==SUSCONT){ + jt->jerr=0; + if(jt->iepdo&&jt->iep){jt->iepdo=0; immex(jt->iep); tpop(old);} + immex(jgets(" ")); + tpop(old); + } + if(jt->dbuser){jt->fdepn-=NFDEP/10; jt->fcalln-=NFCALL/10;} + else {jt->fdepn =NFDEP; jt->fcalln =NFCALL; } + jt->dcs=d; jt->tostdout=t; +} /* user keyboard loop while suspended */ + +static A jtdebug(J jt){A z=0;C e;DC c,d;I*v; + if(jt->dbssd){jt->dbssd->dcss=0; jt->dbssd=0;} + RZ(d=suspset(jt->sitop)); + v=(I*)d->dci; + if(0>*v)R 0; + e=jt->jerr; jt->jerr=0; + if(DBERRCAP==jt->db)errcap(); else susp(); + switch(jt->dbsusact){ + case SUSRUN: + --*v; break; + case SUSRET: + *v=-2; z=jt->dbresult; jt->dbresult=0; break; + case SUSJUMP: + *v=lnumcw(jt->dbjump,d->dcc)-1; break; + case SUSCLEAR: + jt->jerr=e; + c=jt->sitop; + while(c){if(DCCALL==c->dctype)*(I*)(c->dci)=-2; c=c->dclnk;} + } + if(jt->dbsusact!=SUSCLEAR)jt->dbsusact=SUSCONT; + d->dcsusp=0; + R z; +} + + +static A jtparseas(J jt,B as,A w){A*u,*v,y,z;I n; + n=AN(w); v=AAV(w); + GA(y,BOX,5+n,1,0); u=AAV(y); + *u++=mark; DO(n, *u++=*v++;); *u++=mark; *u++=mark; *u++=mark; *u++=mark; + z=parsea(y); /* y is destroyed by parsea */ + if(as&&z)ASSERT(NOUN&AT(z)&&all1(eq(one,z)),EVASSERT); + R z; +} + +/* parsex: parse an explicit defn line */ +/* w - line to be parsed */ +/* lk - 1 iff locked function */ +/* ci - current row of control matrix */ +/* c - stack entry for dbunquote for this function */ + +A jtparsex(J jt,A w,B lk,CW*ci,DC c){A z;B as,s;DC d,t=jt->sitop; + RZ(w); + JATTN; + as=ci->type==CASSERT; + if(lk)R parseas(as,w); + RZ(d=deba(DCPARSE,0L,w,0L)); + if(0==c)z=parseas(as,w); /* anonymous or not debug */ + else{ /* named and debug */ + if(s=dbstop(c,ci->source)){z=0; jsignal(EVSTOP);} + else {z=parseas(as,w); } + if(!z&&(s||DBTRY!=jt->db)){t->dcj=d->dcj=jt->jerr; z=debug(); t->dcj=0;} + } + debz(); + R z; +} + +DF2(jtdbunquote){A t,z;B b=0,s;DC d;I i;V*sv; + sv=VAV(self); t=sv->f; + RZ(d=deba(DCCALL,a,w,self)); + if(CCOLON==sv->id&&t&&NOUN&AT(t)){ /* explicit */ + ra(self); z=a?dfs2(a,w,self):dfs1(w,self); fa(self); + }else{ /* tacit */ + i=0; d->dci=(I)&i; + while(0==i){ + if(s=dbstop(d,0L)){z=0; jsignal(EVSTOP);} + else {ra(self); z=a?dfs2(a,w,self):dfs1(w,self); fa(self);} + if(!z&&(s||DBTRY!=jt->db)){d->dcj=jt->jerr; z=debug(); if(self!=jt->sitop->dcf)self=jt->sitop->dcf;} + if(b){fa(a); fa(w);} + if(b=jt->dbalpha||jt->dbomega){a=jt->dbalpha; w=jt->dbomega; jt->dbalpha=jt->dbomega=0;} + ++i; + } + } + if(d->dcss)ssnext(d,d->dcss); + if(jt->dbss==SSSTEPINTOs)jt->dbss=0; + debz(); + R z; +} /* function call, debug version */ + + +F1(jtdbc){I k; + RZ(w); + if(AN(w)){ + RE(k=i0(w)); + ASSERT(!k||k==DB1||k==DBERRCAP,EVDOMAIN); + ASSERT(!k||!jt->glock,EVDOMAIN); + } + jt->redefined=0; + if(AN(w)){jt->db=jt->dbuser=k; jt->fdepn=NFDEP/(k?2:1); jt->fcalln=NFCALL/(k?2:1);} + jt->dbsusact=SUSCLEAR; + R mtm; +} /* 13!:0 clear stack; enable/disable suspension */ + +F1(jtdbq){ASSERTMTV(w); R sc(jt->dbuser);} + /* 13!:17 debug flag */ + +F1(jtdbrun ){ASSERTMTV(w); jt->dbsusact=SUSRUN; R mtm;} + /* 13!:4 run again */ + +F1(jtdbnext){ASSERTMTV(w); jt->dbsusact=SUSNEXT; R mtm;} + /* 13!:5 run next */ + +F1(jtdbret ){RZ(w); jt->dbsusact=SUSRET; jt->dbresult=ra(w); R mtm;} + /* 13!:6 exit with result */ + +F1(jtdbjump){RE(jt->dbjump=i0(w)); jt->dbsusact=SUSJUMP; R mtm;} + /* 13!:7 resume at line n (return result error if out of range) */ + +static F2(jtdbrr){DC d; + RE(0); + d=jt->sitop; while(d&&DCCALL!=d->dctype)d=d->dclnk; + ASSERT(d&&VERB&AT(d->dcf)&&!d->dcc,EVDOMAIN); /* must be explicit verb */ + jt->dbalpha=ra(a); jt->dbomega=ra(w); + jt->dbsusact=SUSRUN; + R mtm; +} + +F1(jtdbrr1 ){R dbrr(0L,w);} /* 13!:9 re-run with arg(s) */ +F2(jtdbrr2 ){R dbrr(a, w);} + +F1(jtdbtrapq){ASSERTMTV(w); R jt->dbtrap?jt->dbtrap:mtv;} + /* 13!:14 query trap */ + +F1(jtdbtraps){RZ(w=vs(w)); fa(jt->dbtrap); jt->dbtrap=AN(w)?ra(w):0L; R mtm;} + /* 13!:15 set trap */ diff --git a/dtoa.c b/dtoa.c new file mode 100644 --- /dev/null +++ b/dtoa.c @@ -0,0 +1,3430 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* Jsoftware Copyright applies only to changes made by Jsoftware */ +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +/* On a machine with IEEE extended-precision registers, it is + * necessary to specify double-precision (53-bit) rounding precision + * before invoking strtod or dtoa. If the machine uses (the equivalent + * of) Intel 80x87 arithmetic, the call + * _control87(PC_53, MCW_PC); + * does this with many compilers. Whether this or another call is + * appropriate depends on the compiler; for this to work, it may be + * necessary to #include "float.h" or another system-dependent header + * file. + */ + +/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. + * + * This strtod returns a nearest machine number to the input decimal + * string (or sets errno to ERANGE). With IEEE arithmetic, ties are + * broken by the IEEE round-even rule. Otherwise ties are broken by + * biased rounding (add half and chop). + * + * Inspired loosely by William D. Clinger's paper "How to Read Floating + * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * + * 1. We only require IEEE, IBM, or VAX double-precision + * arithmetic (not IEEE double-extended). + * 2. We get by with floating-point arithmetic in a case that + * Clinger missed -- when we're computing d * 10^n + * for a small integer d and the integer n is not too + * much larger than 22 (the maximum integer k for which + * we can represent 10^k exactly), we may be able to + * compute (d*10^k) * 10^(e-k) with just one roundoff. + * 3. Rather than a bit-at-a-time adjustment of the binary + * result in the hard case, we use floating-point + * arithmetic to determine the adjustment to within + * one bit; only in really hard cases do we need to + * compute a second residual. + * 4. Because of 3., we don't need a large table of powers of 10 + * for ten-to-e (just some small tables, e.g. of 10^k + * for 0 <= k <= 22). + */ + +/* + * #define IEEE_8087 for IEEE-arithmetic machines where the least + * significant byte has the lowest address. + * #define IEEE_MC68k for IEEE-arithmetic machines where the most + * significant byte has the lowest address. + * #define Long int on machines with 32-bit ints and 64-bit longs. + * #define IBM for IBM mainframe-style floating-point arithmetic. + * #define VAX for VAX-style floating-point arithmetic (D_floating). + * #define No_leftright to omit left-right logic in fast floating-point + * computation of dtoa. + * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 + * and strtod and dtoa should round accordingly. + * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 + * and Honor_FLT_ROUNDS is not #defined. + * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines + * that use extended-precision instructions to compute rounded + * products and quotients) with IBM. + * #define ROUND_BIASED for IEEE-format with biased rounding. + * #define Inaccurate_Divide for IEEE-format with correctly rounded + * products but inaccurate quotients, e.g., for Intel i860. + * #define NO_LONG_LONG on machines that do not have a "long long" + * integer type (of >= 64 bits). On such machines, you can + * #define Just_16 to store 16 bits per 32-bit Long when doing + * high-precision integer arithmetic. Whether this speeds things + * up or slows things down depends on the machine and the number + * being converted. If long long is available and the name is + * something other than "long long", #define Llong to be the name, + * and if "unsigned Llong" does not work as an unsigned version of + * Llong, #define #ULLong to be the corresponding unsigned type. + * #define KR_headers for old-style C function headers. + * #define Bad_float_h if your system lacks a float.h or if it does not + * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, + * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. + * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) + * if memory is available and otherwise does something you deem + * appropriate. If MALLOC is undefined, malloc will be invoked + * directly -- and assumed always to succeed. + * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making + * memory allocations from a private pool of memory when possible. + * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, + * unless #defined to be a different length. This default length + * suffices to get rid of MALLOC calls except for unusual cases, + * such as decimal-to-binary conversion of a very long string of + * digits. The longest string dtoa can return is about 751 bytes + * long. For conversions by strtod of strings of 800 digits and + * all dtoa conversions in single-threaded executions with 8-byte + * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte + * pointers, PRIVATE_MEM >= 7112 appears adequate. + * #define INFNAN_CHECK on IEEE systems to cause strtod to check for + * Infinity and NaN (case insensitively). On some systems (e.g., + * some HP systems), it may be necessary to #define NAN_WORD0 + * appropriately -- to the most significant word of a quiet NaN. + * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) + * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, + * strtod also accepts (case insensitively) strings of the form + * NaN(x), where x is a string of hexadecimal digits and spaces; + * if there is only one string of hexadecimal digits, it is taken + * for the 52 fraction bits of the resulting NaN; if there are two + * or more strings of hex digits, the first is for the high 20 bits, + * the second and subsequent for the low 32 bits, with intervening + * white space ignored; but if this results in none of the 52 + * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0 + * and NAN_WORD1 are used instead. + * #define MULTIPLE_THREADS if the system offers preemptively scheduled + * multiple threads. In this case, you must provide (or suitably + * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed + * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed + * in pow5mult, ensures lazy evaluation of only one copy of high + * powers of 5; omitting this lock would introduce a small + * probability of wasting memory, but would otherwise be harmless.) + * You must also invoke freedtoa(s) to free the value s returned by + * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. + * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that + * avoids underflows on inputs whose result does not underflow. + * If you #define NO_IEEE_Scale on a machine that uses IEEE-format + * floating-point numbers and flushes underflows to zero rather + * than implementing gradual underflow, then you must also #define + * Sudden_Underflow. + * #define YES_ALIAS to permit aliasing certain double values with + * arrays of ULongs. This leads to slightly better code with + * some compilers and was always used prior to 19990916, but it + * is not strictly legal and can cause trouble with aggressively + * optimizing compilers (e.g., gcc 2.95.1 under -O2). + * #define USE_LOCALE to use the current locale's decimal_point value. + * #define SET_INEXACT if IEEE arithmetic is being used and extra + * computation should be done to set the inexact flag when the + * result is inexact and avoid setting inexact when the result + * is exact. In this case, dtoa.c must be compiled in + * an environment, perhaps provided by #include "dtoa.c" in a + * suitable wrapper, that defines two functions, + * int get_inexact(void); + * void clear_inexact(void); + * such that get_inexact() returns a nonzero value if the + * inexact bit is already set, and clear_inexact() sets the + * inexact bit to 0. When SET_INEXACT is #defined, strtod + * also does extra computations to set the underflow and overflow + * flags when appropriate (i.e., when the result is tiny and + * inexact or when it is a numeric value rounded to +-infinity). + * #define NO_ERRNO if strtod should not assign errno = ERANGE when + * the result overflows to +-Infinity or underflows to 0. + */ + +/* Options for use with J */ +#include "js.h" +#define Long int +#if SYS & SYS_LILENDIAN +#define IEEE_8087 +#else +#define IEEE_MC68k +#endif +#define MULTIPLE_THREADS +#define ACQUIRE_DTOA_LOCK(n) /* handled by using jt */ +#define FREE_DTOA_LOCK(n) /* handled by using jt */ +/* #define Omit_Private_Memory */ +#define PRIVATE_MEM 8000 +#define Use_J_Memory +#if SY_WIN32 +#define Llong __int64 +#endif + +#ifndef Long +#define Long long +#endif +#ifndef ULong +typedef unsigned Long ULong; +#endif + +#ifdef DEBUG +#include "stdio.h" +#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} +#endif + +#include "stdlib.h" +#include "string.h" + +#ifdef USE_LOCALE +#include "locale.h" +#endif + +#if 0 +#ifdef MALLOC +#ifdef KR_headers +extern char *MALLOC(); +#else +extern void *MALLOC(size_t); +#endif +#else +#define MALLOC malloc +#endif +#endif + +#ifndef Omit_Private_Memory +#ifndef PRIVATE_MEM +#define PRIVATE_MEM 2304 +#endif +#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) +#ifndef Use_J_Memory +static double private_mem[PRIVATE_mem], *pmem_next = private_mem; +#endif +#endif + +#undef IEEE_Arith +#undef Avoid_Underflow +#ifdef IEEE_MC68k +#define IEEE_Arith +#endif +#ifdef IEEE_8087 +#define IEEE_Arith +#endif + +#ifdef Bad_float_h + +#ifdef IEEE_Arith +#define DBL_DIG 15 +#define DBL_MAX_10_EXP 308 +#define DBL_MAX_EXP 1024 +#define FLT_RADIX 2 +#endif /*IEEE_Arith*/ + +#ifdef IBM +#define DBL_DIG 16 +#define DBL_MAX_10_EXP 75 +#define DBL_MAX_EXP 63 +#define FLT_RADIX 16 +#define DBL_MAX 7.2370055773322621e+75 +#endif + +#ifdef VAX +#define DBL_DIG 16 +#define DBL_MAX_10_EXP 38 +#define DBL_MAX_EXP 127 +#define FLT_RADIX 2 +#define DBL_MAX 1.7014118346046923e+38 +#endif + +#ifndef LONG_MAX +#define LONG_MAX 2147483647 +#endif + +#else /* ifndef Bad_float_h */ +#include "float.h" +#endif /* Bad_float_h */ + +#ifndef __MATH_H__ +#include "math.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CONST +#ifdef KR_headers +#define CONST /* blank */ +#else +#define CONST const +#endif +#endif + +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 +Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +#endif + +typedef union { double d; ULong L[2]; } U; + +#ifdef YES_ALIAS +#define dval(x) x +#ifdef IEEE_8087 +#define word0(x) ((ULong *)&x)[1] +#define word1(x) ((ULong *)&x)[0] +#else +#define word0(x) ((ULong *)&x)[0] +#define word1(x) ((ULong *)&x)[1] +#endif +#else +#ifdef IEEE_8087 +#define word0(x) ((U*)&x)->L[1] +#define word1(x) ((U*)&x)->L[0] +#else +#define word0(x) ((U*)&x)->L[0] +#define word1(x) ((U*)&x)->L[1] +#endif +#define dval(x) ((U*)&x)->d +#endif + +/* The following definition of Storeinc is appropriate for MIPS processors. + * An alternative that might be better on some machines is + * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) + */ +#if defined(IEEE_8087) + defined(VAX) +#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ +((unsigned short *)a)[0] = (unsigned short)c, a++) +#else +#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ +((unsigned short *)a)[1] = (unsigned short)c, a++) +#endif + +/* #define P DBL_MANT_DIG */ +/* Ten_pmax = floor(P*log(2)/log(5)) */ +/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ +/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ +/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ + +#ifdef IEEE_Arith +#define Exp_shift 20 +#define Exp_shift1 20 +#define Exp_msk1 0x100000 +#define Exp_msk11 0x100000 +#define Exp_mask 0x7ff00000 +#define P 53 +#define Bias 1023 +#define Emin (-1022) +#define Exp_1 0x3ff00000 +#define Exp_11 0x3ff00000 +#define Ebits 11 +#define Frac_mask 0xfffff +#define Frac_mask1 0xfffff +#define Ten_pmax 22 +#define Bletch 0x10 +#define Bndry_mask 0xfffff +#define Bndry_mask1 0xfffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 14 +#define Int_max 14 +#ifndef NO_IEEE_Scale +#define Avoid_Underflow +#ifdef Flush_Denorm /* debugging option */ +#undef Sudden_Underflow +#endif +#endif + +#ifndef Flt_Rounds +#ifdef FLT_ROUNDS +#define Flt_Rounds FLT_ROUNDS +#else +#define Flt_Rounds 1 +#endif +#endif /*Flt_Rounds*/ + +#ifdef Honor_FLT_ROUNDS +#define Rounding rounding +#undef Check_FLT_ROUNDS +#define Check_FLT_ROUNDS +#else +#define Rounding Flt_Rounds +#endif + +#else /* ifndef IEEE_Arith */ +#undef Check_FLT_ROUNDS +#undef Honor_FLT_ROUNDS +#undef SET_INEXACT +#undef Sudden_Underflow +#define Sudden_Underflow +#ifdef IBM +#undef Flt_Rounds +#define Flt_Rounds 0 +#define Exp_shift 24 +#define Exp_shift1 24 +#define Exp_msk1 0x1000000 +#define Exp_msk11 0x1000000 +#define Exp_mask 0x7f000000 +#define P 14 +#define Bias 65 +#define Exp_1 0x41000000 +#define Exp_11 0x41000000 +#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ +#define Frac_mask 0xffffff +#define Frac_mask1 0xffffff +#define Bletch 4 +#define Ten_pmax 22 +#define Bndry_mask 0xefffff +#define Bndry_mask1 0xffffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 4 +#define Tiny0 0x100000 +#define Tiny1 0 +#define Quick_max 14 +#define Int_max 15 +#else /* VAX */ +#undef Flt_Rounds +#define Flt_Rounds 1 +#define Exp_shift 23 +#define Exp_shift1 7 +#define Exp_msk1 0x80 +#define Exp_msk11 0x800000 +#define Exp_mask 0x7f80 +#define P 56 +#define Bias 129 +#define Exp_1 0x40800000 +#define Exp_11 0x4080 +#define Ebits 8 +#define Frac_mask 0x7fffff +#define Frac_mask1 0xffff007f +#define Ten_pmax 24 +#define Bletch 2 +#define Bndry_mask 0xffff007f +#define Bndry_mask1 0xffff007f +#define LSB 0x10000 +#define Sign_bit 0x8000 +#define Log2P 1 +#define Tiny0 0x80 +#define Tiny1 0 +#define Quick_max 15 +#define Int_max 15 +#endif /* IBM, VAX */ +#endif /* IEEE_Arith */ + +#ifndef IEEE_Arith +#define ROUND_BIASED +#endif + +#ifdef RND_PRODQUOT +#define rounded_product(a,b) a = rnd_prod(a, b) +#define rounded_quotient(a,b) a = rnd_quot(a, b) +#ifdef KR_headers +extern double rnd_prod(), rnd_quot(); +#else +extern double rnd_prod(double, double), rnd_quot(double, double); +#endif +#else +#define rounded_product(a,b) a *= b +#define rounded_quotient(a,b) a /= b +#endif + +#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) +#define Big1 0xffffffff + +#ifndef Pack_32 +#define Pack_32 +#endif + +#ifdef KR_headers +#define FFFFFFFF ((((unsigned long)0xffff)<<16)|(unsigned long)0xffff) +#else +#define FFFFFFFF 0xffffffffUL +#endif + +#ifdef NO_LONG_LONG +#undef ULLong +#ifdef Just_16 +#undef Pack_32 +/* When Pack_32 is not defined, we store 16 bits per 32-bit Long. + * This makes some inner loops simpler and sometimes saves work + * during multiplications, but it often seems to make things slightly + * slower. Hence the default is now to store 32 bits per Long. + */ +#endif +#else /* long long available */ +#ifndef Llong +#define Llong long long +#endif +#ifndef ULLong +#define ULLong unsigned Llong +#endif +#endif /* NO_LONG_LONG */ + +#ifndef MULTIPLE_THREADS +#define ACQUIRE_DTOA_LOCK(n) /*nothing*/ +#define FREE_DTOA_LOCK(n) /*nothing*/ +#endif + +#define Kmax 15 + +#ifdef __cplusplus +#if 0 +extern "C" double strtod(const char *s00, char **se); +extern "C" char *dtoa(double d, int mode, int ndigits, + int *decpt, int *sign, char **rve); +#endif +#endif + + struct +Bigint { + struct Bigint *next; + int k, maxwds, sign, wds; + ULong x[1]; + }; + + typedef struct Bigint Bigint; +#define HAVE_BIGINT +#include "dtoa.h" + +#ifndef Use_J_Memory +Error! Code requires Use_J_Memory due to modifications. +#endif + +static void *d2a_Malloc(struct dtoa_info *d2a, int k); +static Bigint *d2a_Balloc(struct dtoa_info *d2a, int k); +static void d2a_Bfree(struct dtoa_info *d2a, Bigint *v); + +#define p5s (d2a->_p5s) +#define private_mem (d2a->_private_mem) +#define pmem_next (d2a->_pmem_next) +#define freelist (d2a->_freelist) + +#define MALLOC(n) d2a_Malloc(d2a, n) +#define Balloc(k) d2a_Balloc(d2a, k) +#define Bfree(v) d2a_Bfree(d2a, v) +#define multadd(b,m,a) d2a_multadd(d2a, b, m, a) +#define i2b(i) d2a_i2b(d2a, i) +#define mult(a,b) d2a_mult(d2a, a, b) +#define nrv_alloc(s,rve,n) d2a_nrv_alloc(d2a,s,rve,n) +#define rv_alloc(n) d2a_rv_alloc(d2a, n) +#define freedtoa(x) d2a_freedtoa(d2a, x) +#define d2b(d,e,b) d2a_d2b(d2a,d,e,b) +#define pow5mult(b,k) d2a_pow5mult(d2a,b,k) +#define diff(x,y) d2a_diff(d2a,x,y) +#define lshift(x,y) d2a_lshift(d2a,x,y) + +/* static Bigint *freelist[Kmax+1]; */ + + static Bigint * +d2a_Balloc +#ifdef KR_headers + (k) int k; +#else + (struct dtoa_info *d2a, int k) +#endif +{ + int x; + Bigint *rv; +#ifndef Omit_Private_Memory + unsigned int len; +#endif + + ACQUIRE_DTOA_LOCK(0); + if (rv = freelist[k]) { + freelist[k] = rv->next; + } + else { + x = 1 << k; +#ifdef Omit_Private_Memory + rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong)); +#else + len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) + /sizeof(double); + if (pmem_next - private_mem + len <= PRIVATE_mem) { + rv = (Bigint*)pmem_next; + pmem_next += len; + } + else + rv = (Bigint*)MALLOC(len*sizeof(double)); +#endif + rv->k = k; + rv->maxwds = x; + } + FREE_DTOA_LOCK(0); + rv->sign = rv->wds = 0; + return rv; + } + + static void +d2a_Bfree +#ifdef KR_headers + (v) Bigint *v; +#else + (struct dtoa_info *d2a, Bigint *v) +#endif +{ + if (v) { + ACQUIRE_DTOA_LOCK(0); + v->next = freelist[v->k]; + freelist[v->k] = v; + FREE_DTOA_LOCK(0); + } + } + +#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ +y->wds*sizeof(Long) + 2*sizeof(int)) + + static Bigint * +d2a_multadd +#ifdef KR_headers + (b, m, a) Bigint *b; int m, a; +#else + (struct dtoa_info *d2a, Bigint *b, int m, int a) /* multiply by m and add a */ +#endif +{ + int i, wds; +#ifdef ULLong + ULong *x; + ULLong carry, y; +#else + ULong carry, *x, y; +#ifdef Pack_32 + ULong xi, z; +#endif +#endif + Bigint *b1; + + wds = b->wds; + x = b->x; + i = 0; + carry = a; + do { +#ifdef ULLong + y = *x * (ULLong)m + carry; + carry = y >> 32; + *x++ = (ULong)(y & FFFFFFFF); +#else +#ifdef Pack_32 + xi = *x; + y = (xi & 0xffff) * m + carry; + z = (xi >> 16) * m + (y >> 16); + carry = z >> 16; + *x++ = (z << 16) + (y & 0xffff); +#else + y = *x * m + carry; + carry = y >> 16; + *x++ = y & 0xffff; +#endif +#endif + } + while(++i < wds); + if (carry) { + if (wds >= b->maxwds) { + b1 = Balloc(b->k+1); + Bcopy(b1, b); + Bfree(b); + b = b1; + } + b->x[wds++] = (ULong)carry; + b->wds = wds; + } + return b; + } + +#if 0 + static Bigint * +d2a_s2b +#ifdef KR_headers + (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9; +#else + (struct dtoa_info *d2a, CONST char *s, int nd0, int nd, ULong y9) +#endif +{ + Bigint *b; + int i, k; + Long x, y; + + x = (nd + 8) / 9; + for(k = 0, y = 1; x > y; y <<= 1, k++) ; +#ifdef Pack_32 + b = Balloc(k); + b->x[0] = y9; + b->wds = 1; +#else + b = Balloc(k+1); + b->x[0] = y9 & 0xffff; + b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; +#endif + + i = 9; + if (9 < nd0) { + s += 9; + do b = multadd(b, 10, *s++ - '0'); + while(++i < nd0); + s++; + } + else + s += 10; + for(; i < nd; i++) + b = multadd(b, 10, *s++ - '0'); + return b; + } +#endif + + static int +hi0bits +#ifdef KR_headers + (x) register ULong x; +#else + (register ULong x) +#endif +{ + register int k = 0; + + if (!(x & 0xffff0000)) { + k = 16; + x <<= 16; + } + if (!(x & 0xff000000)) { + k += 8; + x <<= 8; + } + if (!(x & 0xf0000000)) { + k += 4; + x <<= 4; + } + if (!(x & 0xc0000000)) { + k += 2; + x <<= 2; + } + if (!(x & 0x80000000)) { + k++; + if (!(x & 0x40000000)) + return 32; + } + return k; + } + + static int +lo0bits +#ifdef KR_headers + (y) ULong *y; +#else + (ULong *y) +#endif +{ + register int k; + register ULong x = *y; + + if (x & 7) { + if (x & 1) + return 0; + if (x & 2) { + *y = x >> 1; + return 1; + } + *y = x >> 2; + return 2; + } + k = 0; + if (!(x & 0xffff)) { + k = 16; + x >>= 16; + } + if (!(x & 0xff)) { + k += 8; + x >>= 8; + } + if (!(x & 0xf)) { + k += 4; + x >>= 4; + } + if (!(x & 0x3)) { + k += 2; + x >>= 2; + } + if (!(x & 1)) { + k++; + x >>= 1; + if (!x) + return 32; + } + *y = x; + return k; + } + + static Bigint * +d2a_i2b +#ifdef KR_headers + (i) int i; +#else + (struct dtoa_info *d2a, int i) +#endif +{ + Bigint *b; + + b = Balloc(1); + b->x[0] = i; + b->wds = 1; + return b; + } + + static Bigint * +d2a_mult +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (struct dtoa_info *d2a, Bigint *a, Bigint *b) +#endif +{ + Bigint *c; + int k, wa, wb, wc; + ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; + ULong y; +#ifdef ULLong + ULLong carry, z; +#else + ULong carry, z; +#ifdef Pack_32 + ULong z2; +#endif +#endif + + if (a->wds < b->wds) { + c = a; + a = b; + b = c; + } + k = a->k; + wa = a->wds; + wb = b->wds; + wc = wa + wb; + if (wc > a->maxwds) + k++; + c = Balloc(k); + for(x = c->x, xa = x + wc; x < xa; x++) + *x = 0; + xa = a->x; + xae = xa + wa; + xb = b->x; + xbe = xb + wb; + xc0 = c->x; +#ifdef ULLong + for(; xb < xbe; xc0++) { + if (y = *xb++) { + x = xa; + xc = xc0; + carry = 0; + do { + z = *x++ * (ULLong)y + *xc + carry; + carry = z >> 32; + *xc++ = (ULong)(z & FFFFFFFF); + } + while(x < xae); + *xc = (ULong)carry; + } + } +#else +#ifdef Pack_32 + for(; xb < xbe; xb++, xc0++) { + if (y = *xb & 0xffff) { + x = xa; + xc = xc0; + carry = 0; + do { + z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; + carry = z >> 16; + z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; + carry = z2 >> 16; + Storeinc(xc, z2, z); + } + while(x < xae); + *xc = carry; + } + if (y = *xb >> 16) { + x = xa; + xc = xc0; + carry = 0; + z2 = *xc; + do { + z = (*x & 0xffff) * y + (*xc >> 16) + carry; + carry = z >> 16; + Storeinc(xc, z, z2); + z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; + carry = z2 >> 16; + } + while(x < xae); + *xc = z2; + } + } +#else + for(; xb < xbe; xc0++) { + if (y = *xb++) { + x = xa; + xc = xc0; + carry = 0; + do { + z = *x++ * y + *xc + carry; + carry = z >> 16; + *xc++ = z & 0xffff; + } + while(x < xae); + *xc = carry; + } + } +#endif +#endif + for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; + c->wds = wc; + return c; + } + +#ifndef Use_J_Memory + static Bigint *p5s; +#endif + + static Bigint * +d2a_pow5mult +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (struct dtoa_info *d2a, Bigint *b, int k) +#endif +{ + Bigint *b1, *p5, *p51; + int i; + static const int p05[3] = { 5, 25, 125 }; + + if (i = k & 3) + b = multadd(b, p05[i-1], 0); + + if (!(k >>= 2)) + return b; + if (!(p5 = p5s)) { + /* first time */ +#ifdef MULTIPLE_THREADS + ACQUIRE_DTOA_LOCK(1); + if (!(p5 = p5s)) { + p5 = p5s = i2b(625); + p5->next = 0; + } + FREE_DTOA_LOCK(1); +#else + p5 = p5s = i2b(625); + p5->next = 0; +#endif + } + for(;;) { + if (k & 1) { + b1 = mult(b, p5); + Bfree(b); + b = b1; + } + if (!(k >>= 1)) + break; + if (!(p51 = p5->next)) { +#ifdef MULTIPLE_THREADS + ACQUIRE_DTOA_LOCK(1); + if (!(p51 = p5->next)) { + p51 = p5->next = mult(p5,p5); + p51->next = 0; + } + FREE_DTOA_LOCK(1); +#else + p51 = p5->next = mult(p5,p5); + p51->next = 0; +#endif + } + p5 = p51; + } + return b; + } + + static Bigint * +d2a_lshift +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (struct dtoa_info *d2a, Bigint *b, int k) +#endif +{ + int i, k1, n, n1; + Bigint *b1; + ULong *x, *x1, *xe, z; + +#ifdef Pack_32 + n = k >> 5; +#else + n = k >> 4; +#endif + k1 = b->k; + n1 = n + b->wds + 1; + for(i = b->maxwds; n1 > i; i <<= 1) + k1++; + b1 = Balloc(k1); + x1 = b1->x; + for(i = 0; i < n; i++) + *x1++ = 0; + x = b->x; + xe = x + b->wds; +#ifdef Pack_32 + if (k &= 0x1f) { + k1 = 32 - k; + z = 0; + do { + *x1++ = *x << k | z; + z = *x++ >> k1; + } + while(x < xe); + if (*x1 = z) + ++n1; + } +#else + if (k &= 0xf) { + k1 = 16 - k; + z = 0; + do { + *x1++ = *x << k & 0xffff | z; + z = *x++ >> k1; + } + while(x < xe); + if (*x1 = z) + ++n1; + } +#endif + else do + *x1++ = *x++; + while(x < xe); + b1->wds = n1 - 1; + Bfree(b); + return b1; + } + + static int +cmp +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + ULong *xa, *xa0, *xb, *xb0; + int i, j; + + i = a->wds; + j = b->wds; +#ifdef DEBUG + if (i > 1 && !a->x[i-1]) + Bug("cmp called with a->x[a->wds-1] == 0"); + if (j > 1 && !b->x[j-1]) + Bug("cmp called with b->x[b->wds-1] == 0"); +#endif + if (i -= j) + return i; + xa0 = a->x; + xa = xa0 + j; + xb0 = b->x; + xb = xb0 + j; + for(;;) { + if (*--xa != *--xb) + return *xa < *xb ? -1 : 1; + if (xa <= xa0) + break; + } + return 0; + } + + static Bigint * +d2a_diff +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (struct dtoa_info *d2a, Bigint *a, Bigint *b) +#endif +{ + Bigint *c; + int i, wa, wb; + ULong *xa, *xae, *xb, *xbe, *xc; +#ifdef ULLong + ULLong borrow, y; +#else + ULong borrow, y; +#ifdef Pack_32 + ULong z; +#endif +#endif + + i = cmp(a,b); + if (!i) { + c = Balloc(0); + c->wds = 1; + c->x[0] = 0; + return c; + } + if (i < 0) { + c = a; + a = b; + b = c; + i = 1; + } + else + i = 0; + c = Balloc(a->k); + c->sign = i; + wa = a->wds; + xa = a->x; + xae = xa + wa; + wb = b->wds; + xb = b->x; + xbe = xb + wb; + xc = c->x; + borrow = 0; +#ifdef ULLong + do { + y = (ULLong)*xa++ - *xb++ - borrow; + borrow = y >> 32 & (ULong)1; + *xc++ = (ULong)(y & FFFFFFFF); + } + while(xb < xbe); + while(xa < xae) { + y = *xa++ - borrow; + borrow = y >> 32 & (ULong)1; + *xc++ = (ULong)(y & FFFFFFFF); + } +#else +#ifdef Pack_32 + do { + y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(xc, z, y); + } + while(xb < xbe); + while(xa < xae) { + y = (*xa & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*xa++ >> 16) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(xc, z, y); + } +#else + do { + y = *xa++ - *xb++ - borrow; + borrow = (y & 0x10000) >> 16; + *xc++ = y & 0xffff; + } + while(xb < xbe); + while(xa < xae) { + y = *xa++ - borrow; + borrow = (y & 0x10000) >> 16; + *xc++ = y & 0xffff; + } +#endif +#endif + while(!*--xc) + wa--; + c->wds = wa; + return c; + } + +#if 0 + static double +ulp +#ifdef KR_headers + (x) double x; +#else + (double x) +#endif +{ + register Long L; + double a; + + L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; +#ifndef Avoid_Underflow +#ifndef Sudden_Underflow + if (L > 0) { +#endif +#endif +#ifdef IBM + L |= Exp_msk1 >> 4; +#endif + word0(a) = L; + word1(a) = 0; +#ifndef Avoid_Underflow +#ifndef Sudden_Underflow + } + else { + L = -L >> Exp_shift; + if (L < Exp_shift) { + word0(a) = 0x80000 >> L; + word1(a) = 0; + } + else { + word0(a) = 0; + L -= Exp_shift; + word1(a) = L >= 31 ? 1 : 1 << 31 - L; + } + } +#endif +#endif + return dval(a); + } + + static double +b2d +#ifdef KR_headers + (a, e) Bigint *a; int *e; +#else + (Bigint *a, int *e) +#endif +{ + ULong *xa, *xa0, w, y, z; + int k; + double d; +#ifdef VAX + ULong d0, d1; +#else +#define d0 word0(d) +#define d1 word1(d) +#endif + + xa0 = a->x; + xa = xa0 + a->wds; + y = *--xa; +#ifdef DEBUG + if (!y) Bug("zero y in b2d"); +#endif + k = hi0bits(y); + *e = 32 - k; +#ifdef Pack_32 + if (k < Ebits) { + d0 = Exp_1 | y >> (Ebits - k); + w = xa > xa0 ? *--xa : 0; + d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + if (k -= Ebits) { + d0 = Exp_1 | y << k | z >> (32 - k); + y = xa > xa0 ? *--xa : 0; + d1 = z << k | y >> (32 - k); + } + else { + d0 = Exp_1 | y; + d1 = z; + } +#else + if (k < Ebits + 16) { + z = xa > xa0 ? *--xa : 0; + d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; + w = xa > xa0 ? *--xa : 0; + y = xa > xa0 ? *--xa : 0; + d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + w = xa > xa0 ? *--xa : 0; + k -= Ebits + 16; + d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; + y = xa > xa0 ? *--xa : 0; + d1 = w << k + 16 | y << k; +#endif + ret_d: +#ifdef VAX + word0(d) = d0 >> 16 | d0 << 16; + word1(d) = d1 >> 16 | d1 << 16; +#else +#undef d0 +#undef d1 +#endif + return dval(d); + } +#endif + + static Bigint * +d2a_d2b +#ifdef KR_headers + (d, e, bits) double d; int *e, *bits; +#else + (struct dtoa_info *d2a, double d, int *e, int *bits) +#endif +{ + Bigint *b; + int de, k; + ULong *x, y, z; +#ifndef Sudden_Underflow + int i; +#endif +#ifdef VAX + ULong d0, d1; + d0 = word0(d) >> 16 | word0(d) << 16; + d1 = word1(d) >> 16 | word1(d) << 16; +#else +#define d0 word0(d) +#define d1 word1(d) +#endif + +#ifdef Pack_32 + b = Balloc(1); +#else + b = Balloc(2); +#endif + x = b->x; + + z = d0 & Frac_mask; + d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ +#ifdef Sudden_Underflow + de = (int)(d0 >> Exp_shift); +#ifndef IBM + z |= Exp_msk11; +#endif +#else + if (de = (int)(d0 >> Exp_shift)) + z |= Exp_msk1; +#endif +#ifdef Pack_32 + if (y = d1) { + if (k = lo0bits(&y)) { + x[0] = y | z << (32 - k); + z >>= k; + } + else + x[0] = y; +#ifndef Sudden_Underflow + i = +#endif + b->wds = (x[1] = z) ? 2 : 1; + } + else { +#ifdef DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + x[0] = z; +#ifndef Sudden_Underflow + i = +#endif + b->wds = 1; + k += 32; + } +#else + if (y = d1) { + if (k = lo0bits(&y)) + if (k >= 16) { + x[0] = y | z << 32 - k & 0xffff; + x[1] = z >> k - 16 & 0xffff; + x[2] = z >> k; + i = 2; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16 | z << 16 - k & 0xffff; + x[2] = z >> k & 0xffff; + x[3] = z >> k+16; + i = 3; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16; + x[2] = z & 0xffff; + x[3] = z >> 16; + i = 3; + } + } + else { +#ifdef DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + if (k >= 16) { + x[0] = z; + i = 0; + } + else { + x[0] = z & 0xffff; + x[1] = z >> 16; + i = 1; + } + k += 32; + } + while(!x[i]) + --i; + b->wds = i + 1; +#endif +#ifndef Sudden_Underflow + if (de) { +#endif +#ifdef IBM + *e = (de - Bias - (P-1) << 2) + k; + *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); +#else + *e = de - Bias - (P-1) + k; + *bits = P - k; +#endif +#ifndef Sudden_Underflow + } + else { + *e = de - Bias - (P-1) + 1 + k; +#ifdef Pack_32 + *bits = 32*i - hi0bits(x[i-1]); +#else + *bits = (i+2)*16 - hi0bits(x[i]); +#endif + } +#endif + return b; + } +#undef d0 +#undef d1 + +#if 0 + static double +ratio +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + double da, db; + int k, ka, kb; + + dval(da) = b2d(a, &ka); + dval(db) = b2d(b, &kb); +#ifdef Pack_32 + k = ka - kb + 32*(a->wds - b->wds); +#else + k = ka - kb + 16*(a->wds - b->wds); +#endif +#ifdef IBM + if (k > 0) { + word0(da) += (k >> 2)*Exp_msk1; + if (k &= 3) + dval(da) *= 1 << k; + } + else { + k = -k; + word0(db) += (k >> 2)*Exp_msk1; + if (k &= 3) + dval(db) *= 1 << k; + } +#else + if (k > 0) + word0(da) += k*Exp_msk1; + else { + k = -k; + word0(db) += k*Exp_msk1; + } +#endif + return dval(da) / dval(db); + } +#endif + + static CONST double +tens[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22 +#ifdef VAX + , 1e23, 1e24 +#endif + }; + + static CONST double +#ifdef IEEE_Arith +bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; +static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, +#ifdef Avoid_Underflow + 9007199254740992.*9007199254740992.e-256 + /* = 2^106 * 1e-53 */ +#else + 1e-256 +#endif + }; +/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */ +/* flag unnecessarily. It leads to a song and dance at the end of strtod. */ +#define Scale_Bit 0x10 +#define n_bigtens 5 +#else +#ifdef IBM +bigtens[] = { 1e16, 1e32, 1e64 }; +static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 }; +#define n_bigtens 3 +#else +bigtens[] = { 1e16, 1e32 }; +static CONST double tinytens[] = { 1e-16, 1e-32 }; +#define n_bigtens 2 +#endif +#endif + +#ifndef IEEE_Arith +#undef INFNAN_CHECK +#endif + +#ifdef INFNAN_CHECK + +#ifndef NAN_WORD0 +#define NAN_WORD0 0x7ff80000 +#endif + +#ifndef NAN_WORD1 +#define NAN_WORD1 0 +#endif + + static int +match +#ifdef KR_headers + (sp, t) char **sp, *t; +#else + (CONST char **sp, char *t) +#endif +{ + int c, d; + CONST char *s = *sp; + + while(d = *t++) { + if ((c = *++s) >= 'A' && c <= 'Z') + c += 'a' - 'A'; + if (c != d) + return 0; + } + *sp = s + 1; + return 1; + } + +#ifndef No_Hex_NaN + static void +hexnan +#ifdef KR_headers + (rvp, sp) double *rvp; CONST char **sp; +#else + (double *rvp, CONST char **sp) +#endif +{ + ULong c, x[2]; + CONST char *s; + int havedig, udx0, xshift; + + x[0] = x[1] = 0; + havedig = xshift = 0; + udx0 = 1; + s = *sp; + while(c = *(CONST unsigned char*)++s) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'a' && c <= 'f') + c += 10 - 'a'; + else if (c >= 'A' && c <= 'F') + c += 10 - 'A'; + else if (c <= ' ') { + if (udx0 && havedig) { + udx0 = 0; + xshift = 1; + } + continue; + } + else if (/*(*/ c == ')' && havedig) { + *sp = s + 1; + break; + } + else + return; /* invalid form: don't change *sp */ + havedig = 1; + if (xshift) { + xshift = 0; + x[0] = x[1]; + x[1] = 0; + } + if (udx0) + x[0] = (x[0] << 4) | (x[1] >> 28); + x[1] = (x[1] << 4) | c; + } + if ((x[0] &= 0xfffff) || x[1]) { + word0(*rvp) = Exp_mask | x[0]; + word1(*rvp) = x[1]; + } + } +#endif /*No_Hex_NaN*/ +#endif /* INFNAN_CHECK */ + +#if 0 + double +strtod +#ifdef KR_headers + (s00, se) CONST char *s00; char **se; +#else + (void *jt, CONST char *s00, char **se) +#endif +{ +#ifdef Avoid_Underflow + int scale; +#endif + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, + e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; + CONST char *s, *s0, *s1; + double aadj, aadj1, adj, rv, rv0; + Long L; + ULong y, z; + Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; +#ifdef SET_INEXACT + int inexact, oldinexact; +#endif +#ifdef Honor_FLT_ROUNDS + int rounding; +#endif +#ifdef USE_LOCALE + CONST char *s2; +#endif + + sign = nz0 = nz = 0; + dval(rv) = 0.; + for(s = s00;;s++) switch(*s) { + case '-': + sign = 1; + /* no break */ + case '+': + if (*++s) + goto break2; + /* no break */ + case 0: + goto ret0; + case '\t': + case '\n': + case '\v': + case '\f': + case '\r': + case ' ': + continue; + default: + goto break2; + } + break2: + if (*s == '0') { + nz0 = 1; + while(*++s == '0') ; + if (!*s) + goto ret; + } + s0 = s; + y = z = 0; + for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) + if (nd < 9) + y = 10*y + c - '0'; + else if (nd < 16) + z = 10*z + c - '0'; + nd0 = nd; +#ifdef USE_LOCALE + s1 = localeconv()->decimal_point; + if (c == *s1) { + c = '.'; + if (*++s1) { + s2 = s; + for(;;) { + if (*++s2 != *s1) { + c = 0; + break; + } + if (!*++s1) { + s = s2; + break; + } + } + } + } +#endif + if (c == '.') { + c = *++s; + if (!nd) { + for(; c == '0'; c = *++s) + nz++; + if (c > '0' && c <= '9') { + s0 = s; + nf += nz; + nz = 0; + goto have_dig; + } + goto dig_done; + } + for(; c >= '0' && c <= '9'; c = *++s) { + have_dig: + nz++; + if (c -= '0') { + nf += nz; + for(i = 1; i < nz; i++) + if (nd++ < 9) + y *= 10; + else if (nd <= DBL_DIG + 1) + z *= 10; + if (nd++ < 9) + y = 10*y + c; + else if (nd <= DBL_DIG + 1) + z = 10*z + c; + nz = 0; + } + } + } + dig_done: + e = 0; + if (c == 'e' || c == 'E') { + if (!nd && !nz && !nz0) { + goto ret0; + } + s00 = s; + esign = 0; + switch(c = *++s) { + case '-': + esign = 1; + case '+': + c = *++s; + } + if (c >= '0' && c <= '9') { + while(c == '0') + c = *++s; + if (c > '0' && c <= '9') { + L = c - '0'; + s1 = s; + while((c = *++s) >= '0' && c <= '9') + L = 10*L + c - '0'; + if (s - s1 > 8 || L > 19999) + /* Avoid confusion from exponents + * so large that e might overflow. + */ + e = 19999; /* safe for 16 bit ints */ + else + e = (int)L; + if (esign) + e = -e; + } + else + e = 0; + } + else + s = s00; + } + if (!nd) { + if (!nz && !nz0) { +#ifdef INFNAN_CHECK + /* Check for Nan and Infinity */ + switch(c) { + case 'i': + case 'I': + if (match(&s,"nf")) { + --s; + if (!match(&s,"inity")) + ++s; + word0(rv) = 0x7ff00000; + word1(rv) = 0; + goto ret; + } + break; + case 'n': + case 'N': + if (match(&s, "an")) { + word0(rv) = NAN_WORD0; + word1(rv) = NAN_WORD1; +#ifndef No_Hex_NaN + if (*s == '(') /*)*/ + hexnan(&rv, &s); +#endif + goto ret; + } + } +#endif /* INFNAN_CHECK */ + ret0: + s = s00; + sign = 0; + } + goto ret; + } + e1 = e -= nf; + + /* Now we have nd0 digits, starting at s0, followed by a + * decimal point, followed by nd-nd0 digits. The number we're + * after is the integer represented by those digits times + * 10**e */ + + if (!nd0) + nd0 = nd; + k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; + dval(rv) = y; + if (k > 9) { +#ifdef SET_INEXACT + if (k > DBL_DIG) + oldinexact = get_inexact(); +#endif + dval(rv) = tens[k - 9] * dval(rv) + z; + } + bd0 = 0; + if (nd <= DBL_DIG +#ifndef RND_PRODQUOT +#ifndef Honor_FLT_ROUNDS + && Flt_Rounds == 1 +#endif +#endif + ) { + if (!e) + goto ret; + if (e > 0) { + if (e <= Ten_pmax) { +#ifdef VAX + goto vax_ovfl_check; +#else +#ifdef Honor_FLT_ROUNDS + /* round correctly FLT_ROUNDS = 2 or 3 */ + if (sign) { + rv = -rv; + sign = 0; + } +#endif + /* rv = */ rounded_product(dval(rv), tens[e]); + goto ret; +#endif + } + i = DBL_DIG - nd; + if (e <= Ten_pmax + i) { + /* A fancier test would sometimes let us do + * this for larger i values. + */ +#ifdef Honor_FLT_ROUNDS + /* round correctly FLT_ROUNDS = 2 or 3 */ + if (sign) { + rv = -rv; + sign = 0; + } +#endif + e -= i; + dval(rv) *= tens[i]; +#ifdef VAX + /* VAX exponent range is so narrow we must + * worry about overflow here... + */ + vax_ovfl_check: + word0(rv) -= P*Exp_msk1; + /* rv = */ rounded_product(dval(rv), tens[e]); + if ((word0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) + goto ovfl; + word0(rv) += P*Exp_msk1; +#else + /* rv = */ rounded_product(dval(rv), tens[e]); +#endif + goto ret; + } + } +#ifndef Inaccurate_Divide + else if (e >= -Ten_pmax) { +#ifdef Honor_FLT_ROUNDS + /* round correctly FLT_ROUNDS = 2 or 3 */ + if (sign) { + rv = -rv; + sign = 0; + } +#endif + /* rv = */ rounded_quotient(dval(rv), tens[-e]); + goto ret; + } +#endif + } + e1 += nd - k; + +#ifdef IEEE_Arith +#ifdef SET_INEXACT + inexact = 1; + if (k <= DBL_DIG) + oldinexact = get_inexact(); +#endif +#ifdef Avoid_Underflow + scale = 0; +#endif +#ifdef Honor_FLT_ROUNDS + if ((rounding = Flt_Rounds) >= 2) { + if (sign) + rounding = rounding == 2 ? 0 : 2; + else + if (rounding != 2) + rounding = 0; + } +#endif +#endif /*IEEE_Arith*/ + + /* Get starting approximation = rv * 10**e1 */ + + if (e1 > 0) { + if (i = e1 & 15) + dval(rv) *= tens[i]; + if (e1 &= ~15) { + if (e1 > DBL_MAX_10_EXP) { + ovfl: +#ifndef NO_ERRNO + errno = ERANGE; +#endif + /* Can't trust HUGE_VAL */ +#ifdef IEEE_Arith +#ifdef Honor_FLT_ROUNDS + switch(rounding) { + case 0: /* toward 0 */ + case 3: /* toward -infinity */ + word0(rv) = Big0; + word1(rv) = Big1; + break; + default: + word0(rv) = Exp_mask; + word1(rv) = 0; + } +#else /*Honor_FLT_ROUNDS*/ + word0(rv) = Exp_mask; + word1(rv) = 0; +#endif /*Honor_FLT_ROUNDS*/ +#ifdef SET_INEXACT + /* set overflow bit */ + dval(rv0) = 1e300; + dval(rv0) *= dval(rv0); +#endif +#else /*IEEE_Arith*/ + word0(rv) = Big0; + word1(rv) = Big1; +#endif /*IEEE_Arith*/ + if (bd0) + goto retfree; + goto ret; + } + e1 >>= 4; + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + dval(rv) *= bigtens[j]; + /* The last multiplication could overflow. */ + word0(rv) -= P*Exp_msk1; + dval(rv) *= bigtens[j]; + if ((z = word0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-P)) + goto ovfl; + if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { + /* set to largest number */ + /* (Can't trust DBL_MAX) */ + word0(rv) = Big0; + word1(rv) = Big1; + } + else + word0(rv) += P*Exp_msk1; + } + } + else if (e1 < 0) { + e1 = -e1; + if (i = e1 & 15) + dval(rv) /= tens[i]; + if (e1 >>= 4) { + if (e1 >= 1 << n_bigtens) + goto undfl; +#ifdef Avoid_Underflow + if (e1 & Scale_Bit) + scale = 2*P; + for(j = 0; e1 > 0; j++, e1 >>= 1) + if (e1 & 1) + dval(rv) *= tinytens[j]; + if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask) + >> Exp_shift)) > 0) { + /* scaled rv is denormal; zap j low bits */ + if (j >= 32) { + word1(rv) = 0; + if (j >= 53) + word0(rv) = (P+2)*Exp_msk1; + else + word0(rv) &= 0xffffffff << j-32; + } + else + word1(rv) &= 0xffffffff << j; + } +#else + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + dval(rv) *= tinytens[j]; + /* The last multiplication could underflow. */ + dval(rv0) = dval(rv); + dval(rv) *= tinytens[j]; + if (!dval(rv)) { + dval(rv) = 2.*dval(rv0); + dval(rv) *= tinytens[j]; +#endif + if (!dval(rv)) { + undfl: + dval(rv) = 0.; +#ifndef NO_ERRNO + errno = ERANGE; +#endif + if (bd0) + goto retfree; + goto ret; + } +#ifndef Avoid_Underflow + word0(rv) = Tiny0; + word1(rv) = Tiny1; + /* The refinement below will clean + * this approximation up. + */ + } +#endif + } + } + + /* Now the hard part -- adjusting rv to the correct value.*/ + + /* Put digits into bd: true value = bd * 10^e */ + + bd0 = s2b(s0, nd0, nd, y); + + for(;;) { + bd = Balloc(bd0->k); + Bcopy(bd, bd0); + bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ + bs = i2b(1); + + if (e >= 0) { + bb2 = bb5 = 0; + bd2 = bd5 = e; + } + else { + bb2 = bb5 = -e; + bd2 = bd5 = 0; + } + if (bbe >= 0) + bb2 += bbe; + else + bd2 -= bbe; + bs2 = bb2; +#ifdef Honor_FLT_ROUNDS + if (rounding != 1) + bs2++; +#endif +#ifdef Avoid_Underflow + j = bbe - scale; + i = j + bbbits - 1; /* logb(rv) */ + if (i < Emin) /* denormal */ + j += P - Emin; + else + j = P + 1 - bbbits; +#else /*Avoid_Underflow*/ +#ifdef Sudden_Underflow +#ifdef IBM + j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); +#else + j = P + 1 - bbbits; +#endif +#else /*Sudden_Underflow*/ + j = bbe; + i = j + bbbits - 1; /* logb(rv) */ + if (i < Emin) /* denormal */ + j += P - Emin; + else + j = P + 1 - bbbits; +#endif /*Sudden_Underflow*/ +#endif /*Avoid_Underflow*/ + bb2 += j; + bd2 += j; +#ifdef Avoid_Underflow + bd2 += scale; +#endif + i = bb2 < bd2 ? bb2 : bd2; + if (i > bs2) + i = bs2; + if (i > 0) { + bb2 -= i; + bd2 -= i; + bs2 -= i; + } + if (bb5 > 0) { + bs = pow5mult(bs, bb5); + bb1 = mult(bs, bb); + Bfree(bb); + bb = bb1; + } + if (bb2 > 0) + bb = lshift(bb, bb2); + if (bd5 > 0) + bd = pow5mult(bd, bd5); + if (bd2 > 0) + bd = lshift(bd, bd2); + if (bs2 > 0) + bs = lshift(bs, bs2); + delta = diff(bb, bd); + dsign = delta->sign; + delta->sign = 0; + i = cmp(delta, bs); +#ifdef Honor_FLT_ROUNDS + if (rounding != 1) { + if (i < 0) { + /* Error is less than an ulp */ + if (!delta->x[0] && delta->wds <= 1) { + /* exact */ +#ifdef SET_INEXACT + inexact = 0; +#endif + break; + } + if (rounding) { + if (dsign) { + adj = 1.; + goto apply_adj; + } + } + else if (!dsign) { + adj = -1.; + if (!word1(rv) + && !(word0(rv) & Frac_mask)) { + y = word0(rv) & Exp_mask; +#ifdef Avoid_Underflow + if (!scale || y > 2*P*Exp_msk1) +#else + if (y) +#endif + { + delta = lshift(delta,Log2P); + if (cmp(delta, bs) <= 0) + adj = -0.5; + } + } + apply_adj: +#ifdef Avoid_Underflow + if (scale && (y = word0(rv) & Exp_mask) + <= 2*P*Exp_msk1) + word0(adj) += (2*P+1)*Exp_msk1 - y; +#else +#ifdef Sudden_Underflow + if ((word0(rv) & Exp_mask) <= + P*Exp_msk1) { + word0(rv) += P*Exp_msk1; + dval(rv) += adj*ulp(dval(rv)); + word0(rv) -= P*Exp_msk1; + } + else +#endif /*Sudden_Underflow*/ +#endif /*Avoid_Underflow*/ + dval(rv) += adj*ulp(dval(rv)); + } + break; + } + adj = ratio(delta, bs); + if (adj < 1.) + adj = 1.; + if (adj <= 0x7ffffffe) { + /* adj = rounding ? ceil(adj) : floor(adj); */ + y = adj; + if (y != adj) { + if (!((rounding>>1) ^ dsign)) + y++; + adj = y; + } + } +#ifdef Avoid_Underflow + if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) + word0(adj) += (2*P+1)*Exp_msk1 - y; +#else +#ifdef Sudden_Underflow + if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { + word0(rv) += P*Exp_msk1; + adj *= ulp(dval(rv)); + if (dsign) + dval(rv) += adj; + else + dval(rv) -= adj; + word0(rv) -= P*Exp_msk1; + goto cont; + } +#endif /*Sudden_Underflow*/ +#endif /*Avoid_Underflow*/ + adj *= ulp(dval(rv)); + if (dsign) + dval(rv) += adj; + else + dval(rv) -= adj; + goto cont; + } +#endif /*Honor_FLT_ROUNDS*/ + + if (i < 0) { + /* Error is less than half an ulp -- check for + * special case of mantissa a power of two. + */ + if (dsign || word1(rv) || word0(rv) & Bndry_mask +#ifdef IEEE_Arith +#ifdef Avoid_Underflow + || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1 +#else + || (word0(rv) & Exp_mask) <= Exp_msk1 +#endif +#endif + ) { +#ifdef SET_INEXACT + if (!delta->x[0] && delta->wds <= 1) + inexact = 0; +#endif + break; + } + if (!delta->x[0] && delta->wds <= 1) { + /* exact result */ +#ifdef SET_INEXACT + inexact = 0; +#endif + break; + } + delta = lshift(delta,Log2P); + if (cmp(delta, bs) > 0) + goto drop_down; + break; + } + if (i == 0) { + /* exactly half-way between */ + if (dsign) { + if ((word0(rv) & Bndry_mask1) == Bndry_mask1 + && word1(rv) == ( +#ifdef Avoid_Underflow + (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) + ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : +#endif + 0xffffffff)) { + /*boundary case -- increment exponent*/ + word0(rv) = (word0(rv) & Exp_mask) + + Exp_msk1 +#ifdef IBM + | Exp_msk1 >> 4 +#endif + ; + word1(rv) = 0; +#ifdef Avoid_Underflow + dsign = 0; +#endif + break; + } + } + else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { + drop_down: + /* boundary case -- decrement exponent */ +#ifdef Sudden_Underflow /*{{*/ + L = word0(rv) & Exp_mask; +#ifdef IBM + if (L < Exp_msk1) +#else +#ifdef Avoid_Underflow + if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1)) +#else + if (L <= Exp_msk1) +#endif /*Avoid_Underflow*/ +#endif /*IBM*/ + goto undfl; + L -= Exp_msk1; +#else /*Sudden_Underflow}{*/ +#ifdef Avoid_Underflow + if (scale) { + L = word0(rv) & Exp_mask; + if (L <= (2*P+1)*Exp_msk1) { + if (L > (P+2)*Exp_msk1) + /* round even ==> */ + /* accept rv */ + break; + /* rv = smallest denormal */ + goto undfl; + } + } +#endif /*Avoid_Underflow*/ + L = (word0(rv) & Exp_mask) - Exp_msk1; +#endif /*Sudden_Underflow}}*/ + word0(rv) = L | Bndry_mask1; + word1(rv) = 0xffffffff; +#ifdef IBM + goto cont; +#else + break; +#endif + } +#ifndef ROUND_BIASED + if (!(word1(rv) & LSB)) + break; +#endif + if (dsign) + dval(rv) += ulp(dval(rv)); +#ifndef ROUND_BIASED + else { + dval(rv) -= ulp(dval(rv)); +#ifndef Sudden_Underflow + if (!dval(rv)) + goto undfl; +#endif + } +#ifdef Avoid_Underflow + dsign = 1 - dsign; +#endif +#endif + break; + } + if ((aadj = ratio(delta, bs)) <= 2.) { + if (dsign) + aadj = aadj1 = 1.; + else if (word1(rv) || word0(rv) & Bndry_mask) { +#ifndef Sudden_Underflow + if (word1(rv) == Tiny1 && !word0(rv)) + goto undfl; +#endif + aadj = 1.; + aadj1 = -1.; + } + else { + /* special case -- power of FLT_RADIX to be */ + /* rounded down... */ + + if (aadj < 2./FLT_RADIX) + aadj = 1./FLT_RADIX; + else + aadj *= 0.5; + aadj1 = -aadj; + } + } + else { + aadj *= 0.5; + aadj1 = dsign ? aadj : -aadj; +#ifdef Check_FLT_ROUNDS + switch(Rounding) { + case 2: /* towards +infinity */ + aadj1 -= 0.5; + break; + case 0: /* towards 0 */ + case 3: /* towards -infinity */ + aadj1 += 0.5; + } +#else + if (Flt_Rounds == 0) + aadj1 += 0.5; +#endif /*Check_FLT_ROUNDS*/ + } + y = word0(rv) & Exp_mask; + + /* Check for overflow */ + + if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { + dval(rv0) = dval(rv); + word0(rv) -= P*Exp_msk1; + adj = aadj1 * ulp(dval(rv)); + dval(rv) += adj; + if ((word0(rv) & Exp_mask) >= + Exp_msk1*(DBL_MAX_EXP+Bias-P)) { + if (word0(rv0) == Big0 && word1(rv0) == Big1) + goto ovfl; + word0(rv) = Big0; + word1(rv) = Big1; + goto cont; + } + else + word0(rv) += P*Exp_msk1; + } + else { +#ifdef Avoid_Underflow + if (scale && y <= 2*P*Exp_msk1) { + if (aadj <= 0x7fffffff) { + if ((z = aadj) <= 0) + z = 1; + aadj = z; + aadj1 = dsign ? aadj : -aadj; + } + word0(aadj1) += (2*P+1)*Exp_msk1 - y; + } + adj = aadj1 * ulp(dval(rv)); + dval(rv) += adj; +#else +#ifdef Sudden_Underflow + if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { + dval(rv0) = dval(rv); + word0(rv) += P*Exp_msk1; + adj = aadj1 * ulp(dval(rv)); + dval(rv) += adj; +#ifdef IBM + if ((word0(rv) & Exp_mask) < P*Exp_msk1) +#else + if ((word0(rv) & Exp_mask) <= P*Exp_msk1) +#endif + { + if (word0(rv0) == Tiny0 + && word1(rv0) == Tiny1) + goto undfl; + word0(rv) = Tiny0; + word1(rv) = Tiny1; + goto cont; + } + else + word0(rv) -= P*Exp_msk1; + } + else { + adj = aadj1 * ulp(dval(rv)); + dval(rv) += adj; + } +#else /*Sudden_Underflow*/ + /* Compute adj so that the IEEE rounding rules will + * correctly round rv + adj in some half-way cases. + * If rv * ulp(rv) is denormalized (i.e., + * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid + * trouble from bits lost to denormalization; + * example: 1.2e-307 . + */ + if (y <= (P-1)*Exp_msk1 && aadj > 1.) { + aadj1 = (double)(int)(aadj + 0.5); + if (!dsign) + aadj1 = -aadj1; + } + adj = aadj1 * ulp(dval(rv)); + dval(rv) += adj; +#endif /*Sudden_Underflow*/ +#endif /*Avoid_Underflow*/ + } + z = word0(rv) & Exp_mask; +#ifndef SET_INEXACT +#ifdef Avoid_Underflow + if (!scale) +#endif + if (y == z) { + /* Can we stop now? */ + L = (Long)aadj; + aadj -= L; + /* The tolerances below are conservative. */ + if (dsign || word1(rv) || word0(rv) & Bndry_mask) { + if (aadj < .4999999 || aadj > .5000001) + break; + } + else if (aadj < .4999999/FLT_RADIX) + break; + } +#endif + cont: + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(delta); + } +#ifdef SET_INEXACT + if (inexact) { + if (!oldinexact) { + word0(rv0) = Exp_1 + (70 << Exp_shift); + word1(rv0) = 0; + dval(rv0) += 1.; + } + } + else if (!oldinexact) + clear_inexact(); +#endif +#ifdef Avoid_Underflow + if (scale) { + word0(rv0) = Exp_1 - 2*P*Exp_msk1; + word1(rv0) = 0; + dval(rv) *= dval(rv0); +#ifndef NO_ERRNO + /* try to avoid the bug of testing an 8087 register value */ + if (word0(rv) == 0 && word1(rv) == 0) + errno = ERANGE; +#endif + } +#endif /* Avoid_Underflow */ +#ifdef SET_INEXACT + if (inexact && !(word0(rv) & Exp_mask)) { + /* set underflow bit */ + dval(rv0) = 1e-300; + dval(rv0) *= dval(rv0); + } +#endif + retfree: + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); + ret: + if (se) + *se = (char *)s; + return sign ? -dval(rv) : dval(rv); + } +#endif + + static int +quorem +#ifdef KR_headers + (b, S) Bigint *b, *S; +#else + (Bigint *b, Bigint *S) +#endif +{ + int n; + ULong *bx, *bxe, q, *sx, *sxe; +#ifdef ULLong + ULLong borrow, carry, y, ys; +#else + ULong borrow, carry, y, ys; +#ifdef Pack_32 + ULong si, z, zs; +#endif +#endif + + n = S->wds; +#ifdef DEBUG + /*debug*/ if (b->wds > n) + /*debug*/ Bug("oversize b in quorem"); +#endif + if (b->wds < n) + return 0; + sx = S->x; + sxe = sx + --n; + bx = b->x; + bxe = bx + n; + q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ +#ifdef DEBUG + /*debug*/ if (q > 9) + /*debug*/ Bug("oversized quotient in quorem"); +#endif + if (q) { + borrow = 0; + carry = 0; + do { +#ifdef ULLong + ys = *sx++ * (ULLong)q + carry; + carry = ys >> 32; + y = *bx - (ys & FFFFFFFF) - borrow; + borrow = y >> 32 & (ULong)1; + *bx++ = (ULong)(y & FFFFFFFF); +#else +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) * q + carry; + zs = (si >> 16) * q + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*bx >> 16) - (zs & 0xffff) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(bx, z, y); +#else + ys = *sx++ * q + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + *bx++ = y & 0xffff; +#endif +#endif + } + while(sx <= sxe); + if (!*bxe) { + bx = b->x; + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + if (cmp(b, S) >= 0) { + q++; + borrow = 0; + carry = 0; + bx = b->x; + sx = S->x; + do { +#ifdef ULLong + ys = *sx++ + carry; + carry = ys >> 32; + y = *bx - (ys & FFFFFFFF) - borrow; + borrow = y >> 32 & (ULong)1; + *bx++ = (ULong)(y & FFFFFFFF); +#else +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) + carry; + zs = (si >> 16) + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*bx >> 16) - (zs & 0xffff) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(bx, z, y); +#else + ys = *sx++ + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + *bx++ = y & 0xffff; +#endif +#endif + } + while(sx <= sxe); + bx = b->x; + bxe = bx + n; + if (!*bxe) { + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + return q; + } + +#ifndef MULTIPLE_THREADS + static char *dtoa_result; +#endif + + static char * +#ifdef KR_headers +rv_alloc(i) int i; +#else +d2a_rv_alloc(struct dtoa_info *d2a, int i) +#endif +/* i is guarenteed i >= 0 by caller so the cast to unsigned below is safe */ +{ +#ifndef Use_J_Memory + int j, k, *r; + + j = sizeof(ULong); + for(k = 0; + sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (unsigned)i; + j <<= 1) + k++; + r = (int*)Balloc(k); + *r = k; + return +#ifndef MULTIPLE_THREADS + dtoa_result = +#endif + (char *)(r+1); +#else + if(i>d2a->ndp) longjmp(d2a->_env, 2); /* this shouldn't happen? */ + return d2a->result; +#endif + } + + static char * +#ifdef KR_headers +nrv_alloc(s, rve, n) char *s, **rve; int n; +#else +d2a_nrv_alloc(struct dtoa_info *d2a, char *s, char **rve, int n) +#endif +{ + char *rv, *t; + + t = rv = rv_alloc(n); + /*while(*t = *s++) t++;*/ + while(*s){*t++=*s++;} /* don't copy the NUL */ + if (rve) + *rve = t; + return rv; + } + +/* freedtoa(s) must be used to free values s returned by dtoa + * when MULTIPLE_THREADS is #defined. It should be used in all cases, + * but for consistency with earlier versions of dtoa, it is optional + * when MULTIPLE_THREADS is not defined. + */ +#if 0 + static void +#ifdef KR_headers +freedtoa(s) char *s; +#else +d2a_freedtoa(struct dtoa_info *d2a, char *s) +#endif +{ + Bigint *b = (Bigint *)((int *)s - 1); + b->maxwds = 1 << (b->k = *(int*)b); + Bfree(b); +#ifndef MULTIPLE_THREADS + if (s == dtoa_result) + dtoa_result = 0; +#endif + } +#endif + +/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. + * + * Inspired by "How to Print Floating-Point Numbers Accurately" by + * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. + * + * Modifications: + * 1. Rather than iterating, we use a simple numeric overestimate + * to determine k = floor(log10(d)). We scale relevant + * quantities using O(log2(k)) rather than O(k) multiplications. + * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't + * try to generate digits strictly left to right. Instead, we + * compute with fewer bits and propagate the carry if necessary + * when rounding the final digit up. This is often faster. + * 3. Under the assumption that input will be rounded nearest, + * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. + * That is, we allow equality in stopping tests when the + * round-nearest rule will give the same floating-point value + * as would satisfaction of the stopping test with strict + * inequality. + * 4. We remove common factors of powers of 2 from relevant + * quantities. + * 5. When converting floating-point integers less than 1e16, + * we use floating-point arithmetic rather than resorting + * to multiple-precision integers. + * 6. When asked to produce fewer than 15 digits, we first try + * to get by with floating-point arithmetic; we resort to + * multiple-precision integer arithmetic only if we cannot + * guarantee that the floating-point calculation has given + * the correctly rounded result. For k requested digits and + * "uniformly" distributed input, the probability is + * something like 10^(k-15) that we must resort to the Long + * calculation. + */ + + static char * +d2a_dtoa +#ifdef KR_headers + (d, mode, ndigits, decpt, sign, rve) + double d; int mode, ndigits, *decpt, *sign; char **rve; +#else + (struct dtoa_info *d2a, double d, int mode, int ndigits, int *decpt, int *sign, char **rve) +#endif +{ + /* Arguments ndigits, decpt, sign are similar to those + of ecvt and fcvt; trailing zeros are suppressed from + the returned string. If not null, *rve is set to point + to the end of the return value. If d is +-Infinity or NaN, + then *decpt is set to 9999. + + mode: + 0 ==> shortest string that yields d when read in + and rounded to nearest. + 1 ==> like 0, but with Steele & White stopping rule; + e.g. with IEEE P754 arithmetic , mode 0 gives + 1e23 whereas mode 1 gives 9.999999999999999e22. + 2 ==> max(1,ndigits) significant digits. This gives a + return value similar to that of ecvt, except + that trailing zeros are suppressed. + 3 ==> through ndigits past the decimal point. This + gives a return value similar to that from fcvt, + except that trailing zeros are suppressed, and + ndigits can be negative. + 4,5 ==> similar to 2 and 3, respectively, but (in + round-nearest mode) with the tests of mode 0 to + possibly return a shorter string that rounds to d. + With IEEE arithmetic and compilation with + -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same + as modes 2 and 3 when FLT_ROUNDS != 1. + 6-9 ==> Debugging modes similar to mode - 4: don't try + fast floating-point estimate (if applicable). + + Values of mode other than 0-9 are treated as mode 0. + + Sufficient space is allocated to the return value + to hold the suppressed trailing zeros. + */ + + int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, + j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, + spec_case, try_quick; + Long L; +#ifndef Sudden_Underflow + int denorm; + ULong x; +#endif + Bigint *b, *b1, *delta, *mlo, *mhi, *S; + double d2, ds, eps; + char *s, *s0; +#ifdef Honor_FLT_ROUNDS + int rounding; +#endif +#ifdef SET_INEXACT + int inexact, oldinexact; +#endif + +#ifndef MULTIPLE_THREADS + if (dtoa_result) { + freedtoa(dtoa_result); + dtoa_result = 0; + } +#endif + + if (word0(d) & Sign_bit) { + /* set sign for everything, including 0's and NaNs */ + *sign = 1; + word0(d) &= ~Sign_bit; /* clear sign bit */ + } + else + *sign = 0; + +#if defined(IEEE_Arith) + defined(VAX) +#ifdef IEEE_Arith + if ((word0(d) & Exp_mask) == Exp_mask) +#else + if (word0(d) == 0x8000) +#endif + { + /* Infinity or NaN */ + *decpt = 9999; +#ifdef IEEE_Arith + if (!word1(d) && !(word0(d) & 0xfffff)) + return nrv_alloc("Infinity", rve, 8); +#endif + return nrv_alloc("NaN", rve, 3); + } +#endif +#ifdef IBM + dval(d) += 0; /* normalize */ +#endif + if (!dval(d)) { + *decpt = 1; + return nrv_alloc("0", rve, 1); + } + +#ifdef SET_INEXACT + try_quick = oldinexact = get_inexact(); + inexact = 1; +#endif +#ifdef Honor_FLT_ROUNDS + if ((rounding = Flt_Rounds) >= 2) { + if (*sign) + rounding = rounding == 2 ? 0 : 2; + else + if (rounding != 2) + rounding = 0; + } +#endif + + b = d2b(dval(d), &be, &bbits); +#ifdef Sudden_Underflow + i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); +#else + if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) { +#endif + dval(d2) = dval(d); + word0(d2) &= Frac_mask1; + word0(d2) |= Exp_11; +#ifdef IBM + if (j = 11 - hi0bits(word0(d2) & Frac_mask)) + dval(d2) /= 1 << j; +#endif + + /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 + * log10(x) = log(x) / log(10) + * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) + * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) + * + * This suggests computing an approximation k to log10(d) by + * + * k = (i - Bias)*0.301029995663981 + * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); + * + * We want k to be too large rather than too small. + * The error in the first-order Taylor series approximation + * is in our favor, so we just round up the constant enough + * to compensate for any error in the multiplication of + * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, + * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, + * adding 1e-13 to the constant term more than suffices. + * Hence we adjust the constant term to 0.1760912590558. + * (We could get a more accurate k by invoking log10, + * but this is probably not worthwhile.) + */ + + i -= Bias; +#ifdef IBM + i <<= 2; + i += j; +#endif +#ifndef Sudden_Underflow + denorm = 0; + } + else { + /* d is denormalized */ + + i = bbits + be + (Bias + (P-1) - 1); + x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32) + : word1(d) << (32 - i); + dval(d2) = x; + word0(d2) -= 31*Exp_msk1; /* adjust exponent */ + i -= (Bias + (P-1) - 1) + 1; + denorm = 1; + } +#endif + ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + k = (int)ds; + if (ds < 0. && ds != k) + k--; /* want k = floor(ds) */ + k_check = 1; + if (k >= 0 && k <= Ten_pmax) { + if (dval(d) < tens[k]) + k--; + k_check = 0; + } + j = bbits - i - 1; + if (j >= 0) { + b2 = 0; + s2 = j; + } + else { + b2 = -j; + s2 = 0; + } + if (k >= 0) { + b5 = 0; + s5 = k; + s2 += k; + } + else { + b2 -= k; + b5 = -k; + s5 = 0; + } + if (mode < 0 || mode > 9) + mode = 0; + +#ifndef SET_INEXACT +#ifdef Check_FLT_ROUNDS + try_quick = Rounding == 1; +#else + try_quick = 1; +#endif +#endif /*SET_INEXACT*/ + + if (mode > 5) { + mode -= 4; + try_quick = 0; + } + leftright = 1; + switch(mode) { + case 0: + case 1: + ilim = ilim1 = -1; + i = 18; + ndigits = 0; + break; + case 2: + leftright = 0; + /* no break */ + case 4: + if (ndigits <= 0) + ndigits = 1; + ilim = ilim1 = i = ndigits; + break; + case 3: + leftright = 0; + /* no break */ + case 5: + i = ndigits + k + 1; + ilim = i; + ilim1 = i - 1; + if (i <= 0) + i = 1; + } + s = s0 = rv_alloc(i); + +#ifdef Honor_FLT_ROUNDS + if (mode > 1 && rounding != 1) + leftright = 0; +#endif + + if (ilim >= 0 && ilim <= Quick_max && try_quick) { + + /* Try to get by with floating-point arithmetic. */ + + i = 0; + dval(d2) = dval(d); + k0 = k; + ilim0 = ilim; + ieps = 2; /* conservative */ + if (k > 0) { + ds = tens[k&0xf]; + j = k >> 4; + if (j & Bletch) { + /* prevent overflows */ + j &= Bletch - 1; + dval(d) /= bigtens[n_bigtens-1]; + ieps++; + } + for(; j; j >>= 1, i++) + if (j & 1) { + ieps++; + ds *= bigtens[i]; + } + dval(d) /= ds; + } + else if (j1 = -k) { + dval(d) *= tens[j1 & 0xf]; + for(j = j1 >> 4; j; j >>= 1, i++) + if (j & 1) { + ieps++; + dval(d) *= bigtens[i]; + } + } + if (k_check && dval(d) < 1. && ilim > 0) { + if (ilim1 <= 0) + goto fast_failed; + ilim = ilim1; + k--; + dval(d) *= 10.; + ieps++; + } + dval(eps) = ieps*dval(d) + 7.; + word0(eps) -= (P-1)*Exp_msk1; + if (ilim == 0) { + S = mhi = 0; + dval(d) -= 5.; + if (dval(d) > dval(eps)) + goto one_digit; + if (dval(d) < -dval(eps)) + goto no_digits; + goto fast_failed; + } +#ifndef No_leftright + if (leftright) { + /* Use Steele & White method of only + * generating digits needed. + */ + dval(eps) = 0.5/tens[ilim-1] - dval(eps); + for(i = 0;;) { + L = (Long)dval(d); + dval(d) -= L; + *s++ = '0' + (int)L; + if (dval(d) < dval(eps)) + goto ret1; + if (1. - dval(d) < dval(eps)) + goto bump_up; + if (++i >= ilim) + break; + dval(eps) *= 10.; + dval(d) *= 10.; + } + } + else { +#endif + /* Generate ilim digits, then fix them up. */ + dval(eps) *= tens[ilim-1]; + for(i = 1;; i++, dval(d) *= 10.) { + L = (Long)(dval(d)); + if (!(dval(d) -= L)) + ilim = i; + *s++ = '0' + (int)L; + if (i == ilim) { + if (dval(d) > 0.5 + dval(eps)) + goto bump_up; + else if (dval(d) < 0.5 - dval(eps)) { + while(*--s == '0'); + s++; + goto ret1; + } + break; + } + } +#ifndef No_leftright + } +#endif + fast_failed: + s = s0; + dval(d) = dval(d2); + k = k0; + ilim = ilim0; + } + + /* Do we have a "small" integer? */ + + if (be >= 0 && k <= Int_max) { + /* Yes. */ + ds = tens[k]; + if (ndigits < 0 && ilim <= 0) { + S = mhi = 0; + if (ilim < 0 || dval(d) <= 5*ds) + goto no_digits; + goto one_digit; + } + for(i = 1;; i++, dval(d) *= 10.) { + L = (Long)(dval(d) / ds); + dval(d) -= L*ds; +#ifdef Check_FLT_ROUNDS + /* If FLT_ROUNDS == 2, L will usually be high by 1 */ + if (dval(d) < 0) { + L--; + dval(d) += ds; + } +#endif + *s++ = '0' + (int)L; + if (!dval(d)) { +#ifdef SET_INEXACT + inexact = 0; +#endif + break; + } + if (i == ilim) { +#ifdef Honor_FLT_ROUNDS + if (mode > 1) + switch(rounding) { + case 0: goto ret1; + case 2: goto bump_up; + } +#endif + dval(d) += dval(d); + if (dval(d) > ds || dval(d) == ds && L & 1) { + bump_up: + while(*--s == '9') + if (s == s0) { + k++; + *s = '0'; + break; + } + ++*s++; + } + break; + } + } + goto ret1; + } + + m2 = b2; + m5 = b5; + mhi = mlo = 0; + if (leftright) { + i = +#ifndef Sudden_Underflow + denorm ? be + (Bias + (P-1) - 1 + 1) : +#endif +#ifdef IBM + 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); +#else + 1 + P - bbits; +#endif + b2 += i; + s2 += i; + mhi = i2b(1); + } + if (m2 > 0 && s2 > 0) { + i = m2 < s2 ? m2 : s2; + b2 -= i; + m2 -= i; + s2 -= i; + } + if (b5 > 0) { + if (leftright) { + if (m5 > 0) { + mhi = pow5mult(mhi, m5); + b1 = mult(mhi, b); + Bfree(b); + b = b1; + } + if (j = b5 - m5) + b = pow5mult(b, j); + } + else + b = pow5mult(b, b5); + } + S = i2b(1); + if (s5 > 0) + S = pow5mult(S, s5); + + /* Check for special case that d is a normalized power of 2. */ + + spec_case = 0; + if ((mode < 2 || leftright) +#ifdef Honor_FLT_ROUNDS + && rounding == 1 +#endif + ) { + if (!word1(d) && !(word0(d) & Bndry_mask) +#ifndef Sudden_Underflow + && word0(d) & (Exp_mask & ~Exp_msk1) +#endif + ) { + /* The special case */ + b2 += Log2P; + s2 += Log2P; + spec_case = 1; + } + } + + /* Arrange for convenient computation of quotients: + * shift left if necessary so divisor has 4 leading 0 bits. + * + * Perhaps we should just compute leading 28 bits of S once + * and for all and pass them and a shift to quorem, so it + * can do shifts and ors to compute the numerator for q. + */ +#ifdef Pack_32 + if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) + i = 32 - i; +#else + if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) + i = 16 - i; +#endif + if (i > 4) { + i -= 4; + b2 += i; + m2 += i; + s2 += i; + } + else if (i < 4) { + i += 28; + b2 += i; + m2 += i; + s2 += i; + } + if (b2 > 0) + b = lshift(b, b2); + if (s2 > 0) + S = lshift(S, s2); + if (k_check) { + if (cmp(b,S) < 0) { + k--; + b = multadd(b, 10, 0); /* we botched the k estimate */ + if (leftright) + mhi = multadd(mhi, 10, 0); + ilim = ilim1; + } + } + if (ilim <= 0 && (mode == 3 || mode == 5)) { + if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { + /* no digits, fcvt style */ + no_digits: + k = -1 - ndigits; + goto ret; + } + one_digit: + *s++ = '1'; + k++; + goto ret; + } + if (leftright) { + if (m2 > 0) + mhi = lshift(mhi, m2); + + /* Compute mlo -- check for special case + * that d is a normalized power of 2. + */ + + mlo = mhi; + if (spec_case) { + mhi = Balloc(mhi->k); + Bcopy(mhi, mlo); + mhi = lshift(mhi, Log2P); + } + + for(i = 1;;i++) { + dig = quorem(b,S) + '0'; + /* Do we yet have the shortest decimal string + * that will round to d? + */ + j = cmp(b, mlo); + delta = diff(S, mhi); + j1 = delta->sign ? 1 : cmp(b, delta); + Bfree(delta); +#ifndef ROUND_BIASED + if (j1 == 0 && mode != 1 && !(word1(d) & 1) +#ifdef Honor_FLT_ROUNDS + && rounding >= 1 +#endif + ) { + if (dig == '9') + goto round_9_up; + if (j > 0) + dig++; +#ifdef SET_INEXACT + else if (!b->x[0] && b->wds <= 1) + inexact = 0; +#endif + *s++ = dig; + goto ret; + } +#endif + if (j < 0 || j == 0 && mode != 1 +#ifndef ROUND_BIASED + && !(word1(d) & 1) +#endif + ) { + if (!b->x[0] && b->wds <= 1) { +#ifdef SET_INEXACT + inexact = 0; +#endif + goto accept_dig; + } +#ifdef Honor_FLT_ROUNDS + if (mode > 1) + switch(rounding) { + case 0: goto accept_dig; + case 2: goto keep_dig; + } +#endif /*Honor_FLT_ROUNDS*/ + if (j1 > 0) { + b = lshift(b, 1); + j1 = cmp(b, S); + if ((j1 > 0 || j1 == 0 && dig & 1) + && dig++ == '9') + goto round_9_up; + } + accept_dig: + *s++ = dig; + goto ret; + } + if (j1 > 0) { +#ifdef Honor_FLT_ROUNDS + if (!rounding) + goto accept_dig; +#endif + if (dig == '9') { /* possible if i == 1 */ + round_9_up: + *s++ = '9'; + goto roundoff; + } + *s++ = dig + 1; + goto ret; + } +#ifdef Honor_FLT_ROUNDS + keep_dig: +#endif + *s++ = dig; + if (i == ilim) + break; + b = multadd(b, 10, 0); + if (mlo == mhi) + mlo = mhi = multadd(mhi, 10, 0); + else { + mlo = multadd(mlo, 10, 0); + mhi = multadd(mhi, 10, 0); + } + } + } + else + for(i = 1;; i++) { + *s++ = dig = quorem(b,S) + '0'; + if (!b->x[0] && b->wds <= 1) { +#ifdef SET_INEXACT + inexact = 0; +#endif + goto ret; + } + if (i >= ilim) + break; + b = multadd(b, 10, 0); + } + + /* Round off last digit */ + +#ifdef Honor_FLT_ROUNDS + switch(rounding) { + case 0: goto trimzeros; + case 2: goto roundoff; + } +#endif + b = lshift(b, 1); + j = cmp(b, S); + if (j > 0 || j == 0 && dig & 1) { + roundoff: + while(*--s == '9') + if (s == s0) { + k++; + *s++ = '1'; + goto ret; + } + ++*s++; + } + else { +/* trimzeros: */ /* since it's unreferenced */ + while(*--s == '0'); + s++; + } + ret: + Bfree(S); + if (mhi) { + if (mlo && mlo != mhi) + Bfree(mlo); + Bfree(mhi); + } + ret1: +#ifdef SET_INEXACT + if (inexact) { + if (!oldinexact) { + word0(d) = Exp_1 + (70 << Exp_shift); + word1(d) = 0; + dval(d) += 1.; + } + } + else if (!oldinexact) + clear_inexact(); +#endif + Bfree(b); + /* *s = 0; */ /* don't NUL terminate */ + *decpt = k + 1; + if (rve) + *rve = s; + return s0; + } + +#ifdef Use_J_Memory +#undef diff +#undef mult +#undef P +#undef MALLOC +#include "j.h" + + static void * +d2a_Malloc +#ifdef KR_headers + (k) int k; +#else + (struct dtoa_info *di, int n) +#endif +{ + A z; + J jt=(J)di->jt; + + z=jtga(jt, LIT, n, 1, 0); + if(!z || jt->jerr) longjmp(di->_env, 1); + return AV(z); + } + + +#endif + +B jtecvtinit(J jt) {A x; struct dtoa_info *di; + if(jt->dtoa) R 1; + GA(x, LIT, sizeof(struct dtoa_info), 1, 0); + di=(struct dtoa_info*)AV(x); + di->_p5s=0; + di->_pmem_next=di->_private_mem; + memset(di->_private_mem, 0, sizeof(di->_private_mem)); + memset(di->_freelist, 0, sizeof(di->_freelist)); + di->jt=jt; + ra(x); jt->dtoa=di; + R 1; +} + +/* uses dtoa and behaves like ecvt (well, ecvt_r) */ +/* this writes exactly ndp bytes at dest */ +B jtecvt(J jt, D dw, I ndp, int *decpt, int *sign, C *dest) +{ + struct dtoa_info *di=(struct dtoa_info*)jt->dtoa; + C *y,*z=0; + + ASSERTSYS(ndp<=INT_MAX, "jtecvt: too long"); + di->ndp=(int)ndp; di->result=dest; + y=d2a_dtoa(di, dw, 2, (int)ndp, decpt, sign, &z); + RZ(y&&z); + memset(z, '0', ndp-(z-y)); + R 1; +} + +#ifdef __cplusplus +} +#endif diff --git a/dtoa.h b/dtoa.h new file mode 100644 --- /dev/null +++ b/dtoa.h @@ -0,0 +1,27 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* Jsoftware Copyright applies only to changes made by Jsoftware */ +#include + +#if SYS & SYS_MACOSX +/* Use the non-signal restoring pair */ +#define setjmp _setjmp +#define longjmp _longjmp +#endif + +#ifndef HAVE_BIGINT +struct dtoa_info { + jmp_buf _env; +}; +#else +struct dtoa_info { + jmp_buf _env; + Bigint *_p5s; + double *_pmem_next; + double _private_mem[PRIVATE_mem]; + Bigint *_freelist[Kmax+1]; + void *jt; + int ndp; + char *result; +}; +#endif diff --git a/f.c b/f.c new file mode 100644 --- /dev/null +++ b/f.c @@ -0,0 +1,444 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Format: ": Monad */ + +#include "j.h" + +#if SY_64 +#define WI 21L +#else +#define WI 12L +#endif + +#define WD (9L+NPP) +#define WZ (WD+WD) +#define FMTF(f,T) void f(J jt,C*s,T*v) +#define ENGAP(j,r,s,exp) \ + {B b;I k=1,p=j,*sr=s+r-2; DO(p?r-1:0, k*=*(sr-i); b=!(p%k); exp;); } + +static F1(jtthxqe); + +static FMTF(jtfmtI,I){I x=*v; + sprintf(s,FMTI,x); + if('-'==*s)*s=CSIGN; +} + +static FMTF(jtfmtD,D){B q;C buf[1+WD],c,*t;D x=*v;I k=0; + if(!memcmp(v,&inf, SZD)){strcpy(s,"_" ); R;} + if(!memcmp(v,&infm,SZD)){strcpy(s,"__"); R;} + if(_isnan(*v) ){strcpy(s,"_."); R;} + x=*v; x=x==*(D*)minus0?0.0:x; /* -0 to 0*/ + sprintf(buf,jt->pp,x); + c=*buf; if(q=c=='-')*s++=CSIGN; q=q||(c=='+'); + if('.'==buf[q])*s++='0'; + MC(s,buf+q,WD+1-q); + if(t=strchr(s,'e')){ + if('-'==*++t)*t++=CSIGN; + while(c=*(k+t),c=='0'||c=='+')k++; + if(k)while(*t=*(k+t))t++; +}} + +static FMTF(jtfmtZ,Z){fmtD(s,&v->re); if(v->im){I k=strlen(s); *(k+s)='j'; fmtD(1+k+s,&v->im);}} + +static void thcase(I t,I*wd,VF*fmt){ + switch(t){ + case CMPX: *wd=WZ; *fmt=jtfmtZ; break; + case FL: *wd=WD; *fmt=jtfmtD; break; + default: *wd=WI; *fmt=jtfmtI; +}} + +I jtthv(J jt,A w,I n,C*s){A t;B ov=0;C buf[WZ],*x,*y=s;I k,n4=n-4,p,wd,wn,wt;VF fmt; + RZ(w&&n); + wn=AN(w); wt=AT(w); x=CAV(w); thcase(wt,&wd,&fmt); + switch(wt){ + case XNUM: case RAT: + RZ(t=thxqe(w)); p=AN(t); if(ov=n=wn*wd)DO(wn, fmt(jt,y,x); y+=strlen(y); *y++=' '; x+=k;) + else DO(wn, fmt(jt,buf,x); p=strlen(buf); if(ov=n4<1+p+y-s)break; strcpy(y,buf); y+=p; *y++=' '; x+=k;); + } + if(ov){if(' '!=*(y-1))*y++=' '; memset(y,'.',3L); y+=3;} + else if(' '==*(y-1))--y; + *y=0; R y-s; +} + +static F1(jtthbit){A z;UC*x;C*y;I c,i,m,n,p,q,r,r1,*s; + n=AN(w); r=AR(w); s=AS(w); + c=r?s[r-1]:1; m=n/c; p=2*c-1; + GA(z,LIT,m*p,r+!r,s); *(AS(z)+AR(z)-1)=p; + x=UAV(w); y=CAV(z); + q=c/BB; r=c%BB; r1=c%BW?(BW-c%BW)/BB:0; + for(i=0;i=r){p=thv(w,AN(t),tv); ASSERTSYS(p,"thn"); AN(t)=*AS(t)=p; z=t;} + else{ + c=s[r-1]; m=n/c; k=bp(AT(w)); + y=tv-wd; x=CAV(w)-k; + RZ(d=apv(c,1L,0L)); dv=AV(d); + DO(m, DO(c, fmt(jt,y+=wd,x+=k); p=strlen(y); dv[i]=MAX(dv[i],p););); + --dv[c-1]; p=0; DO(c, p+=++dv[i];); + GA(z,LIT,m*p,r+!r,s); *(AS(z)+AR(z)-1)=p; zv=CAV(z); memset(zv,' ',AN(z)); + y=tv; DO(m, DO(c, zv+=dv[i]; p=strlen(y); MC(zv-p-(c>1+i),y,p); y+=wd;);); + } + R z; +} + +static F1(jtthsb){A d,z;C*zv;I c,*dv,m,n,p,q,r,*s;SB*x,*y;SBU*u; + n=AN(w); r=AR(w); s=AS(w); x=y=SBAV(w); q=jt->sbun; + if(1>=r){ + c=n; + p=2*n-1; DO(c, p+=SBUV(*x++)->n;); + GA(z,LIT, p,1, 0); zv=CAV(z); memset(zv,' ',AN(z)); + DO(c, u=SBUV(*y++); *zv='`'; MC(1+zv,SBSV(u->i),u->n); zv+=2+u->n;); + }else{ + c=s[r-1]; m=n/c; RZ(d=apv(c,0L,0L)); dv=AV(d); + DO(m, DO(c, p =SBUV(*x++)->n; dv[i]=MAX(dv[i],p););); + p=-1; DO(c, p+=dv[i]+=2;); --dv[c-1]; + GA(z,LIT,m*p,r+!r,s); zv=CAV(z); memset(zv,' ',AN(z)); *(AS(z)+AR(z)-1)=p; + DO(m, DO(c, u=SBUV(*y++); *zv='`'; MC(1+zv,SBSV(u->i),u->n); zv+=dv[i];);); + } + R z; +} + +static F1(jtthx1){A z;B b;C*s,s1[2+XBASEN];I n,p,p1,*v; + n=AN(w); v=AV(w)+n-1; b=0>*v; + p=*v; if(p==XPINF)R cstr("_"); else if(p==XNINF)R cstr("__"); + sprintf(s1,FMTI,*v); p1=strlen(s1); + p=p1+XBASEN*(n-1); + GA(z,LIT,p,1,0); s=CAV(z); + MC(s,s1,p1); if(b)*s=CSIGN; s+=p1; + DO(n-1, --v; sprintf(s,FMTI04,b?-*v:*v); s+=XBASEN;); + R z; +} + +static A jtthq1(J jt,Q y){A c,d,z;B b;C*zv;I m,n=-1; + RZ(c=thx1(y.n)); m=AN(c); + d=y.d; + if(b=1*v; + if(p==DXINF)R cstr("_"); else if(p==DXMINF)R cstr("__"); + sprintf(s1,FMTI,b?-*v:*v); p1=strlen(s1); + if(e&&*v){s=s2; *s++='e'; if(0>e)*s++=CSIGN; sprintf(s,FMTI,01+i),AV(y),p);)); + R z; +} + + +static B jtrc(J jt,A w,A*px,A*py){A*v,x,y;I j,k,r,*s,xn,*xv,yn,*yv; + RZ(w); + r=AR(w); s=AS(w); v=AAV(w); + xn=1bx[k]; a=b?' ':jt->bx[10]; d=b?l:jt->bx[1+k]; r=b?l:jt->bx[2+k]; + *v++=l; DO(n, memset(v,a,x[i]-1); v+=x[i]-1; *v++=d;); *--v=r; +} + +static void jtfminit(J jt,I m,I ht,I wd,A x,A y,C*zv){C*u,*v;I p,xn,*xv,yn,*yv; + p=ht*wd; + xn=AN(x)-1; xv=AV(x); + yn=AN(y)-1; yv=AV(y); + fram(9L,yn,yv,zv); u=zv; DO(ht-2, MC(u+=wd,zv,wd);); + fram(3L,yn,yv,u=v=zv+wd**xv); DO(xn-1, MC(u+=wd*xv[1+i],v,wd);); + fram(0L,yn,yv,zv); + fram(6L,yn,yv,zv+p-wd); + u=zv; DO(m-1, MC(u+=p,zv,p);); +} /* Initialize with box-drawing characters */ + +static void jtfmfill(J jt,I p,I q,I wd,A w,A x,A y,C*zv){A e,*wv;C*u,*v; + I c,d,i,j,k,n,r,*s,xn,xp,*xv,yn,yp,*yv; + n=AN(w); wv=AAV(w); + xp=jt->pos[0]; yp=jt->pos[1]; + xn=AN(x)-1; xv=AV(x); j=1; DO(1+xn, k=xv[i]; xv[i]=j; j+=k;); + yn=AN(y)-1; yv=AV(y); j=1; DO(1+yn, k=yv[i]; yv[i]=j; j+=k;); + for(i=0;i=p,EVLIMIT); k+=m;);} + RE(p=mult(m,q)+k*!!q); ASSERT(0<=p,EVLIMIT); RE(zn=mult(p,c)); + GA(z,LIT,zn,2,0); *AS(z)=p; *(1+AS(z))=c; x=CAV(z); + if(2s[i])s[i]=ctrl[s[i]];); + R z; +} + +static F1(jtths){A e,i,x,z;C c,*u,*v;I d,m,n,*s;P*p; + RZ(scheck(w)); + p=PAV(w); e=SPA(p,e); i=SPA(p,i); x=SPA(p,x); + RZ(i=thorn1(i)); s=AS(i); m=s[0]; n=s[1]; + RZ(x=thorn1(1bx[9]; DO(*s, *(v+n)=c; v+=d;); + R z; +} + +F1(jtthorn1){PROLOG;A z; + RZ(w); + if(!AN(w))GA(z,LIT,0,AR(w),AS(w)) + else switch(AT(w)){ +#ifdef UNDER_CE + default: if(AT(w)&XD+XZ)z=thxqe(w); else R 0; break; + case XNUM: case RAT: + z=thxqe(w); break; +#else + default: R 0; + case XNUM: case RAT: case XD: case XZ: + z=thxqe(w); break; +#endif + case BIT: z=thbit(w); break; + case B01: z=thb(w); break; + case LIT: z=ca(w); break; + case C2T: z=rank1ex(w,0L,1L,jttoutf8); break; + case BOX: z=thbox(w); break; + case SBT: z=thsb(w); break; + case NAME: z=sfn(0,w); break; + case ASGN: z=spellout(*CAV(w)); break; + case INT: case FL: case CMPX: + z=thn(w); break; + case SB01: case SINT: case SFL: case SCMPX: case SLIT: case SBOX: + z=ths(w); break; + case VERB: case ADV: case CONJ: + switch((jt->disp)[1]){ + case 1: z=thorn1(arep(w)); break; + case 2: z=thorn1(drep(w)); break; + case 4: z=thorn1(trep(w)); break; + case 5: z=thorn1(lrep(w)); break; + case 6: z=thorn1(prep(w)); break; + }} + EPILOG(z); +} + +#define DDD(v) {*v++='.'; *v++='.'; *v++='.';} +#define EOL(zv) {zv[0]=eov[0]; zv[1]=eov[1]; zv+=m; ++lc;} +#define BDC(x) if(16<=x&&x<=26){*(zv-1)='\342'; *zv++='\224'; *zv++=bdc[x];} + +static I scanbdc(C*v,I h,I nq,I c,I lb,I la){C*u,x;I m; + u=v; x=0; m=0; + if(h>=nq) + DO(c*nq, x=*u++; if(16<=x&&x<=26)m+=3;) + else{ + DO(c*lb, x=*u++; if(16<=x&&x<=26)m+=3;); + u=v+c*(nq-la); + DO(c*la, x=*u++; if(16<=x&&x<=26)m+=3;); + } + R m; +} /* scan for box drawing chars requiring additional space */ + +static I scaneol(C*v,I h,I nq,I c,I lb,I la){C e,*u,x;I m; + u=v; x=0; m=0; + if(h>=nq) + DO(c*nq, e=x; x=*u++; if(x==CCR)++m; else if(x==CLF)e==CCR?--m:++m;) + else{ + DO(c*lb, e=x; x=*u++; if(x==CCR)++m; else if(x==CLF)e==CCR?--m:++m;); + u=v+c*(nq-la); + DO(c*la, e=x; x=*u++; if(x==CCR)++m; else if(x==CLF)e==CCR?--m:++m;); + } + R m; +} /* scan for EOL requiring additional space */ + +/* zn: max length of zu,zv */ +/* zu: points to start of data area */ +/* zv: points to 1 + end of data area */ +/* lb: # lines before ... */ +/* la: # lines after ... */ +/* m: # chars in end-of-line */ +/* eo: eol if 1 char */ +/* eol: eol if 2 chars */ + +static C*dropl(I zn,C*zu,C*zv,I lb,I la,I m,C eo,C*eov){C*u,*v;I lc=0,n,p,q; + p=q=0; u=zu; v=zv; + if(1==m){ + DO(zn, if(p>=lb)break; if(eo ==*u++ )p++;); + DO(zn, if(q> la)break; if(eo ==*--v )q++;); + }else{ + DO(zn, if(p>=lb)break; if(*(S*)eov==*(S*)(u++))p++;); + DO(zn, if(q> la)break; if(*(S*)eov==*(S*)(--v))q++;); + } + DDD(u); EOL(u); n=zv-(m+v); memmove(u,m+v,n); + R u+n; +} /* drop excessive lines */ + +static A jtjprx(J jt,I ieol,I maxlen,I lb,I la,A w){A y,z;B ch;C e,eo,*eov,*v,x,*zu,*zv;D lba; + I c,c1,h,i,j,k,lc,m,n,nbx,nq,p,q,r,*s,zn;S eol; + static C bdc[]="123456789_123456\214\254\220\234\274\244\224\264\230\202\200"; + RZ(y=thorn1(w)); + ch=1&&AT(w)&LIT+C2T+SBT; + r=AR(y); s=AS(y); v=CAV(y); eov=(C*)&eol; + q=1la){h=IMAX; p=nq-la; v+=c*(p-i); i=p-1; DDD(zv);} + else if(ch)for(j=k=x=0;j1+lba)zv=dropl(zn,zu,zv,lb,la,m,eo,eov); + p=zv-zu; + ASSERTSYS(p<=zn,"jprx zn"); + *zv=0; z->n=*(z->s)=p; + R z; +} /* output string from array w */ + +F2(jtoutstr){I*v; + RZ(a&&w); + RZ(a=vib(a)); + ASSERT(1==AR(a), EVRANK); + ASSERT(4==AN(a), EVLENGTH); + ASSERT(INT&AT(a),EVDOMAIN); + v=AV(a); + ASSERT(0<=v[0]&&v[0]<=2,EVINDEX); + ASSERT(0<=v[1],EVDOMAIN); + ASSERT(0<=v[2],EVDOMAIN); + ASSERT(0<=v[3],EVDOMAIN); + R jprx(v[0],v[1],v[2],v[3],w); +} + +static F1(jtjpr1){PROLOG;A z; + RZ(z=jprx(jt->outeol,jt->outmaxlen,jt->outmaxbefore,jt->outmaxafter,w)); + if(AN(z))jsto(jt,jt->mtyo==0?MTYOFM:jt->mtyo,CAV(z)); + EPILOG(mtm); +} + +F1(jtjpr){A y;I i,n,t,*v; + RZ(w); + t=AT(w); + if(t&NOUN&&jt->tostdout)RZ(jpr1(w)) + else if(t&VERB+ADV+CONJ){ + RZ(y=evoke(w)?symbrdlock(VAV(w)->f):w); + if(jt->tostdout){ + n=*jt->disp; v=1+jt->disp; + for(i=0;ipos[0]; q=jt->pos[1]; + RZ(a=vi(a)); n=AN(a); v=AV(a); + ASSERT(1>=AR(a),EVRANK); + ASSERT(1==n||2==n,EVLENGTH); + x=v[0]; y=2>n?0:v[1]; + ASSERT(0<=x&&x<=2&&0<=y&&y<=2,EVDOMAIN); + jt->pos[0]=x; jt->pos[1]=y; + z=thorn1(w); + jt->pos[0]=p; jt->pos[1]=q; + R z; +} + +static I jtc2j(J jt,B e,I m,C*zv){C c,*s,*t;I k,p; + if(e&&(t=strchr(jt->th2buf,'e'))){ + ++t; t+='-'==*t; + k=0; while(c=*(k+t),c=='0'||c=='+')++k; + if(k){ + if(!c||' '==c){*t++='0'; --k;} + while(*t=*(k+t))++t; + p=m-(t-jt->th2buf); DO(p,*t++=' ';); if(0<=p)jt->th2buf[m]=0; + }} + t=jt->th2buf; k=strlen(t); + if(!e&&(s=memchr(t,'-',k))){ /* turn -0 to 0 */ + *s=' '; + DO(k-(1+s-t), c=s[1+i]; if(c!='0'&&c!='.'){*s=CSIGN; break;}); + if(!m&&' '==*s){++t; --k;} + } + if(m&&mth2buf;I k; + if(jt->th2bufn<20+d){A s; jt->th2bufn=20+d; GA(s,LIT,jt->th2bufn,1,0); v=jt->th2buf=CAV(s);} + if(b)*v++='_'; else if(m)*v++=' '; *v++=' '; sprintf(v,FMTI,c); v+=q; + k=(XBASEN+d+1-q)/XBASEN; k=MIN(n-1,k); + DO(k, c=*--xv; sprintf(v,FMTI04,b?-c:c); v+=XBASEN;); + k=v-jt->th2buf-(2+bm); + if(kd&&(u=v=jt->th2buf+d+2+bm,'5'<=*v)){ + while('9'==*--u); + if(' '!=*u)++*u; else{*++u='1'; ++ex;} + memset(u+1,'0',v-u-1); + } + jt->th2buf[bm]=jt->th2buf[bm+1]; jt->th2buf[bm+1]='.'; sprintf(v-!d,"e"FMTI"",ex); + R 1; +} /* format one extended integer in exponential form */ + +static B jtfmtx(J jt,B e,I m,I d,C*s,I t,X*wv){B b;C*v=jt->th2buf;I c,n,p,q,*xv;X x; + x=*wv; n=AN(x); xv=AV(x)+n-1; + c=*xv; b=0>c; if(b)c=-c; + if(c==XPINF){if(b)*v++='_'; *v++='_'; *v=0; R 1;} + q=c>999?4:c>99?3:c>9?2:1; p=q+XBASEN*(n-1); + if(e)R fmtex(m,d,n,xv,b,c,q,p-1); + else if(m&&mth2bufn<4+p+d){A s; jt->th2bufn=4+p+d; GA(s,LIT,jt->th2bufn,1,0); v=jt->th2buf=CAV(s);} + if(' '==*s)*v++=' '; if(b)*v++='_'; + sprintf(v,FMTI,c); v+=q; + DO(n-1, c=*--xv; sprintf(v,FMTI04,b?-c:c); v+=XBASEN;); + if(d){*v++='.'; memset(v,'0',d); v[d]=0;} + } + R 1; +} /* format one extended integer */ + +static B jtfmtq(J jt,B e,I m,I d,C*s,I t,Q*wv){B b;C*v=jt->th2buf;I c,ex=0,k,n,p,q,*xv;Q y;X a,g,x; + y=*wv; x=y.n; c=XDIG(x); b=0>c; if(b)x=negate(x); + if(c==XPINF||c==XNINF){if(e)*v++=' '; if(e>b)*v++=' '; if(b)*v++='_'; *v++='_'; *v=0; R 1;} + RZ(a=xpow(xc(10L),xc(1+d))); + if(e&&c&&0>xcompare(x,y.d)){ + ex=XBASEN*(AN(y.n)-AN(y.d)); + g=xtymes(x,xpow(xc(10L),xc(1+d-ex))); + RZ(x=xdiv(g,y.d,XMFLR)); + while(1==xcompare(a,x)){--ex; g=xtymes(xc(10L),g); RZ(x=xdiv(g,y.d,XMFLR));} + if(b)x=negate(x); + }else x=xdiv(xtymes(y.n,a),y.d,XMFLR); + RZ(x=xdiv(xplus(x,xc(5L)),xc(10L),XMFLR)); + n=AN(x); xv=AV(x)+n-1; c=*xv; b=0>c; if(b)c=-c; + q=c>999?4:c>99?3:c>9?2:1; p=q+XBASEN*(n-1); if(c||!e)ex+=p-d-1; + if(e)R fmtex(m,d,n,xv,b,c,q,ex); + else if(m&&mex?1:1+ex)){memset(v,'*',m); v[m]=0;} + else{ + if(jt->th2bufn<4+p+d){A s; jt->th2bufn=4+p+d; GA(s,LIT,jt->th2bufn,1,0); v=jt->th2buf=CAV(s);} + if(' '==*s)*v++=' '; if(b)*v++='_'; + if(0>ex){k=-ex-1; DO(1+MIN(d,k), *v++='0';);} + sprintf(v,FMTI,c); v+=q; + DO(n-1, c=*--xv; sprintf(v,FMTI04,b?-c:c); v+=XBASEN;); + if(d){v[1]=0; DO(d, *v=*(v-1); --v;); *v='.';} + } + R 1; +} /* format one rational number */ + +static void jtfmt1(J jt,B e,I m,I d,C*s,I t,C*wv){D y; + switch(t){ + case B01: sprintf(jt->th2buf,s,(D)*wv); break; + case INT: sprintf(jt->th2buf,s,(D)*(I*)wv); break; + case XNUM: fmtx(e,m,d,s,t,(X*)wv); break; + case RAT: fmtq(e,m,d,s,t,(Q*)wv); break; + default: + y=*(D*)wv; y=y?y:0.0; /* -0 to 0 */ + if (!memcmp(wv,&inf, SZD))strcpy(jt->th2buf,e?" _" :' '==*s?" _" :"_" ); + else if(!memcmp(wv,&infm,SZD))strcpy(jt->th2buf,e?" __" :' '==*s?" __":"__"); + else if(_isnan(*wv) )strcpy(jt->th2buf,e?" _.":' '==*s?" _.":"_."); + else sprintf(jt->th2buf,s,y); +}} /* format one number */ + +static void jtth2c(J jt,B e,I m,I d,C*s,I n,I t,I wk,C*wv,I zk,C*zv){ + DO(n, fmt1(e,m,d,s,t,wv); c2j(e,m,zv); zv+=zk; wv+=wk;); +} /* format a column */ + +static A jtth2a(J jt,B e,I m,I d,C*s,I n,I t,I wk,C*wv,B first){PROLOG;A y,z;B b=0;C*u,*yv,*zv;I i,m0=m,k,p,q; + q=m?m:t&B01?3:t&INT?12:17; p=n*q; + GA(z,LIT,p,2,0); *AS(z)=n; *(1+AS(z))=q; zv=CAV(z); + if(m){th2c(e,m,d,s,n,t,wk,wv,m,zv); R z;} + for(i=q=0;ith2buf)+1){RZ(z=over(z,z)); p+=p; zv=CAV(z);} + u=q+zv; q+=k=c2j(e,0L,u); b=b||CSIGN==*u; zv[q++]=0; m=MAX(m,k); wv+=wk; + } + m+=!first; + GA(y,LIT,n*m,2,0); *AS(y)=n; *(1+AS(y))=m; + yv=CAV(y); memset(yv,' ',AN(y)); u=zv; + if(e){yv+=!first; DO(n, q=strlen(u); MC(yv+(b&&CSIGN!=*u),u,q); yv+=m; u+=1+q;);} + else {yv+=m; DO(n, q=strlen(u); MC(yv-q, u,q); yv+=m; u+=1+q;);} + EPILOG(y); +} /* like th2c, but allocates and returns array */ + +static B jtth2ctrl(J jt,A a,A*ep,A*mp,A*dp,A*sp,I*zkp){A da,ea,ma,s;B b=1,*ev,r; + C*sv;D x,y;I an,*av,d,*dv,i,m,*mv,sk=15,zk=0;Z*au; + r=!(CMPX&AT(a)); jt->th2bufn=500; + if(r)RZ(a=cvt(INT,a)); + an=AN(a); au=ZAV(a); av=AV(a); + GA(ea,B01,an, 1,0); *ep=ea; ev=BAV(ea); + GA(ma,INT,an, 1,0); *mp=ma; mv= AV(ma); + GA(da,INT,an, 1,0); *dp=da; dv= AV(da); + GA(s, LIT,an*sk,2,0); *sp=s; sv=CAV(s); *AS(s)=an; *(1+AS(s))=sk; + for(i=0;iy)x=-1; + } + if(0>m)m=-m; if(0>d)d=-d; ASSERT(0<=m&&0<=d,EVLIMIT); + if(0<=x)sprintf(sv, "%%"FMTI"."FMTI"f", m,d); + else sprintf(sv, m?"%%- "FMTI"."FMTI"e" :"%%-"FMTI"."FMTI"e", m?m-1:0,d+!!(SYS&SYS_PC)); + sv+=sk; ev[i]=0>x; mv[i]=m; dv[i]=d; zk+=m; b=b&&m; + if(jt->th2bufnth2bufn=m; if(jt->th2bufn<500+d)jt->th2bufn=500+d; + } + GA(s,LIT,jt->th2bufn,1,0); jt->th2buf=CAV(s); + *zkp=b?zk:0; R 1; +} /* parse format control (left argument of ":) */ + +F2(jtthorn2){PROLOG;A da,ea,h,ma,s,y,*yv,z;B e,*ev;C*sv,*wv,*zv;I an,c,d,*dv,k,m,*mv,n,r,sk,t,wk,*ws,zk; + F2RANK(1,RMAX,jtthorn2,0); + an=AN(a); t=AT(w); + if(t&BOX)R th2box(a,w); + ASSERT(t&NUMERIC&&!(t&SPARSE)&&!(AT(a)&SPARSE),EVDOMAIN); + r=AR(w); ws=AS(w); c=r?ws[r-1]:1; n=c?AN(w)/c:prod(r-1,ws); + ASSERT(!AR(a)||c==an,EVLENGTH); + k=bp(t); wk=c*k; wv=CAV(w)-k; + RZ(th2ctrl(a,&ea,&ma,&da,&s,&zk)); + ev=BAV(ea); mv=AV(ma); dv=AV(da); sk=1 +#endif + +J gjt=0; // JPF debug + +void startup(void); + +static A jtmakename(J jt,C*s){A z;I m;NM*zv; + m=strlen(s); + GA(z,NAME,m,1,0); zv=NAV(z); + memcpy(zv->s,s,m); *(m+zv->s)=0; + zv->m =(UC)m; + zv->sn =0; + zv->e =0; + zv->flag=NMDOT; + zv->hash=NMHASH(m,s); + ACX(z); + R z; +} + +B jtglobinit(J jt){A x,y;C*s;D*d;I j;UC c,k; + liln=1&&SYS&SYS_LILENDIAN; + jt->adbreak=&breakdata; /* required for ma to work */ + meminit(); /* required for ma to work */ + jt->parsercalls=0; + s=bitdisp; + DO(256, c=(UC)i; DO(BB, *s++=c&(UC)128?'1':'0'; *s++=' '; c<<=1;); ); + DO(16, c=(UC)i; k=0; DO(BB, if(c&(UC)1)++k; c>>=1;); bitc[i]=k;); + DO(15, j=1+i; DO(16, bitc[16*j+i]=bitc[j]+bitc[i];);); + MC(&inf, XINF,SZD); + MC(&jnan,XNAN,SZD); + infm=-inf; + memset(testb,C0,256); + testb[CIF]=testb[CELSEIF]=testb[CSELECT]=testb[CWHILE]=testb[CWHILST]=testb[CFOR]=testb[CCASE]=testb[CFCASE]=1; + num=9+numv; + DO(9, GA(x,INT,1,0,0); ACX(x); * AV(x)=i-9; num[i-9] =x;); + DO(8, GA(x,INT,1,0,0); ACX(x); * AV(x)=i+2; num[i+2] =x;); + GA(x,B01, 1,0,0 ); ACX(x); *BAV(x)=0; num[0]=zero=x; + GA(x,B01, 1,0,0 ); ACX(x); *BAV(x)=1; num[1]=one =x; + memset(chr,C0,256*SZI); + GA(x,LIT, 1,0,0 ); ACX(x); *CAV(x)=' '; chr[' ' ]=x; + GA(x,LIT, 1,0,0 ); ACX(x); *CAV(x)=':'; chr[':' ]=x; + GA(x,LIT, 1,0,0 ); ACX(x); *CAV(x)='/'; chr['/' ]=x; + GA(x,LIT, 1,0,0 ); ACX(x); *CAV(x)='\\'; chr['\\' ]=x; + GA(x,LIT, 1,0,0 ); ACX(x); *CAV(x)=CQUOTE; chr[CQUOTE]=x; + GA(x,B01, 0,1,0 ); ACX(x); mtv =x; + GA(x,LIT, 0,1,0 ); ACX(x); aqq =x; + GA(x,INT, 1,1,0 ); ACX(x); * AV(x)=0; iv0=xzero =x; + GA(x,INT, 1,1,0 ); ACX(x); * AV(x)=1; iv1=xone =x; + GA(x,FL, 1,0,0 ); ACX(x); *DAV(x)=inf; ainf =x; + GA(x,FL, 1,0,0 ); ACX(x); *DAV(x)=PI; pie =x; + GA(x,MARK,1,0,0 ); ACX(x); * AV(x)=0; mark =x; + GA(x,B01, 0,2,&zeroZ); ACX(x); mtm =x; + GA(x,CMPX,1,0,0 ); ACX(x); d=DAV(x); *d=0; *(1+d)=1; a0j1 =x; + RZ(y=str(1L,"z")); ACX(y); + GA(x,BOX, 1,1,0 ); ACX(x); *AAV(x)=y; zpath =x; + RZ(mnam=makename("m")); RZ(mdot=makename("m.")); + RZ(nnam=makename("n")); RZ(ndot=makename("n.")); + RZ(unam=makename("u")); RZ(udot=makename("u.")); + RZ(vnam=makename("v")); RZ(vdot=makename("v.")); + RZ(xnam=makename("x")); RZ(xdot=makename("x.")); + RZ(ynam=makename("y")); RZ(ydot=makename("y.")); + zeroQ.n =xzero; zeroQ.d =xone; + zeroDX.e=0; zeroDX.x=xzero; + memset(minus0,C0,8L); minus0[SYS&SYS_LILENDIAN?7:0]='\200'; + pf=qpf(); + pinit(); + R 1; +} /* called once when dll is loaded to create global constants */ + +static B jtevinit(J jt){A q,*v; + GA(q,BOX,1+NEVM,1,0); v=AAV(q); + DO(AN(q), v[i]=mtv;); + v[EVALLOC ]=cstr("allocation error" ); + v[EVASSERT ]=cstr("assertion failure" ); + v[EVATTN ]=cstr("attention interrupt" ); + v[EVBREAK ]=cstr("break" ); + v[EVCTRL ]=cstr("control error" ); + v[EVDOMAIN ]=cstr("domain error" ); + v[EVFACCESS]=cstr("file access error" ); + v[EVFNAME ]=cstr("file name error" ); + v[EVFNUM ]=cstr("file number error" ); + v[EVILNAME ]=cstr("ill-formed name" ); + v[EVILNUM ]=cstr("ill-formed number" ); + v[EVINDEX ]=cstr("index error" ); + v[EVINPRUPT]=cstr("input interrupt" ); + v[EVFACE ]=cstr("interface error" ); + v[EVLENGTH ]=cstr("length error" ); + v[EVLIMIT ]=cstr("limit error" ); + v[EVLOCALE ]=cstr("locale error" ); + v[EVNAN ]=cstr("NaN error" ); + v[EVNONCE ]=cstr("nonce error" ); + v[EVSPARSE ]=cstr("non-unique sparse elements" ); + v[EVOPENQ ]=cstr("open quote" ); + v[EVWSFULL ]=cstr("out of memory" ); + v[EVRANK ]=cstr("rank error" ); + v[EVRO ]=cstr("read-only data" ); + v[EVSECURE ]=cstr("security violation" ); + v[EVSPELL ]=cstr("spelling error" ); + v[EVSTACK ]=cstr("stack error" ); + v[EVSTOP ]=cstr("stop" ); + v[EVSYNTAX ]=cstr("syntax error" ); + v[EVSYSTEM ]=cstr("system error" ); + v[EVTIME ]=cstr("time limit" ); + v[EVVALUE ]=cstr("value error" ); + ra(q); jt->evm=q; + if(jt->jerr){printf("evinit failed; error %hhi\n", jt->jerr); R 0;} else R 1; +} + +/* static void sigflpe(int k){jsignal(EVDOMAIN); signal(SIGFPE,sigflpe);} */ + +static B jtconsinit(J jt){D y; + jt->assert=1; + RZ(jt->bxa=cstr("+++++++++|-")); jt->bx=CAV(jt->bxa); + y=1.0; DO(44, y*=0.5;); jt->ct=jt->fuzz=y; + jt->disp[0]=1; jt->disp[1]=5; + jt->fcalln=NFCALL; + jt->fdepn=NFDEP; + jt->outmaxafter=222; + jt->outmaxlen=256; + strcpy(jt->outseq,"\x0a"); + strcpy(jt->pp,"%0.6g"); + jt->retcomm=1; + jt->tostdout=1; + jt->transposeflag=1; + jt->xmode=XMEXACT; + R 1; +} + +static C jtjinit3(J jt){S t; +/* required for jdll and doesn't hurt others */ + gjt=jt; // global jt for JPF debug +#if (SYS & SYS_DOS) + t=EM_ZERODIVIDE+EM_INVALID; _controlfp(t,t); +#endif +#if (SYS & SYS_OS2) + t=EM_ZERODIVIDE+EM_INVALID+EM_OVERFLOW+EM_UNDERFLOW; _control87(t,t); +#endif +#if (SYS & SYS_FREEBSD) + fpsetmask(0); +#endif + jt->tssbase=tod(); + meminit(); + sesminit(); + evinit(); + consinit(); + symbinit(); + parseinit(); + xoinit(); + xsinit(); + sbtypeinit(); + rnginit(); +#if (SYS & SYS_DOS+SYS_MACINTOSH) + xlinit(); +#endif + jtecvtinit(jt); + R !jt->jerr; +} + +C jtjinit2(J jt,int dummy0,C**dummy1){jt->sesm=1; R jinit3();} diff --git a/io.c b/io.c new file mode 100644 --- /dev/null +++ b/io.c @@ -0,0 +1,409 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Input/Output */ + +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#include +#define _stdcall +#endif + +#include "j.h" +#include "d.h" + +void jtwri(J jt,I type,C*p,I m,C*s){C buf[1024],*t=jt->outseq,*v=buf;I c,d,e,n; + if(jt->tostdout){ + c=strlen(p); /* prompt */ + e=strlen(t); /* end-of-line */ + n=sizeof(buf)-(c+e+1); /* main text */ + d=m>n?n-3:m; + memcpy(v,p,c); v+=c; + memcpy(v,s,d); v+=d; if(m>n){memcpy(v,"...",3L); v+=3;} + memcpy(v,t,e); v+=e; + *v=0; + jsto(jt,type,buf); +}} + +static void jtwrf(J jt,I n,C*v,F f){C*u,*x;I j=0,m; + while(n>j){ + u=j+v; + m=(x=memchr(u,CLF,n-j))?1+x-u:n-j; + fwrite(u,sizeof(C),m,f); + j+=m; +}} + +A jtinpl(J jt,B b,I n,C*s){C c;I k=0; + if(n&&(c=*(s+n-1),CLF==c||CCR==c))--n; + ASSERT(!*jt->adbreak,EVINPRUPT); + if(!b){ /* 1==b means literal input */ + if(n&&COFF==*(s+n-1))joff(zero); + c=jt->bx[9]; if(c<0)DO(n, if(' '!=s[i]&&c!=s[i]){k=i; break;}); + } + R str(n-k,s+k); +} + +static I advl(I j,I n,C*s){B b;C c,*v; + v=j+s; + DO(n-j, c=*v++; b=c==CCR; if(b||c==CLF)R j+1+i+(b&&CLF==*v);); + R n; +} /* advance one line on CR, CRLF, or LF */ + +void breakclose(J jt); + +static C* nfeinput(J jt,C* s){A y; + jt->breakignore=1; + y=exec1(cstr(s)); + jt->breakignore=0; + if(!y){breakclose(jt);exit(2);} /* J input verb failed */ + jtwri(jt,MTYOLOG,"",strlen(CAV(y)),CAV(y)); + return CAV(y); /* don't combine with previous line! CAV runs (x) 2 times! */ +} + +A jtjgets(J jt,C*p){A y;B b;C*v;I j,k,m,n;UC*s; + *jt->adbreak=0; + if(b=1==*p)p=""; /* 1 means literal input */ + if(jt->dcs){ + ++jt->dcs->dcn; j=jt->dcs->dci; + y=jt->dcs->dcy; n=AN(y); s=UAV(y); + RZ(jdcs->dcj=k=j; + jt->dcs->dci=j=advl(j,n,s); + m=j-k; if(m&&32>s[k+m-1])--m; if(m&&32>s[k+m-1])--m; + jtwri(jt,MTYOLOG,p,m,k+s); + R inpl(b,m,k+s); + } + /* J calls for input in 3 cases: + debug suspension for normal input + n : 0 input lines up to terminating ) + 1!:1[1 read from keyboard */ + showerr(); + if(jt->nfe) + v=nfeinput(jt,*p?"input_jfe_' '":"input_jfe_''"); + else{ + ASSERT(jt->sminput,EVBREAK); + v=((inputtype)(jt->sminput))(jt,p); + } + R inpl(b,(I)strlen(v),v); +} + +extern C breakdata; + +#if SYS&SYS_UNIX +void breakclose(J jt) +{ + if(jt->adbreak==&breakdata) return; + munmap(jt->adbreak,1); + jt->adbreak=&breakdata; + close(jt->breakfh); + jt->breakfh=0; + unlink(jt->breakfn); + *jt->breakfn=0; +} +#else +void breakclose(J jt) +{ + if(jt->adbreak==&breakdata) return; + UnmapViewOfFile(jt->adbreak); + jt->adbreak=&breakdata; + CloseHandle(jt->breakmh); + jt->breakmh=0; + CloseHandle(jt->breakfh); + jt->breakfh=0; +#if SY_WINCE + DeleteFile(tounibuf(jt->breakfn)); +#else + DeleteFile(jt->breakfn); +#endif + *jt->breakfn=0; +} +#endif + +F1(jtjoff){I x; + RZ(w); + x=i0(w); + breakclose(jt); + if(jt->sesm)jsto(jt, MTYOEXIT,(C*)x); + exit((int)x); + R 0; +} + +#if (SYS & SYS_SESM) + +I jdo(J jt, C* lp){I e,old;A x; + jt->jerr=0; jt->etxn=0; /* clear old errors */ + old=jt->tbase+jt->ttop; + *jt->adbreak=0; + x=inpl(0,(I)strlen(lp),lp); + while(jt->iepdo&&jt->iep){jt->iepdo=0; immex(jt->iep); jt->jerr=0; tpop(old);} + if(!jt->jerr)immex(x); + e=jt->jerr; + jt->jerr=0; + if(e&&DBERRCAP==jt->db&&jt->dbtrap){ + jt->db=0; + immex(jt->dbtrap); + jt->jerr=0; + } + while(jt->iepdo&&jt->iep){jt->iepdo=0; immex(jt->iep); jt->jerr=0; tpop(old);} + showerr(); + spfree(); + tpop(old); + R e; +} + +#define SZINT ((I)sizeof(int)) + +DF1(jtwd){A z=0;C*p=0;D*pd;I e,*pi,t;V*sv; + F1RANK(1,jtwd,self); + RZ(w); + ASSERT(2>AR(w),EVRANK); + sv=VAV(self); + t=i0(sv->g); + if(t>=2000 && t<3000 && AN(w) && LIT!=AT(w) && C2T!=AT(w) && INT!=AT(w)) + { + switch(AT(w)) + { + case B01: + RZ(w=vi(w));break; + case FL: + pd=DAV(w); + GA(w,INT,AN(w),AR(w),0); + pi=AV(w); + DO(AN(w),*pi++=(I)(jfloor(0.5+*pd++));); + break; + default: + ASSERT(0,EVDOMAIN); + } + } + // t is 11!:t and w is wd argument + e=jt->smdowd ? ((dowdtype)(jt->smdowd))(jt, (int)t, w, &z) : EVDOMAIN; + if(!e) R mtm; // e==0 is MTM + if(e==-1) R z; // e---1 is zp + ASSERT(e<=0,e); // e>=0 is EVDOMAIN etc + RZ(z=df1(z,cut(ds(CBOX),num[-2]))); // e==-2 is lit pairs + R reshape(v2(AN(z)/2,2L),z); +} + +C* getlocale(J jt){A y=locname(mtv); y=*AAV(y); R CAV(y);} + +static char breaknone=0; + +B jtsesminit(J jt){jt->adbreak=&breakdata; R 1;} +#endif + +int _stdcall JDo(J jt, char* lp){int r; + r=(int)jdo(jt,lp); + while(jt->nfe) + r=(int)jdo(jt,nfeinput(jt,"input_jfe_' '")); + R r; +} + +/* socket protocol CMDGET name */ +A _stdcall JGetA(J jt, I n, C* name){A x; + jt->jerr=0; + RZ(x=symbrdlock(nfs(n,name))); + ASSERT(!(FUNC&AT(x)),EVDOMAIN); + R binrep1(x); +} + +/* socket protocol CMDSET */ +I _stdcall JSetA(J jt,I n,C* name,I dlen,C* d){I old; + jt->jerr=0; + if(!vnm(n,name)) R EVILNAME; + old=jt->tbase+jt->ttop; + symbis(nfs(n,name),jtunbin(jt,str(dlen,d)),jt->global); + tpop(old); + R jt->jerr; +} + +/* set jclient callbacks */ +void _stdcall JSM(J jt, void* callbacks[]) +{ + jt->smoutput = (outputtype)callbacks[0]; + jt->smdowd = (dowdtype)callbacks[1]; + jt->sminput = (inputtype)callbacks[2]; + jt->sm = (I)callbacks[4]; +} + +C* _stdcall JGetLocale(J jt){return getlocale(jt);} + +A _stdcall Jga(J jt, I t, I n, I r, I*s){ + return ga(t, n, r, s); +} + +void oleoutput(J jt, I n, char* s); /* SY_WIN32 only */ + +/* jsto - display output in output window */ +void jsto(J jt,I type,C*s){C e;I ex; + if(jt->nfe) + { + C q[]="0 output_jfe_ (15!:18)0"; + q[0]+=(C)type; + jt->mtyostr=s; + e=jt->jerr; ex=jt->etxn; + jt->jerr=0; jt->etxn=0; + jt->breakignore=1;exec1(cstr(q));jt->breakignore=0; + jt->jerr=e; jt->etxn=ex; + }else{ + if(jt->smoutput) ((outputtype)(jt->smoutput))(jt,(int)type,s); +#if SY_WIN32 && !SY_WINCE + if(type & MTYOFM) oleoutput(jt,strlen(s),s); /* save output for ole */ +#endif +}} + +#if SYS&SYS_UNIX + +J JInit(void){ + J jt; + /* jtglobinit must be done once when dll is first loaded + Windows does it in dll load routine - thread safe + Unix does it here once, but this is not thread safe */ + + static J g_jt=0; + if(!g_jt) + { + g_jt=malloc(sizeof(JST)); + if(!g_jt) R 0; + memset(g_jt,0,sizeof(JST)); + if(!jtglobinit(g_jt)){free(g_jt);g_jt=0; R 0;} + } + RZ(jt=malloc(sizeof(JST))); + memset(jt,0,sizeof(JST)); + if(!jtjinit2(jt,0,0)){free(jt); R 0;}; + R jt; +} + +int JFree(J jt){return 0;} +#endif + +F1(jtbreakfnq){ + ASSERTMTV(w); + R cstr(jt->breakfn); +} + +F1(jtbreakfns){A z;I *fh,*mh; void* ad; + ASSERT(1>=AR(w),EVRANK); + ASSERT(!AN(w)||AT(w)&LIT,EVDOMAIN); + ASSERT(AN(w)breakfn,CAV(w))) R mtm; + breakclose(jt); +#if SYS&SYS_UNIX + fh=(I*)(I)open(CAV(w),O_RDWR); + ASSERT(-1!=(I)fh,EVDOMAIN); + ad=mmap(0,1,PROT_READ|PROT_WRITE,MAP_SHARED,(I)fh,0); + if(0==ad){close(fh); ASSERT(0,EVDOMAIN);} +#else + RZ(z=toutf16x(w)); + fh=CreateFileW(USAV(z),GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0); + ASSERT(INVALID_HANDLE_VALUE!=fh,EVDOMAIN); + mh=CreateFileMapping(fh,0,PAGE_READWRITE,0,1,0); + if(0==mh){CloseHandle(fh); ASSERT(0,EVDOMAIN);} + ad=MapViewOfFile(mh,FILE_MAP_WRITE,0,0,0); + if(0==ad){CloseHandle(mh); CloseHandle(fh); ASSERT(0,EVDOMAIN);} +#endif + strcpy(jt->breakfn,CAV(w)); + jt->breakfh=fh; + jt->breakmh=mh; + jt->adbreak=ad; + R mtm; +} + +int valid(C* psrc, C* psnk) +{ + while(*psrc == ' ') ++psrc; + if(!isalpha(*psrc)) return EVILNAME; + while(isalnum(*psrc) || *psrc=='_') *psnk++ = *psrc++; + while(*psrc == ' ') ++psrc; + if(*psrc) return EVILNAME; + *psnk = 0; + return 0; +} + +int _stdcall JGetM(J jt, C* name, I* jtype, I* jrank, I* jshape, I* jdata) +{ + A a; char gn[256]; + if(strlen(name) >= sizeof(gn)) return EVILNAME; + if(valid(name, gn)) return EVILNAME; + RZ(a=symbrdlock(nfs(strlen(gn),gn))); + if(FUNC&AT(a))R EVDOMAIN; + *jtype = AT(a); + *jrank = AR(a); + *jshape = (I)AS(a); + *jdata = (I)AV(a); + return 0; +} + +static int setterm(J jt, C* name, I* jtype, I* jrank, I* jshape, I* jdata) +{ + A a; + I k=1,i,n; + char gn[256]; + + switch(*jtype) + { + case LIT: + case B01: + n = sizeof(char); + break; + + case INT: + n = sizeof(I); + break; + + case FL: + n = sizeof(double); + break; + + case CMPX: + n = 2 * sizeof(double); + break; + + default: + return EVDOMAIN; + } + + // validate name + if(strlen(name) >= sizeof(gn)) return EVILNAME; + if(valid(name, gn)) return EVILNAME; + for(i=0; i<*jrank; ++i) k *= ((I*)(*jshape))[i]; + a = ga(*jtype, k, *jrank, (I*)*jshape); + if(!a) return EVWSFULL; + memcpy(AV(a), (void*)*jdata, n*k); + jset(gn, a); + return jt->jerr; +} + +int _stdcall JSetM(J jt, C* name, I* jtype, I* jrank, I* jshape, I* jdata) +{ + int er; + + PROLOG; + er = setterm(jt, name, jtype, jrank, jshape, jdata); + tpop(_ttop); + return er; +} + +#define EDCBUSY -1 +#define EDCEXE -2 + +C* esub(J jt, I ec) +{ + if(!ec) return ""; + if(ec == EDCBUSY) return "busy with previous input"; + if(ec == EDCEXE) return "not supported in EXE server"; + if(ec > NEVM || ec < 0) return "unknown error"; + return (C*)AV(*(ec+AAV(jt->evm))); +} + +int _stdcall JErrorTextM(J jt, I ec, I* p) +{ + *p = (I)esub(jt, ec); + return 0; +} diff --git a/j.c b/j.c new file mode 100644 --- /dev/null +++ b/j.c @@ -0,0 +1,61 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Global Variables */ + +#include "j.h" + +A a0j1=0; /* 0j1 */ +A ace=0; /* a: */ +A ainf=0; /* _ */ +A alp=0; /* a. */ +A aqq=0; /* '' */ +UC bit[8]={(UC)0x80, (UC)0x40, (UC)0x20, (UC)0x10, (UC)0x08, (UC)0x04, (UC)0x02, (UC)0x01}; +UC bitc[256]={0}; /* # 1 bits in each possible byte */ +C bitdisp[256*16]={0}; /* display for each possible byte */ +C breakdata=0; +A chr[256]={0}; /* scalar for each character, or 0 */ +D inf=0; /* _ */ +D infm=0; /* __ */ +A iv0=0; /* ,0 */ +A iv1=0; /* ,1 */ +D jnan=0; /* _. */ +I liln=0; /* 1 iff little endian */ +A mark=0; /* parser marker */ +C minus0[8]={0}; /* the abominable minus 0 */ +A mdot=0; /* m. */ +A mnam=0; /* m as a name */ +I msize[MLEN]={0}; /* m.c size of blocks in mfree[i] */ +A mtm=0; /* i. 0 0 */ +A mtv=0; /* i.0 */ +A ndot=0; /* n. */ +A nnam=0; /* n as a name */ +A* num=0; /* i=num[i]; see numinit() */ +A numv[19]={0}; +A one=0; /* 1 */ +D pf=0; /* performance frequency */ +A pie=0; /* o.1 */ +A pst[256]={0}; +B testb[256]={0}; /* 1 iff test block follows */ +A udot=0; /* u. */ +A unam=0; /* u as a name */ +A vdot=0; /* v. */ +A vnam=0; /* v as a name */ +C wtype[256]={0}; +A xdot=0; /* x. */ +A xnam=0; /* x as a name */ +X xone=0; /* extended integer 1 */ +X xzero=0; /* extended integer 0 */ +A ydot=0; /* y. */ +A ynam=0; /* y as a name */ +A zero=0; /* 0 */ +Q zeroQ={0,0}; /* 0r1 */ +DX zeroDX={0,0}; /* 0 */ +Z zeroZ={0,0}; /* 0j0 */ +A zpath=0; /* default locale search path */ + +/* version text up to first / is the J System ID and it */ +/* identifies the J Front Ends, J Engine, and J Library */ +/* and is used in Unix to find profile.ijs */ + +F1(jtversq){ASSERTMTV(w); R cstr("j701/2011-02-23/15:25");} diff --git a/j.h b/j.h new file mode 100644 --- /dev/null +++ b/j.h @@ -0,0 +1,345 @@ +/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ +/* License in license.txt. */ +/* */ +/* Global Definitions */ + +#include "js.h" + +#if SY_WINCE +#include "..\cesrc\cecompat.h" +#endif + +#if (SYS & SYS_PCWIN) +#define HEAPCHECK heapcheck() +#else +#define HEAPCHECK +#endif + +#if (SYS & SYS_ATARIST) +#define __NO_INLINE__ 1 +#endif + +#if (SYS & SYS_UNIX - SYS_SGI) +#include +#include +#endif + +#if (SYS & SYS_ANSILIB) +#include +#include +#define link unused_syscall_link +#define qdiv unused_netbsd_qdiv +#include +#undef link +#undef qdiv +#else +#define const /*nothing*/ /* blame rx.h */ +#endif + +#if ! SY_WINCE +#include +#include +#endif + +#include +#include + + +#if SY_64 +#define IMAX 9223372036854775807L +#define FMTI "%lli" +#define FMTI02 "%02lli" +#define FMTI04 "%04lli" +#define FMTI05 "%05lli" + +#else +#define IMAX 2147483647L +#define FMTI "%li" +#define FMTI02 "%02li" +#define FMTI04 "%04li" +#define FMTI05 "%05li" +#endif + +#define IMIN (~IMAX) /* ANSI C LONG_MIN is -LONG_MAX */ + + +#if (SYS & SYS_AMIGA) +#define XINF "\177\377\000\000\000\000\000\000" +#define XNAN "\177\361\000\000\000\000\000\000" +#endif + +#if (SYS & SYS_ARCHIMEDES) +#define XINF "\000\000\360\177\000\000\000\000" +#define XNAN "\000\000\370\377\000\000\000\000" +#endif + +#if (SYS & SYS_DEC5500) || SY_WINCE_SH +#define XINF "\000\000\000\000\000\000\360\177" +#define XNAN "\000\000\000\000\000\000\370\377" +#endif + +#if (SYS & SYS_MACINTOSH) +/* for old versions of ThinkC */ +/* #define XINF "\177\377\000\000\000\000\000\000\000\000\000\000" */ +/* #define XNAN "\377\377\100\000\100\000\000\000\000\000\000\000" */ +/* for ThinkC 7.0 or later */ +#define XINF "\177\377\177\377\000\000\000\000\000\000\000\000" +#define XNAN "\377\377\377\377\100\000\000\000\000\000\000\000" +#endif + +#if (SYS & SYS_SUN4+SYS_SUNSOL2) +#define XINF "\177\360\000\000\000\000\000\000" +#define XNAN "\177\377\377\377\377\377\377\377" +#endif + +#if (SYS & SYS_VAX) +#define XINF "\377\177\377\377\377\377\377\377" +#define XNAN "\377\177\377\377\377\377\377\376" /* not right */ +#endif + +#if (SY_WINCE_MIPS || SY_WINCE_SH) +#if WIN32_PLATFORM_PSPC +#define XINF "\000\000\000\000\000\000\360\177" +#define XNAN "\377\377\377\377\377\377\367\177" +#else +#define XINF "\000\000\000\000\000\000\360\177" +#define XNAN "\001\000\000\000\000\000\360\177" +#endif +#endif + +#if SY_WINCE_ARM +#define XINF "\000\000\000\000\000\000\360\177" +#define XNAN "\000\000\000\000\000\000\370\177" +#endif + +#if (SYS & SYS_LILENDIAN) +#ifndef XINF +#define XINF "\000\000\000\000\000\000\360\177" +#define XNAN "\000\000\000\000\000\000\370\377" +#endif +#endif + +#ifndef XINF +#define XINF "\177\360\000\000\000\000\000\000" +#define XNAN "\177\370\000\000\000\000\000\000" +#endif + + +#ifndef PI +#define PI ((D)3.14159265358979323846) +#endif +#define P2 ((D)6.28318530717958647693) +#ifndef OVERFLOW +#define OVERFLOW ((D)8.988465674311578e307) +#endif +#ifndef UNDERFLOW +#define UNDERFLOW ((D)4.450147717014403e-308) +#endif + + +#define NALP 256 /* size of alphabet */ +#define NETX 2000 /* size of error display buffer */ +#define NPP 20 /* max value for quad pp */ +#define RMAX IMAX /* max rank */ +#define NPATH 1024 /* max length for path names, */ + /* including trailing 0 byte */ + +#if SY_WINCE +#define NFCALL 100L /* wince named fn call depth */ +#define NFDEP 200L /* wince fn call depth */ +#endif +#if SYS & SYS_MACOSX +#define NFCALL 9000L /* darwin named fn call depth */ +#define NFDEP 18000L /* darwin fn call depth */ +#endif +#ifndef NFCALL +#define NFCALL 10000L /* all other named fn call depth */ +#define NFDEP 20000L /* all other fn call depth */ +#endif + +#define NTSTACK 2000L /* size of stack for temps */ + +#define IIDOT 0 /* modes for indexofsub() */ +#define IICO 1 +#define INUBSV 2 +#define INUB 3 +#define ILESS 4 +#define INUBI 5 +#define IEPS 6 +#define II0EPS 7 +#define II1EPS 8 +#define IJ0EPS 9 +#define IJ1EPS 10 +#define ISUMEPS 11 +#define IANYEPS 12 +#define IALLEPS 13 +#define IIFBEPS 14 + +#define IPHOFFSET 30 /* offset for prehashed versions */ +#define IPHIDOT 30 +#define IPHICO 31 +#define IPHLESS 34 +#define IPHEPS 36 +#define IPHI0EPS 37 +#define IPHI1EPS 38 +#define IPHJ0EPS 39 +#define IPHJ1EPS 40 +#define IPHSUMEPS 41 +#define IPHANYEPS 42 +#define IPHALLEPS 43 +#define IPHIFBEPS 44 + + +#if SY_64 && SY_WIN32 +#define jfloor jfloor1 +#else +#define jfloor floor +#endif + +#define BB 8 /* # bits in a byte */ +#if SY_64 +#define BW 64 /* # bits in a word */ +#else +#define BW 32 +#endif + +#define ABS(a) (0<=(a)?(a):-(a)) +#define ACX(a) {AC(a)=IMAX/2;} +#define ASSERT(b,e) {if(!(b)){jsignal(e); R 0;}} +#define ASSERTD(b,s) {if(!(b)){jsigd((s)); R 0;}} +#define ASSERTMTV(w) {RZ(w); ASSERT(1==AR(w),EVRANK); ASSERT(!AN(w),EVLENGTH);} +#define ASSERTN(b,e,nm) {if(!(b)){jt->curname=(nm); jsignal(e); R 0;}} +#define ASSERTSYS(b,s) {if(!(b)){jsignal(EVSYSTEM); jtwri(jt,MTYOSYS,"",(I)strlen(s),s); R 0;}} +#define ASSERTW(b,e) {if(!(b)){if((e)<=NEVM)jsignal(e); else jt->jerr=(e); R;}} +#define CALL1(f,w,fs) ((f)(jt, (w),(A)(fs))) +#define CALL2(f,a,w,fs) ((f)(jt,(a),(w),(A)(fs))) +#define DF1(f) A f(J jt, A w,A self) +#define DF2(f) A f(J jt,A a,A w,A self) +#define DO(n,stm) {I i=0,_n=(n); for(;i<_n;i++){stm}} +#define DQ(n,stm) {I i=(n)-1; for(;i>=0;--i){stm}} +#define ds(c) pst[(UC)(c)] +#define EPILOG(z) R gc(z,_ttop) +#define FDEPDEC(d) {jt->fdepi-=d;} +#define FDEPINC(d) {ASSERT(jt->fdepn>=d+jt->fdepi,EVSTACK); jt->fdepi+=d;} +#define FCONS(x) fdef(CFCONS,VERB,jtnum1,jtnum2,0L,0L,(x),0L,RMAX,RMAX,RMAX) +#define FEQ(u,v) (ABS((u)-(v))<=jt->fuzz*MAX(ABS(u),ABS(v))) +#define F1(f) A f(J jt, A w) +#define F2(f) A f(J jt,A a,A w) +#define F1RANK(m,f,self) {RZ( w); if(madbreak&&!jt->breakignore){jsignal(EVATTN); R 0;}} +#define JBREAK0 {if(2<=*jt->adbreak&&!jt->breakignore){jsignal(EVBREAK); R 0;}} +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MC memcpy +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MLEN (SY_64?63:31) +#define NAN0 (_clearfp()) +#define NAN1 {if(_SW_INVALID&_clearfp()){jsignal(EVNAN); R 0;}} +#define NAN1V {if(_SW_INVALID&_clearfp()){jsignal(EVNAN); R ;}} +#define PROLOG I _ttop=jt->tbase+jt->ttop +#define R return +#define RE(exp) {if((exp),jt->jerr)R 0;} +#define RER {if(er){jt->jerr=er; R;}} +#define RESETERR {jt->etxn=jt->jerr=0;} +#define RNE(exp) {R jt->jerr?0:(exp);} +#define RZ(exp) {if(!(exp))R 0;} +#define SBSV(x) (jt->sbsv+(I)(x)) +#define SBUV(x) (jt->sbuv+(I)(x)) +#define SGN(a) ((0<(a))-(0>(a))) +#define SMAX 65535 +#define SMIN (-65536) +#define SZA ((I)sizeof(A)) +#define SZD ((I)sizeof(D)) +#define SZI ((I)sizeof(I)) +#define VAL1 '\001' +#define VAL2 '\002' + + +#if SYS & SYS_LILENDIAN +#define B0000 0x00000000 +#define B0001 0x01000000 +#define B0010 0x00010000 +#define B0011 0x01010000 +#define B0100 0x00000100 +#define B0101 0x01000100 +#define B0110 0x00010100 +#define B0111 0x01010100 +#define B1000 0x00000001 +#define B1001 0x01000001 +#define B1010 0x00010001 +#define B1011 0x01010001 +#define B1100 0x00000101 +#define B1101 0x01000101 +#define B1110 0x00010101 +#define B1111 0x01010101 +#define BS00 0x0000 +#define BS01 0x0100 +#define BS10 0x0001 +#define BS11 0x0101 +#else +#define B0000 0x00000000 +#define B0001 0x00000001 +#define B0010 0x00000100 +#define B0011 0x00000101 +#define B0100 0x00010000 +#define B0101 0x00010001 +#define B0110 0x00010100 +#define B0111 0x00010101 +#define B1000 0x01000000 +#define B1001 0x01000001 +#define B1010 0x01000100 +#define B1011 0x01000101 +#define B1100 0x01010000 +#define B1101 0x01010001 +#define B1110 0x01010100 +#define B1111 0x01010101 +#define BS00 0x0000 +#define BS01 0x0001 +#define BS10 0x0100 +#define BS11 0x0101 +#endif + +#include "ja.h" +#include "jc.h" +#include "jtype.h" +#include "jt.h" +#include "jlib.h" +#include "je.h" +#include "jerr.h" +#include "va.h" +#include "vq.h" +#include "vx.h" +#include "vz.h" +#include "vdx.h" +#include "m.h" +#include "a.h" +#include "s.h" + +// JPFX("here we are\n") +// JPF("size is %i\n", v) +// JPF("size and extra: %i %i\n", (v,x)) +#define JPFX(s) {char b[1000]; sprintf(b, s); jsto(gjt,MTYOFM,b);} +#define JPF(s,v) {char b[1000]; sprintf(b, s, v); jsto(gjt,MTYOFM,b);} +extern J gjt; // global for JPF (procs without jt) + +#if SY_WINCE_MIPS +/* strchr fails for CE MIPS - neg chars - spellit fails in ws.c for f=.+. */ +#define strchr(a,b) strchr(a, (UC)b) +#endif + +#if SYS & SYS_UNIX +#include +#define _isnan isnan +#define _SW_INVALID FE_INVALID + +static inline UINT _clearfp(void){int r=fetestexcept(FE_ALL_EXCEPT); + feclearexcept(FE_ALL_EXCEPT); return r; +} +#endif diff --git a/j/addons/data/jmf/jmf.ijs b/j/addons/data/jmf/jmf.ijs new file mode 100644 --- /dev/null +++ b/j/addons/data/jmf/jmf.ijs @@ -0,0 +1,455 @@ +cocurrent 'jmf' + +jsystemdefs 'hostdefs' + +coinsert 'jdefs' + + +doc=: 0 : 0 + + map name;filename [;sharename;readonly] + - map jmf file (self-describing) + + opt map name;filename [;sharename;readonly] + - map data file (opt is description) + + where: opt=type [;trailing_shape] + + types are defined in dll.ijs as: + JB01 boolean + JCHAR character + JINT integer + JFL floating point + JCMPX complex + + trailing_shape= }. shape (default '') + + [force] unmap name + 0 ok + 1 not mapped + 2 refs + + unmapall'' - unmap all + + createjmf filename;msize - creates jmf file as empty vector + (self-describing) + + additem name - add an item to a name + + share name;sharedname - share 'sharedname' as name + + showle name - show locale entry and header for name + + showmap'' - show all maps + +) +SZI=: IF64{4 8 +'HADK HADFLAG HADM HADT HADC HADN HADR HADS'=: SZI*i.8 +HADCN=: <.HADC%SZI + +HSN=: 7+64 +HS=: SZI*HSN +AFRO=: 1 +AFNJA=: 2 +NULLPTR=: <0 +3 : 0'' +if. IFUNIX do. + lib=. >(UNAME-:'Darwin'){'libc.so.6 ';'libc.dylib ' + api=. 1 : ('(''',lib,''',x) & cd') + c_isatty=: ' isatty i i' api + c_open=: 'open i *c i i' api + c_close=: 'close i i' api + c_read=: 'read x i * x' api + c_write=: 'write x i * x' api + c_lseek=: 'lseek x i x i' api + c_mmap=: 'mmap * * x i i i x' api + c_munmap=: 'munmap i * x' api + if. UNAME -: 'Darwin' do. + c_mmap=: }:@:('mmap * * i i i i i i' api)@:(}: , (<0)"_ , {:) + if. ({.a.)={. 1&(3!:4) 1 do. + c_lseek=: (0 1 3 4&{)@:('lseek i i i i i' api)@:(0&{ , (<0)"_ , 1&{ , 2&{) + end. + end. +else. + CREATE_ALWAYS=: 2 + CREATE_NEW=: 1 + FALSE=: 0 + FILE_BEGIN=: 0 + FILE_END=: 2 + FILE_MAP_READ=: 4 + FILE_MAP_WRITE=: 2 + FILE_SHARE_READ=: 1 + FILE_SHARE_WRITE=: 2 + GENERIC_READ=: _2147483648 + GENERIC_WRITE=: 1073741824 + OPEN_ALWAYS=: 4 + OPEN_EXISTING=: 3 + PAGE_READONLY=: 2 + PAGE_READWRITE=: 4 + TRUNCATE_EXISTING=: 5 + + j=. (GENERIC_READ+GENERIC_WRITE),PAGE_READWRITE,FILE_MAP_WRITE + RW=: j,:GENERIC_READ,PAGE_READONLY,FILE_MAP_READ + + CloseHandleR=: 'kernel32 CloseHandle > i x'&(15!:0) + CreateFileMappingR=: 'kernel32 CreateFileMappingA > x x * i i i *c'&(15!:0) + CreateFileR=: 'kernel32 CreateFileA > x *c i i * i i x'&(15!:0) + GetLastError=: 'kernel32 GetLastError > i'&(15!:0) + FlushViewOfFileR=: 'kernel32 FlushViewOfFile > i * x'&(15!:0) + MapViewOfFileR=: >@{.@('kernel32 MapViewOfFile * x i i i x'&(15!:0)) + OpenFileMappingR=: 'kernel32 OpenFileMappingA > x i i *c'&(15!:0) + SetEndOfFile=: 'kernel32 SetEndOfFile > i x'&(15!:0) + UnmapViewOfFileR=: 'kernel32 UnmapViewOfFile > i *'&(15!:0) + WriteFile=: 'kernel32 WriteFile i x * i *i *'&(15!:0) + if. IF64 do. + GetFileSizeR=: 2 >@{ 'kernel32 GetFileSizeEx i x *x' 15!:0 ;&(,2) + SetFilePointerR=: 'kernel32 SetFilePointerEx > i x x *x i'&(15!:0) + else. + GetFileSizeR=: 'kernel32 GetFileSize > i x *i' 15!:0 ;&( i x i *i i'&(15!:0) + end. +end. + +if. _1 = 4!:0<'mappings' do. + mappings=: i.0 8 +end. +empty'' +) +symget=: 15!:6 +symset=: 15!:7 +allochdr=: 3 : 'r[2 memw (r=.15!:8 y),HADC,1,JINT' + +freehdr=: 15!:9 +msize=: 3 : 'memr y,HADM,1,JINT' +refcount=: 3 : 'memr y,HADC,1,JINT' +MAXINTU=: 2 ^ IF64{32 64x +MAXINTS=: <: 2 ^ IF64{31 63x +ufs=: + MAXINTU * 0 > ] +sfu=: _1 x: ] - MAXINTU * MAXINTS < ] +findkey=: 4 : 'I. (:HS do. + d=. memr had,0 4,JINT + *./((HS,ts-HS)=0 2{d),1 2 4 8 16 32 e.~ 3{d +else. 0 end. +) +ERROR_NOT_ENOUGH_MEMORY=: 8 +j=. <;._2 (0 : 0) +1 ERROR_INVALID_FUNCTION +2 ERROR_FILE_NOT_FOUND +3 ERROR_PATH_NOT_FOUND +4 ERROR_TOO_MANY_OPEN_FILES +5 ERROR_ACCESS_DENIED +6 ERROR_INVALID_HANDLE +7 ERROR_ARENA_TRASHED +8 ERROR_NOT_ENOUGH_MEMORY +9 ERROR_INVALID_BLOCK +10 ERROR_BAD_ENVIRONMENT +11 ERROR_BAD_FORMAT +12 ERROR_INVALID_ACCESS +13 ERROR_INVALID_DATA +14 ERROR_OUTOFMEMORY +15 ERROR_INVALID_DRIVE +16 ERROR_CURRENT_DIRECTORY +17 ERROR_NOT_SAME_DEVICE +18 ERROR_NO_MORE_FILES +19 ERROR_WRITE_PROTECT +20 ERROR_BAD_UNIT +21 ERROR_NOT_READY +22 ERROR_BAD_COMMAND +23 ERROR_CRC +24 ERROR_BAD_LENGTH +25 ERROR_SEEK +26 ERROR_NOT_DOS_DISK +27 ERROR_SECTOR_NOT_FOUND +28 ERROR_OUT_OF_PAPER +29 ERROR_WRITE_FAULT +30 ERROR_READ_FAULT +31 ERROR_GEN_FAILURE +32 ERROR_SHARING_VIOLATION +33 ERROR_LOCK_VIOLATION +34 ERROR_WRONG_DISK +) + +WINERRNOS=: 0 ". 2 {.&> j +WINERRMSG=: 3 }.each j +additem=: 3 : 0 +sad=. symget x else. t=. x end. +'type tshape hsize'=. 3 {. t, a: + +'trailing shape may not be zero' assert -. 0 e. tshape + +'name fn sn ro'=. 4{.y,(#y)}.'';'';'';0 +sn=. '/' (('\'=sn)#i.#sn)} sn +name=. fullname name +c=. #mappings + +'name already mapped'assert c=({."1 mappings)i.0 { c_open fn;(ro{O_RDWR,O_RDONLY);0 + 'bad file name/access' assert fh~:_1 + mh=. ts + fad=. >0{ c_mmap (<0);ts;(OR ro}. PROT_WRITE, PROT_READ);MAP_SHARED;fh;0 + if. fad e. 0 _1 do. + 'bad view' assert 0[free fh,mh,0 + end. +else. + 'fa ma va'=. ro{RW + fh=. CreateFileR (fn,{.a.);fa;(FILE_SHARE_READ+FILE_SHARE_WRITE);NULLPTR;OPEN_EXISTING;0;0 + 'bad file name/access'assert fh~:_1 + ts=. GetFileSizeR fh + mh=: CreateFileMappingR fh;NULLPTR;ma;0;0;(0=#sn){(sn,{.a.);unmap each 0{"1 mappings' +memshare=: 3 : 0 +bNo_Inherit_Handle=. FALSE +lpShareName=. y,{.a. +mh=. OpenFileMappingR (FILE_MAP_READ+FILE_MAP_WRITE); bNo_Inherit_Handle; lpShareName +('Unable to map ',y) assert mh~:0 + +addr=. MapViewOfFileR mh; (FILE_MAP_READ+FILE_MAP_WRITE); 0; 0; 0 +if. addr=0 do. 'MapViewOfFile failed' assert 0[CloseHandleR mh end. +".(_1=4!:0<'mapTable')#'mapTable=:i.0,3' +mapTable=: mapTable, y; mh; addr +addr +) +memshareclose=: 3 : 0 +r=. y findkey mapTable +'Unknown share name' assert 0~:$r +'mh addr'=. {:( 0 +UnmapViewOfFileR <(systype-5){(2!:5'HOME');2!:5'USERPROFILE' + +userx=. '\j',('64-'#~16={:$3!:3[2),'701-user' +user=. home,userx +break=. user,'/break' +snap=. user,'/snap' +temp=. user,'/temp' +config=. user,'/config' +ids=. ;:'addons bin break config home install snap system tools temp user' + +0!:0 :: ] ids + +md=. 3 : 0 NB. recursive makedir +a=. jpathsep y,'/' +if. -.#1!:0 }:a do. + for_n. I. a='/' do. 1!:5 :: [ boxopen y +else. + if. Tags do. parsetags"0 jpath&.> boxopen Tags end. +end. +initdone=: 1 +EMPTY +) + +NB. ========================================================= +NB. parsetags parse tags as segmented string for memory efficiency +parsetags=: 3 : 0 +y=. '/' (I.'\'=y)}y=. >y +a=. freads y +if. 4>#a do. EMPTY return. end. +tag=. ; ,&({.a.)&.>@{.@(<;._2)@(,&TAB);._2 a +if. 0=#tag do. EMPTY return. end. +if. 0=#tagtags do. tagtags=: tagfiles=: taglines=: ,{.a. end. +tagtags=: tagtags, tag +if. absolutepath *. y-.@-:pf=. ({.~ i:&'/')y do. + pf=. pf,'/' + tagfiles=: tagfiles, b=. jpathsep ; ,&({.a.)@(pf&,)&.>@(1&{)@(<;._2)@(,&TAB);._2 a +else. + tagfiles=: tagfiles, b=. jpathsep ; ,&({.a.)&.>@(1&{)@(<;._2)@(,&TAB);._2 a +end. +taglines=: taglines, ; <@(,&({.a.))@parseline@;@:(2&}.)@(<;.2)@(,&TAB);._2 a +EMPTY +) + +NB. ========================================================= +parseline=: 3 : 0 +if. '/' = {.y do. + if. #r=. I. ('/;"',TAB) E. y do. + z=. }.({.r){.y + else. + z=. ,'1' + end. +elseif. '0123456789' e.~ {.y do. + if. #r=. I. (';"',TAB) E. y do. + z=. ({.r){.y + else. + z=. ,'1' + end. +elseif. do. + z=. ,'1' +end. +z +) + +NB. find tags + +NB. ========================================================= +NB. y string or boxed list of tags +NB. x (default 0) if x=1 then include partial matches +tagtag=: 0&$: : (4 : 0) +if. 0=#y=. boxxopen y do. 0$0 return. end. +if. 0=initdone do. loadtags'' end. +if. 0=#tagtags do. 0$0 return. end. +res=. 0$0 +for_t. y do. + if. 1 -.@e. r=. (({.a.),(>t),(0=x)#{.a.) E. tagtags do. continue. end. + res=. res, (I.tagtags={.a.) i. I.r +end. +~.res +) + +NB. tag name from index +tagtagname=: 3 : 0 +'a b'=. (y+i.2){r=. I.tagtags={.a. +(}.a+i.b-a){tagtags +) + +NB. tag file from index +tagfile=: 3 : 0 +'a b'=. (y+i.2){r=. I.tagfiles={.a. +if. 1 e. msk=. '/./' E. r=. (}.a+i.b-a){tagfiles do. + r=. r #~ -. +./ 0 _1 |."0 1 msk NB. simplify /./ to / +end. +r +) + +NB. tag line from index +tagline=: 3 : 0 +'a b'=. (y+i.2){r=. I.taglines={.a. +(}.a+i.b-a){taglines +) + +NB. tagopen open in external editor +NB. x (default 0) index of occurrence as in tagselect +NB. ========================================================= +tagopen=: 0&$: : (4 : 0) +if. 0=#n=. tagtag y do. EMPTY return. end. +file=. tagfile idx=. x{n +if. -.fexist line (>:2*i.#file)}2#(<"1 ":,.i.#file) ,&.> (<' ') ,&.> file +) + +NB. tagcp tag completion +NB. return boxed list of partial matches +NB. ========================================================= +tagcp=: 3 : 0 +if. 0=#n=. 1 tagtag y do. 0$<'' return. end. +/:~ ~. <@tagtagname"0 n +) + +NB. user friendly helper verbs + +NB. jump to tag directly for only one candidate, +NB. otherwise display all candidates and wait for user input +NB. x (default 0) if x=1 then include partial matches +NB. ========================================================= +ta=: 0&$: : (4 : 0) +if. x do. y=. tagcp y end. +if. #a=. tagselect y do. + if. 3>#a do. + tagopen ::0: y + else. + smoutput a + smoutput 'Type number and (empty cancels):' + if. '' -.@-: b=. 0". 1!:1]1 do. + ({.b) tagopen ::0: y + end. + end. +end. +EMPTY +) + +NB. do string search +NB. ========================================================= +NB. return 0-base line number or 0$0 if nothing done +tagss=: 4 : 0 +what=. >y [ f=. boxopen x +ind=. 0$0 +if. 0=#what do. ind return. end. +if. '0123456789' e. ~{.what do. <: 0". what return. end. NB. line number + +NB. flag to enable UTF-8 support +rxflag=. RX_OPTIONS_UTF8_jregex_ +RX_OPTIONS_UTF8_jregex_=: 1 + +if. 0=tagss_init what do. ind [ RX_OPTIONS_UTF8_jregex_=: rxflag return. end. + +termLF=. , ((0 < #) # LF -. {:) +tagmatches=. {.@{."2 @ rxmatches_jregex_ +groupndx=. [: <: I. + e.~ + +txt=. freads f +if. -. txt -: _1 do. + ndx=. TAGCOMP tagmatches txt + if. #ndx do. + ind=. ~. (0,}:I. txt = LF) groupndx ndx + end. +end. +rxfree_jregex_ :: 0: TAGCOMP +ind [ RX_OPTIONS_UTF8_jregex_=: rxflag +) + +NB. ========================================================= +tagss_init=: 3 : 0 +NB. no magic except anchors, but \ is \\ in tags file for vi compatibility +anchor1=. '^'={.y [ anchor2=. '$'={:y +y=. ('\/';'/') stringreplace ('\\';'\') stringreplace (anchor1#'^'), '\Q', ((-anchor2)}.anchor1}.y), '\E', (anchor2#'$') +TAGCOMP=: rxcomp_jregex_ :: _1: y +if. TAGCOMP -: _1 do. + rxfree_jregex_ :: 0: TAGCOMP + 0 +else. + 1 +end. +) diff --git a/j/system/main/regex.ijs b/j/system/main/regex.ijs new file mode 100644 --- /dev/null +++ b/j/system/main/regex.ijs @@ -0,0 +1,302 @@ +NB. Regular expression pattern matching +NB. +NB. PCRE: Perl-compatible regular expression library +NB. with POSIX interface +NB. +NB. ========================================================= +NB. main definitions: +NB. rxmatch single match +NB. rxmatches all matches +NB. +NB. rxcomp compile pattern +NB. rxfree free pattern handles +NB. rxhandles list pattern handles +NB. rxinfo info on pattern handles +NB. +NB. regex utilities: +NB. rxeq -: +NB. rxin e. +NB. rxindex i. +NB. rxE E. +NB. rxfirst {.@{ (first match) +NB. rxall { (all matches) +NB. rxrplc search and replace +NB. rxapply apply verb to pattern +NB. +NB. rxerror last regex error message +NB. +NB. other utilities: +NB. rxcut cut string into nomatch/match list +NB. rxfrom matches from string +NB. rxmerge replace matches in string +NB. +NB. ========================================================= +NB. Form: +NB. here: pat = pattern, or pattern handle +NB. phnd = pattern handle +NB. patndx = pattern;index or phnd;index +NB. str = character string +NB. bstr = boxed list of str +NB. mat = result of regex search +NB. nsub = #subexpressions in pattern +NB. +NB. mat=. pat or patndx rxmatch str +NB. mat=. pat or patndx rxmatches str +NB. +NB. phnd=. rxcomp pat +NB. empty=. rxfree phnd +NB. phnds=. rxhandles '' +NB. 'nsub pat'=. rxinfo phnd +NB. +NB. boolean=. pat rxeq str +NB. index=. pat rxindex str +NB. mask=. pat rxE str +NB. bstr=. pat rxfirst str +NB. bstr=. pat rxall str +NB. str=. (patndx;new) rxrplc str +NB. str=. patndx (verb rxapply) str +NB. +NB. errormsg=. rxerror '' +NB. +NB. bstr mat rxcut str +NB. bstr=. mat rxfrom str +NB. str=. new (mat rxmerge) str + +NB. ========================================================= +NB. following defined in z: +NB.*rxmatch v single match +NB.*rxmatches v all matches +NB.*rxcomp v compile pattern +NB.*rxfree v free pattern handles +NB.*rxhandles v list pattern handles +NB.*rxinfo v info on pattern handles +NB.*rxeq v regex equivalent of -: +NB.*rxin v regex equivalent of e. +NB.*rxindex v regex equivalent of i. +NB.*rxE v regex equivalent of E. +NB.*rxfirst v regex equivalent of {.@{ (first match) +NB.*rxall v regex equivalent of { (all matches) +NB.*rxrplc v search and replace +NB.*rxapply v apply verb to pattern +NB.*rxerror v last regex error message +NB.*rxcut v cut string into nomatch/match list +NB.*rxfrom v matches from string +NB.*rxmerge v replace matches in string +NB.*rxutf8 v set UTF-8 support 1=on(default), 0=off + +coclass <'jregex' + +NB. ========================================================= +NB. flag to enable UTF-8 support +RX_OPTIONS_UTF8=: 1 + +Rxnna=: '(^|[^[:alnum:]_])' +Rxnnz=: '($|[^[:alnum:]_.:])' +Rxass=: '[[:space:]]*=[.:]' +NB. defs + +NB. ========================================================= +NB. rxdll is in bin or tools/regex +3 : 0'' +select. UNAME +case. 'Win' do. t=. 'jpcre.dll' +case. 'Darwin' do. t=. 'libjpcre.dylib' +case. do. t=. 'libjpcre.so' +end. +f=. BINPATH,'/',t +if. 0 = 1!:4 :: 0: 0{x else. ph=. x end. +if. cx=. 2 = 3!:0 ph do. hx=. rxcomp ph +else. rxlastxrp=: > 1{((hx=. ph) - 1) ({"1) rxpatterns end. +nsub=. rxnsub rxlastxrp +rxlastrc=: >0{rv=. jregexec rxlastxrp ; (,y) ; rxms ; ((2*rxms)$_1 0) ; 0 +if. cx do. rxfree hx end. +m=. (nsub,2)$>4{rv +t=. (0{"1 m) +m=. t,.-~/"1 m +m=. _1 0 ((t=_1)#i.#t)} m +if. lb do. (>1{x){ m else. m end. +) + +NB. ========================================================= +NB. rxmatches +rxmatches=: 4 : 0 +if. lb=. 32 = 3!:0 x do. + ph=. >0{x else. ph=. x end. +if. cx=. 2 = 3!:0 ph do. + hx=. rxcomp ph else. NB. rxcomp sets rxlastxrp + rxlastxrp=: > 1{((hx=. ph) - 1) ({"1) rxpatterns end. +nsub=. rxnsub rxlastxrp +o=. 0 +rxm=. (0, nsub, 2)$0 +while. 1 do. + m=. hx rxmatch o}.y + if. 0 e. $m do. break. end. + if. _1 = 0{0{m do. break. end. + m=. m+ ($m)$o,0 + rxm=. rxm , m +NB. Advance the offset o beyond this match. +NB. The match length can be zero (with the *? operators), +NB. so take special care to advance at least to the next +NB. position. If that reaches beyond the end, exit the loop. + o=. (>:o) >. +/0{m + if. o >: #y do. break. end. +end. +if. cx do. rxfree hx end. +if. lb do. (>1{x){"2 rxm else. rxm end. +) + +NB. ========================================================= +NB. rxcomp +NB. +NB. options rxcomp pattern +rxcomp=: 3 : 0 +'rxlastrc rxlastxrp'=: 2 {. jregcomp (rxregxsz$2-2); (,y); 2 + RX_OPTIONS_UTF8*16b40 +if. rxlastrc do. (rxerror'') 13!:8 [12 end. +if. ({:$rxpatterns) = hx=. (<_1) i.~ 0 { rxpatterns do. + rxpatterns=: rxpatterns ,. (rxmp$<_1),(rxmp$: 1&{ NB. Number of main+sub-expressions from Perl regex_t + +NB. ========================================================= +NB. rxerror +rxerror=: 3 : 0 +r=. >3{jregerror rxlastrc;rxlastxrp;(80#' ');80 +({.~ i.&(0{a.)) r +) + +NB. ========================================================= +rxfree=: 3 : 0 +hx=. ,y - 1 +while. 0<#hx do. + ix=. 0{hx + jregfree 1{ix ({"_1) rxpatterns + rxpatterns=: ((<_1),(0{rxpatterns +(h~:_1)#h +) + +NB. ========================================================= +NB. rxinfo +rxinfo=: 3 : 0 +i=. (y-1){"1 rxpatterns +|:(<"_1 rxnsub >1{i) ,: 2{i +) + +NB. ========================================================= +NB. rxfrom=: <@({~ (+ i.)/)"1~ +rxfrom=: ,."1@[ <;.0 ] +rxeq=: {.@rxmatch -: 0: , #@] +rxin=: _1: ~: {.@{.@rxmatch +rxindex=: #@] [^:(<&0@]) {.@{.@rxmatch +rxE=: i.@#@] e. {.@{."2 @ rxmatches +rxfirst=: {.@rxmatch >@rxfrom ] +rxall=: {."2@rxmatches rxfrom ] + +NB. ========================================================= +rxapply=: 1 : 0 +: +if. L. x do. 'pat ndx'=. x else. pat=. x [ ndx=. ,0 end. +if. 1 ~: #$ ndx do. 13!:8[3 end. +mat=. ({.ndx) {"2 pat rxmatches y +r=. u&.> mat rxfrom y +r mat rxmerge y +) + +NB. ========================================================= +rxcut=: 4 : 0 +if. 0 e. #x do. {.x +new=. {:x +if. L. pat do. 'pat ndx'=. pat else. ndx=. ,0 end. +if. 1 ~: #$ ndx do. 13!:8[3 end. +mat=. ({.ndx) {"2 pat rxmatches y +new mat rxmerge y +) + +NB. ========================================================= +NB. set UTF-8 support on/off +NB. result is previous setting +rxutf8=: 3 : 0 +(RX_OPTIONS_UTF8=: y) ] RX_OPTIONS_UTF8 +) +NB. zdefs + +NB. ========================================================= +NB. define z locale names: +nms=. 0 : 0 +rxmatch rxmatches rxcomp rxfree rxhandles rxinfo rxeq +rxin rxindex rxE rxfirst rxall rxrplc rxapply rxerror +rxcut rxfrom rxmerge rxutf8 +) + +nms=. (nms e.' ',LF) <;._2 nms +". > nms ,each (<'_z_=:') ,each nms ,each <'_jregex_' diff --git a/j/system/main/socket.ijs b/j/system/main/socket.ijs new file mode 100644 --- /dev/null +++ b/j/system/main/socket.ijs @@ -0,0 +1,383 @@ +coclass <'jsocket' +coinsert 'jsocket jdefs' + +jsystemdefs 'hostdefs' +jsystemdefs 'netdefs' +3 : 0'' +assert. INADDR_ANY=0 +assert. sockaddr_sz=16 +if. IFUNIX do. + assert. fds_bits_off=0 +end. +) +3 : 0'' +select. UNAME +case. 'Win' do. + c=. >IFWINCE{'wsock32';'winsock' + ccdm=: 1 : ('(''"',c,,'" '',x)&(15!:0)') + ncdm=: ccdm + scdm=: ccdm + wcdm=: ccdm + LIB=: '' + closesocketJ=: 'closesocket i i' scdm + ioctlsocketJ=: 'ioctlsocket i i i *i' scdm +case. 'Linux' do. + c=. 'libc.so.6' + ccdm=: 1 : ('(''"',c,'" '',x)&(15!:0)') + ncdm=: ccdm + scdm=: ccdm + wcdm=: 1 : ']' + LIB=: c + closesocketJ=: 'close i i' scdm + ioctlsocketJ=: 'ioctl i i i *i' scdm +case. 'Darwin' do. + c=. 'libc.dylib' + ccdm=: 1 : ('(''"',c,'" '',x)&(15!:0)') + ncdm=: ccdm + scdm=: ccdm + wcdm=: 1 : ']' + LIB=: c + closesocketJ=: 'close i i' scdm + ioctlsocketJ=: 'ioctl i i i *i' scdm +case. 'SunOS' do. + c=. find_dll 'c' + ccdm=: 1 : ('(''"',c,'" '',x)&(15!:0)') + n=. find_dll 'nsl' + ncdm=: 1 : ('(''"',n,'" '',x)&(15!:0)') + s=. find_dll 'socket' + scdm=: 1 : ('(''"',s,'" '',x)&(15!:0)') + wcdm=: 1 : ']' + LIB=: c + closesocketJ=: 'close i i' scdm + ioctlsocketJ=: 'ioctl i i i *i' scdm +end. +empty'' +) +gethostbyaddrJ=: 'gethostbyaddr * * i i' ncdm +gethostbynameJ=: 'gethostbyname * *c' ncdm +gethostnameJ=: 'gethostname i *c i' ncdm +inet_addrJ=: 'inet_addr i *c' ncdm +inet_ntoaJ=: 'inet_ntoa i i' ncdm +acceptJ=: 'accept i i * *i' scdm +acceptNullJ=: 'acceptNull i i *c *c' scdm +bindJ=: 'bind i i * i' scdm +connectJ=: 'connect i i * i' scdm +FD_ISSETJ=: 'FD_ISSET i i ' scdm +getpeernameJ=: 'getpeername i i * *i' scdm +getprotobynameJ=: 'getprotobyname i *c' scdm +getprotobynumberJ=: 'getprotobynumber i i' scdm +getservbynameJ=: 'getservbyname i i i' scdm +getservbyportJ=: 'getservbyport i i i' scdm +getsocknameJ=: 'getsockname i i * *i' scdm +getsockoptJ=: 'getsockopt i i i i * *i' scdm +htonlJ=: 'htonl i i' scdm +htonsJ=: 'htons s s' scdm +listenJ=: 'listen i i i' scdm +ntohlJ=: 'ntohl i i' scdm +ntohsJ=: 'ntohs s s' scdm +recvJ=: 'recv i i * i i' scdm +recvfromJ=: 'recvfrom i i *c i i * *i' scdm +selectJ=: 'select i i * * * *' ccdm +sendJ=: 'send i i *c i i' scdm +sendtoJ=: 'sendto i i *c i i * i' scdm +setsockoptJ=: 'setsockopt i i i i * i' scdm +shutdownJ=: 'shutdown i i i' scdm +socketJ=: 'socket i i i i' scdm + +WSAAsyncGetHostByAddrJ=: 'WSAAsyncGetHostByAddr i i i i i i i i' wcdm +WSAAsyncGetHostByNameJ=: 'WSAAsyncGetHostByName i i i *c i i' wcdm +WSAAsyncGetProtoByNameJ=: 'WSAAsyncGetProtoByName i i i *c i i' wcdm +WSAAsyncGetProtoByNumberJ=: 'WSAAsyncGetProtoByNumber i i i i i i' wcdm +WSAAsyncGetServByNameJ=: 'WSAAsyncGetServByName i i i *c *c i i' wcdm +WSAAsyncGetServByPortJ=: 'WSAAsyncGetServByPort i i i i *c i i' wcdm +WSAAsyncSelectJ=: 'WSAAsyncSelect i i i i i' wcdm +WSACancelAsyncRequestJ=: 'WSACancelAsyncRequest i i' wcdm +WSACancelBlockingCallJ=: 'WSACancelBlockingCall i ' wcdm +WSACleanupJ=: 'WSACleanup i ' wcdm +WSAGetLastErrorJ=: 'WSAGetLastError i ' wcdm +WSAIsBlockingJ=: 'WSAIsBlocking i ' wcdm +WSASetBlockingHookJ=: 'WSASetBlockingHook i i' wcdm +WSASetLastErrorJ=: 'WSASetLastError i i' wcdm +WSAStartupJ=: 'WSAStartup i i *' wcdm +WSAStringToAddressJ=: 'WSAStringToAddress i c i i i i' wcdm +WSAUnhookBlockingHookJ=: 'WSAUnhookBlockingHook i ' wcdm +x_WSAFDIsSetJ=: 'x_WSAFDIsSet i i i' wcdm + +sderror=: 3 : 0 +'num msg'=. SDERRORS +> (num i. >{.y) { msg, <'unknown error' +) +j=. <;._2 (0 : 0) + 0 no error +10004 EINTR +10009 EBADF +10011 EAGAIN +10013 EACCES +10014 EFAULT +10022 EINVAL +10024 EMFILE +10035 EWOULDBLOCK +10036 EINPROGRESS +10037 EALREADY +10038 ENOTSOCK +10039 EDESTADDRREQ +10040 EMSGSIZE +10041 EPROTOTYPE +10042 ENOPROTOOPT +10043 EPROTONOSUPPORT +10044 ESOCKTNOSUPPORT +10045 EOPNOTSUPP +10046 EPFNOSUPPORT +10047 EAFNOSUPPORT +10048 EADDRINUSE +10049 EADDRNOTAVAIL +10050 ENETDOWN +10051 ENETUNREACH +10052 ENETRESET +10053 ECONNABORTED +10054 ECONNRESET +10055 ENOBUFS +10056 EISCONN +10057 ENOTCONN +10058 ESHUTDOWN +10059 ETOOMANYREFS +10060 ETIMEDOUT +10061 ECONNREFUSED +10062 ELOOP +10063 ENAMETOOLONG +10064 EHOSTDOWN +10065 EHOSTUNREACH +10066 ENOTEMPTY +10067 EPROCLIM +10068 EUSERS +10069 EDQUOT +10070 ESTALE +10071 EREMOTE +10091 SYSNOTREADY +10092 VERNOTSUPPORTED +10093 NOTINITIALISED +10098 EADDRINUSE +10101 EDISCON +11001 HOST_NOT_FOUND +11002 TRY_AGAIN +11003 NO_RECOVERY +11004 NO_DATA +) + +SDERRORS=: (0 ". 5 {. &> j) ; < 6 }.each j +SDERRORS=: ((10000*IFUNIX) | >{.SDERRORS);{:SDERRORS + +tostring=: 3 : 0 +}: ;'.',~each ":each a.i.y +) + +data2string=: 3 : 0 +tostring 4{.4}.2{::y +) + +namesub=: 3 : 0 +if. 0~:res y do. (sdsockerror'');0;'';0 return. end. +0;AF_INET;(data2string y);256#.a.i.2 3{2{::y +) + +flip=: 'a'={.2 ic a.i.'a' +bigendian=: |.^:flip +hns=: 3 : 'a.{~256 256#:y' +hs=: 3 : 'bigendian a.{~256 256#:y' +res=: >@:{. + +sockaddr_in=: 3 : 0 +'s fam host port'=. y +assert. fam=AF_INET +if. 0=#host do. host=. '0.0.0.0' end. +(hs AF_INET),(hns port),(afroms host),8#{.a. +) + +sockaddr_split=: 3 : 0 +'fam port host'=. 1 0 1 0 1 0 0 0 <;.1 (8){.y +assert. AF_INET = 256 256 #. a. i. bigendian fam +port=. 256 256 #. a. i. port +host=. }. , sfroma "0 host +host;port +) + +sfroma=: 3 : 0 +'.',": a. i. y +) +afroms=: 3 : 0 +a.{~4{.".each '.' cutopen y +) +rc0=: 3 : 0 +if. 0=>{.y do. 0 else. sdsockerror'' end. +) + +sdsockaddress=: 3 : 0"0 +r=. getsocknameJ y;(sockaddr_in_sz#{.a.);,sockaddr_in_sz +(rc0 r);data2string r +) +sdsend=: 4 : 0"1 +r=. >{.sendJ (>0{y);x;(#x);>1{y +if. _1=r do. 0;~sdsockerror'' else. 0;r end. +) +sdsendto=: 4 : 0"1 +if. 3 = #y do. + 's flags saddr'=. y + r=. >{.sendtoJ s;x;(#x);flags;saddr;sockaddr_in_sz +else. + 's flags family address port'=. y + r=. >{.sendtoJ s;x;(#x);flags;(sockaddr_in 0 2 3 4{y);sockaddr_in_sz +end. +if. _1=r do. 0;~sdsockerror'' else. 0;r end. +) + +sdcleanup=: 3 : '0[sdclose SOCKETS_jsocket_' +sdinit=: 3 : 0 +if. 0=nc<'SOCKETS_jsocket_' do. 0 return. end. +SOCKETS_jsocket_=: '' +if. IFUNIX do. 0 return. end. +if. 0~:res WSAStartupJ 257;1000$' ' do. _1[mbinfo'Socket Error' else. 0 end. +) +sdrecv=: 3 : 0"1 +'s size'=. 2{.y +r=. recvJ s;(size#' ');size;2{3{.y +if. 0>c=. res r do. '';~sdsockerror'' return. end. +0;c{.>2{r +) +sdrecvfrom=: 3 : 0"1 +'s size flags'=. 3 {. y ,<0 +s=. {.s +r=. recvfromJ s;(size#' ');size;flags;(sockaddr_in_sz#{.a.);,sockaddr_in_sz +'unexpected size of peer address' assert sockaddr_in_sz = 6 pick r +if. 0>c=. res r do. (sdsockerror '');'';'' return. end. +0;(c{.>2{r); 5{r +) +sdconnect=: 3 : 0"1 +rc0 connectJ (>{.y);(sockaddr_in y);sockaddr_in_sz +) +sdsocket=: 3 : 0"1 +s=. res socketJ <"0 [3{.y,(0=#y)#PF_INET,SOCK_STREAM,IPPROTO_TCP +if. s=_1 do. 0;~sdsockerror'' return. end. +SOCKETS_jsocket_=: SOCKETS_jsocket_,s +0;s +) +sdbind=: 3 : 0"1 +rc0 bindJ (>{.y);(sockaddr_in y);sockaddr_in_sz +) +sdasync=: 3 : 0"0 +if. IFUNIX do. 'not implemented under Unix - please use sdselect' assert 0 end. +flags=. OR/ FD_READ,FD_WRITE,FD_OOB,FD_ACCEPT,FD_CONNECT,FD_CLOSE +hwnd=. ".wd'qhwndx' +if. >{.WSAAsyncSelectJ ({.y);hwnd;1026;flags do. sdsockerror '' else. 0 end. +) +sdlisten=: 3 : 0"1 +rc0 listenJ ;/2 {. y,<^:(L.y) SOMAXCONN +) +sdaccept=: 3 : 0"0 +if. _1~:s=. res r=. acceptJ y;(sockaddr_in_sz$' ');,sockaddr_in_sz do. + SOCKETS_jsocket_=: SOCKETS_jsocket_,s + 0;s +else. 0;~sdsockerror '' end. +) +sdgethostbyname=: 3 : 0 +if. 0~:hostent=. res gethostbynameJ :>./r,w,e,0 + m=. 4 + n=. 32 + bytes=. m*>:<.n%~max1 + r=. bytes fdset_bytes r + w=. bytes fdset_bytes w + e=. bytes fdset_bytes e + rwe=. r;w;e +else. + max1=. 0 + rwe=. (] ,~ #) each r;w;e +end. +if. _1=res q=. selectJ (4{r +if. name-:SO_LINGER do. 0;65536 65536#:d else. 0;d end. +) +sdsetsockopt=: 3 : 0 +'s lev name val'=. y +if. name -: SO_LINGER do. val=. 65536 65536#.val end. +rc0 setsockoptJ s;lev;name;(,val);4 +) +sdsockerror=: 3 : 0 +> {. cderx '' +) +sdioctl=: 3 : 0 +'s option value'=. y +r=. ioctlsocketJ s;option;,value +if. 0~:res r do. 0;~sdsockerror'' else. 0;''$>3{r end. +) +sdionread=: 3 : 0 +''$>{.sdcheck sdioctl y,FIONREAD,0 +) +sdgethostname=: 3 : 0 +if. 0=res r=. gethostnameJ (256#' ');256 do. + 0;>{.1 take (0{a.)cutopen ;1{r +else. + 0;'unknown host' +end. +) +sdgetpeername=: 3 : 0"0 +namesub getpeernameJ y;(sockaddr_in_sz#{.a.);,sockaddr_in_sz +) +sdgetsockname=: 3 : 0"0 +namesub getsocknameJ y;(sockaddr_in_sz#{.a.);,sockaddr_in_sz +) + +sdgetsockets=: 3 : '0;SOCKETS_jsocket_' +sdcheck=: }. ` (sderror 13!:8 3:) @. (0 ~: >@{.) +INVALID_SOCKET=: 1 +SOCKET_ERROR=: _1 +sdinit'' diff --git a/j/system/main/stdlib.ijs b/j/system/main/stdlib.ijs new file mode 100644 --- /dev/null +++ b/j/system/main/stdlib.ijs @@ -0,0 +1,2007 @@ +18!:4 <'z' +3 : 0 '' + +notdef=. 0: ~: 4!:0 @ < +jpathsep=: '/'&(('\' I.@:= ])}) +winpathsep=: '\'&(('/' I.@:= ])}) +PATHJSEP_j_=: '/' +IF64=: 16={:$3!:3[2 +'IFUNIX IFWIN IFWINCE'=: 5 6 7 = 9!:12'' +IFGTK=: IFJHS=: 0 +IFJ6=: 0 +IFWINE=: IFWIN > 0-:2!:5'_' +if. IFUNIX do. + UNAME=: (2!:0 'uname')-.10{a. +else. + UNAME=: 'Win' +end. +) +jcwdpath=: (1!:43@(0&$),])@jpathsep@((*@# # '/'"_),]) +jsystemdefs=: 3 : 0 +0!:0 +echo=: 0 0&$ @ (1!:2&2) +exit=: 2!:55 +every=: &> +getenv=: 2!:5 +inv=: inverse=: ^:_1 +items=: "_1 +fetch=: {:: +leaf=: L:0 +nameclass=: nc=: 4!:0 +namelist=: 4!:1 +on=: @: +pick=: >@{ +rows=: "1 +stdout=: 1!:2&4 +stderr=: 1!:2&5 +stdin=: 1!:1@3: :. stdout +sign=: * +sort=: /:~ : /: +take=: {. +assert=: 0 0 $ 13!:8^:((0 e. ])`(12"_)) +bind=: 2 : 'x@(y"_)' +boxopen=: <^:(L.=0:) +boxxopen=: <^:(L.<*@#) +clear=: 3 : 0 +". 'do_',(' '-.~y),'_ '' (#~ -.@(4!:55)) (4!:1) 0 1 2 3''' +) +cutLF=: 3 : 'if. L. y do. y else. a: -.~ <;._2 y,LF end.' +cutopen=: 3 : 0 +y cutopen~ (' ',LF) {~ LF e. ,y +: +if. L. y do. y return. end. +if. 1 < #$y do. <"_1 y return. end. +(<'') -.~ (y e.x) <;._2 y=. y,1{.x +) +datatype=: 3 : 0 +n=. 1 2 4 8 16 32 64 128 1024 2048 4096 8192 16384 32768 65536 131072 +t=. '/boolean/literal/integer/floating/complex/boxed/extended/rational' +t=. t,'/sparse boolean/sparse literal/sparse integer/sparse floating' +t=. t,'/sparse complex/sparse boxed/symbol/unicode' +(n i. 3!:0 y) pick <;._1 t +) +empty=: EMPTY"_ +erase=: [: 4!:55 ;: ::] +expand=: # inverse +H=. '0123456789ABCDEF' +h=. '0123456789abcdef' +dfh=: 16 #. 16 | (H,h) i. ] +hfd=: h {~ 16 #.^:_1 ] +isutf8=: 1:@(7&u:) :: 0: +list=: 3 : 0 +w=. {.wcsize'' +w list y +: +if. 0=#y do. i.0 0 return. end. +if. 2>#$y=. >y do. + d=. (' ',LF) {~ LF e. y=. toJ ": y + y=. [;._2 y, d #~ d ~: {: y +end. +y=. y-. ' '{.~ c=. {:$ y=. (": y),.' ' +(- 1>. <. x % c) ;\ <"1 y +) +nl=: 3 : 0 +'' nl y +: +if. 0 e. #y do. y=. 0 1 2 3 end. + +if. 1 4 8 e.~ 3!:0 y do. + nms=. (4!:1 y) -. ;: 'x y x. y.' +else. + nms=. cutopen_z_ y +end. + +if. 0 e. #nms do. return. end. + +if. #t=. x -. ' ' do. + 'n s'=. '~*' e. t + t=. t -. '~*' + b=. t&E. &> nms + if. s do. b=. +./"1 b + else. b=. {."1 b end. + nms=. nms #~ n ~: b +end. +) +names=: list_z_ @ nl +Note=: 3 : '0 0 $ 0 : 0' : [ +script=: [: 3 : '0!:0 y [ 4!:55<''y''' jpath_z_ &.: > +scriptd=: [: 3 : '0!:1 y [ 4!:55<''y''' jpath_z_ &.: > +sminfo=: 3 : 0 +if. IFGTK do. mbinfo_jgtk_ y else. smoutput >_1{.boxopen y end. +) +smoutput=: 0 0 $ 1!:2&2 +tmoutput=: 0 0 $ 1!:2&4 +split=: {. ,&< }. +table=: 1 : 0~ +: +(((#~LF-.@e.])5!:5<'u');,.y),.({.;}.)":x,y u/x +) +timex=: 6!:2 +timespacex=: 6!:2 , 7!:2@] +tolower=: 3 : 0 +x=. I. 26 > n=. ((65+i.26){a.) i. t=. ,y +($y) $ ((x{n) { (97+i.26){a.) x}t +) + +toupper=: 3 : 0 +x=. I. 26 > n=. ((97+i.26){a.) i. t=. ,y +($y) $ ((x{n) { (65+i.26){a.) x}t +) +t=. <;._1 '/invalid name/not defined/noun/adverb/conjunction/verb/unknown' +type=: {&t@(2&+)@(4!:0)&boxopen +ucp=: 7&u: +ucpcount=: # @ (7&u:) +utf8=: 8&u: +uucp=: u:@(7&u:) +3 : 0'' +h=. 9!:12'' +subs=. 2 : 'x I. @(e.&y)@]} ]' +toJ=: (LF subs CR) @: (#~ -.@(CRLF&E.@,)) +toCRLF=: 2&}. @: ; @: (((CR&,)&.>)@<;.1@(LF&,)@toJ) +if. h=5 do. + toHOST=: ] +else. + toHOST=: toCRLF +end. +1 +) +18!:4 <'z' + +coclass=: 18!:4 @ boxxopen +cocreate=: 18!:3 +cocurrent=: 18!:4 @ boxxopen +codestroy=: coerase @ coname +coerase=: 18!:55 +cofullname=: 3 : 0 +y=. ,> y +if. #y do. + if. ('_' = {: y) +: 1 e. '__' E. y do. + y,'_',(>18!:5''),'_' + end. +end. +) +coinsert=: 3 : 0 +n=. ;: :: ] y +p=. ; (, 18!:2) @ < each n +p=. ~. (18!:2 coname''), p +(p /: p = <,'z') 18!:2 coname'' +) +coname=: 18!:5 +conames=: list_z_ @ conl +conew=: 3 : 0 +c=. y) (4 : 'try. x e. nl__y $0 catch. 0 end.'"0 # ]) 18!:1]0 1 +if. 0=#r do. i.0 2 end. +) +cofindv=: 3 : 0 +lcs=. cofind y +if. #lcs do. + lcs ,. ". each ( ".each n +< ;: inverse t +) +conounsx=: 3 : 0 +r=. '' +if. #y do. + s=. #y=. boxxopen y + loc=. conl 0 + for_i. loc do. r=. r,conouns__i y end. + r=. (r~:a:) # (y$~#r),.r,.s#loc +end. +/:~~.r +) +copathnl=: 3 : 0 +'' copathnl y +: +r=. '' +t=. (coname''),copath coname'' +for_i. t -. <,'z' do. + r=. r,x nl__i y +end. +/:~~.r +) +copathnlx=: 3 : 0 +'' copathnlx y +: +r=. '' +t=. (coname''),copath coname'' +for_i. t=. t -. <,'z' do. + r=. r, r) #each t +) +coselect_result=: 3 : 0 +'r x s'=. y +if. r do. + runimmx0_jijs_ '18!:4 <''',s,'''' +end. +empty'' +) +costate=: 3 : 0 +r=. ,: ;:'refs id creator path' +if. #n=. conl 1 do. r,coinfo &> n /: 0 ".&> n end. +) +cocurrent 'z' +cd=: 15!:0 +memr=: 15!:1 +memw=: 15!:2 +mema=: 15!:3 +memf=: 15!:4 +cdf=: 15!:5 +cder=: 15!:10 +cderx=: 15!:11 +gh=. 15!:8 +fh=. 15!:9 +symget=: 15!:6 +symset=: 15!:7 +cdcb=: 15!:13 +JB01=: 1 +JCHAR=: 2 +JSTR=: _1,JCHAR +JINT=: 4 +JPTR=: JINT +JFL=: 8 +JCMPX=: 16 +JBOXED=: 32 +JTYPES=: JB01,JCHAR,JINT,JPTR,JFL,JCMPX,JBOXED +JSIZES=: >IF64{1 1 4 4 8 16 4;1 1 8 8 8 16 8 +ic=: 3!:4 +fc=: 3!:5 +endian=: |.^:('a'={.2 ic a.i.'a') +AND=: $:/ : (17 b.) +OR=: $:/ : (23 b.) +XOR=: $:/ : (22 b.) +cocurrent 'z' +3 : 0 '' +if. -. (UNAME-:'Darwin')+.(UNAME-:'SunOS') do. DLL_PATH=: '' return. end. +llp=. 2!:5 'LD_LIBRARY_PATH',~'DY'#~UNAME-:'Darwin' +if. 0 -: llp do. llp=. '' end. +def_path=. ':/usr/local/lib:/usr/lib:/usr/lib/ccs/lib:/etc/lib:/lib' +DLL_PATH=: a: -.~ <;._1 ':',llp,def_path +) +find_dll=: 3 : 0 +DLL_PATH find_dll y +: +if. UNAME-:'Linux' do. ('find_dll decommitted') 13!:8 ] 24 end. +if. -.IFUNIX do. y return. end. +y=. ,y +if. (UNAME-:'Darwin') do. ext=. '.dylib*' else. ext=. '.so*' end. +for_dir. x do. + l=. (>dir), '/lib', y, ext + if. # fns=. \:~ 1!: 0 l do. + (>dir), '/', > (<0 0) { fns + return. + end. +end. +('could not locate dll ',y) 13!:8 ] 24 +) +break=: 3 : 0 +class=. >(0=#y){y;'default' +p=. 9!:46'' +q=. (>:p i: '/'){.p +fs=. (:a.i.1!:11 f,<0 1 + (v{a.) 1!:12 f,<0 +end. +i.0 0 +) +setbreak=: 3 : 0 +p=. jpath '~break/' +1!:5 ::]

:*"1>/)i.42 +m=. (<:}.y),i.12*1=#y +h=. 'JanFebMarAprMayJunJulAugSepOctNovDec' +h=. ((x*3)|.' Su Mo Tu We Th Fr Sa'),:"1~_3(_12&{.)\h +<"2 m{h,"2[12 6 21 ($,) r{' ',3":1+i.31 1 +) +getdate=: 3 : 0 +0 getdate y +: +r=. '' +opt=. x +chr=. [: -. [: *./ e.&'0123456789 ' +dat=. ' ' (I. y e.',-/:') } y + +if. chr dat do. + opt=. 0 + dat=. a: -.~ <;._1 ' ',dat + if. 1=#dat do. r return. end. + typ=. chr &> dat + dat=. (2{.typ{dat),{:dat + mth=. 3{.>1{dat + uc=. 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + lc=. 'abcdefghijklmnopqrstuvwxyz' + mth=. (lc,a.) {~ mth i.~ uc,a. + mos=. _3[\'janfebmaraprmayjunjulaugsepoctnovdec' + mth=. <": >:mos i. mth + dat=. ;' ',each mth 1 } dat +end. + +dat=. ". :: (''"_) dat +if. 0 e. #dat do. return. end. + +if. 3 ~: #dat do. r return. end. + +if. 31 < {.dat do. 'y m d'=. dat +else. ((opt|.'d m '),' y')=. dat +end. + +if. y<100 do. + y=. y + (-100&|) {. 6!:0'' +end. + +(#~ valdate) y,m,d +) +isotimestamp=: 3 : 0 +r=. }: $y +t=. _6 [\ , 6 {."1 y +d=. '--b::' 4 7 10 13 16 }"1 [ 4 3 3 3 3 3 ": <.t +d=. d ,. }."1 [ 0j3 ": ,. 1 | {:"1 t +c=. {: $d +d=. ,d +d=. '0' (I. d=' ')} d +d=. ' ' (I. d='b')} d +(r,c) $ d +) +todate=: 3 : 0 +0 todate y +: +s=. $y +a=. 657377.75 +, y +d=. <. a - 36524.25 * c=. <. a % 36524.25 +d=. <.1.75 + d - 365.25 * y=. <. (d+0.75) % 365.25 +r=. (1+12|m+2) ,: <. 0.41+d-30.6* m=. <. (d-0.59) % 30.6 +r=. s $ |: ((c*100)+y+m >: 10) ,r +if. x do. r=. 100 #. r end. +r +) +todayno=: 3 : 0 +0 todayno y +: +a=. y +if. x do. a=. 0 100 100 #: a end. +a=. ((*/r=. }: $a) , {:$a) $,a +'y m d'=. <"_1 |: a +y=. 0 100 #: y - m <: 2 +n=. +/ |: <. 36524.25 365.25 *"1 y +n=. n + <. 0.41 + 0 30.6 #. (12 | m-3),"0 d +0 >. r $ n - 657378 +) +tsdiff=: 4 : 0 +r=. -/"2 d=. _6 (_3&([\)) \ ,x,"1 y +if. #i=. i#i.#i=. 0 > 2{"1 r do. + j=. (-/0=4 100 400 |/ (: 10) ,s + r $ s,. (_3{. &> t%1000) +"1 [ 0 60 60 #: n +else. + a=. ((*/r=. }: $y) , {:$y) $, y + 'w m d'=. <"_1 |: 3{."1 a + w=. 0 100 #: w - m <: 2 + n=. +/ |: <. 36524.25 365.25 *"1 w + n=. n + <. 0.41 + 0 30.6 #. (12 | m-3),"0 d + s=. 3600000 60000 1000 +/ .*"1 [ 3}."1 a + r $ s+86400000 * n - 657378 +end. +) +timestamp=: 3 : 0 +if. 0 = #y do. w=. 6!:0'' else. w=. y end. +r=. }: $ w +t=. 2 1 0 3 4 5 {"1 [ _6 [\ , 6 {."1 <. w +d=. '+++::' 2 6 11 14 17 }"1 [ 2 4 5 3 3 3 ": t +mth=. _3[\' JanFebMarAprMayJunJulAugSepOctNovDec' +d=. ,((1 {"1 t) { mth) 3 4 5 }"1 d +d=. '0' (I. d=' ') } d +d=. ' ' (I. d='+') } d +(r,20) $ d +) + +tstamp=: timestamp +valdate=: 3 : 0 +s=. }:$y +'w m d'=. t=. |:((*/s),3)$,y +b=. *./(t=<.t),(_1 0 0:m +day=. (13|m){0 31 28 31 30 31 30 31 31 30 31 30 31 +day=. day+(m=2)*-/0=4 100 400|/w +s$b*d<:day +) +weekday=: 7 | 3 + todayno +weeknumber=: 3 : 0 +yr=. {.y +sd=. 1 ((i.~weekday){]) ((<:yr),.12,.29+i.3),yr,.1,.1+i.4 +wk=. >.7%~>: y -&todayno sd +if. wk >weeksinyear yr do. + (>:yr),1 +elseif. wk=0 do. + (,weeksinyear)<:yr +elseif. do. + yr,wk +end. +) +weeksinyear=: 3 : '52+ +./"1 [ 4=weekday(1 1,:12 31),"0 1/~ y' +cocurrent 'z' +dbr=: 13!:0 +dbs=: 13!:1 +dbsq=: 13!:2 +dbss=: 13!:3 +dbrun=: 13!:4 +dbnxt=: 13!:5 +dbret=: 13!:6 +dbjmp=: 13!:7 +dbsig=: 13!:8 +dbrr=: 13!:9 +dbrrx=: 13!:10 +dberr=: 13!:11 +dberm=: 13!:12 +dbstk=: 13!:13 +dblxq=: 13!:14 +dblxs=: 13!:15 +dbtrace=: 13!:16 +dbq=: 13!:17 +dbst=: 13!:18 +dbctx=: 3 3&$: : (4 : 0) +if. -.13!:17'' do. 0 0$'' return. end. +try. + 'before after'=. 2{. <. , x, 3 3 +catch. + 'before after'=. 3 3 +end. +if. 0= #d=. 13!:13'' do. 0 0$'' return. end. +if. '*' -.@e. sus=. >{:"1 d do. 0 0$'' return. end. +'name ln nc def src'=. 0 2 3 4 5{(sus i. '*'){d +dyad=. {: ':'&e.;._2 ] 13!:12'' +if. (_2{.def) -: LF,')' do. + def=. }.def [ def0=. {.def=. }:<;._2 def,LF +else. + def=. ,: def i. <,':' + else. + def=. def{.~ def i. <,':' + end. +end. +min=. 0>.ln-before [ max=. (<:#def)<.ln+after +ctx=. '[',"1 (":,.range) ,"1 ('] ') ,"1 >def{~range=. min + i. >:max-min +> (<'@@ ', name, '[', (dyad#':'), (":ln) ,'] *', (nc{' acv'),' @@ ', src), def0, <"1 ctx +) +dbg=: 13!:0 +dblocals=: _1&$: : (4 : 0) +stk=. }. 13!:13'' +if. 0=#y do. y=. a: else. y=. (y e. i.#stk) # y end. +loc=. ( {:"1 loc +end. +) +dbstack=: 3 : 0 +hdr=. ;:'name en ln nc args locals susp' +stk=. }. 13!:13'' +if. #y do. + if. 2=3!:0 y do. + stk=. stk #~ ( stk +wds=. ({:@$@":@,.)"1 |: stk +len=. 20 >.<.-:({.wcsize'') - +/8, 4 {. wds +tc=. (len+1)&<.@$ {.!.'.' ({.~ len&<.@$) +tc@": each stk +) +dbstop=: 3 : 0 +if. 0 e. #y -. ' ' do. 13!:3'' return. end. +t=. 13!:2'' +if. #t do. t=. <;._2 t, ';' -. {:t end. +t=. ~. t, (;: ^: (L.=0:) y) ,&.> <' *:*' +13!:3 ; t ,&.> ';' +) +dbstops=: 3 : 0 +13!:3 ; (;: ^: (L.=0:) y) ,&.> <' *:*;' +) +dbstopme=: 3 : 0 +if. y do. + if. 0 e. $c=. }. 13!:13'' do. return. end. + c=. (> {. {. c), ' *:*' + t=. 13!:2'' + if. #t do. t=. <;._2 t, ';' -. {:t end. + t=. ~. t, ';' +end. +) +dbstopnext=: 3 : 0 +if. y do. + if. 0 e. $c=. }. 13!:13'' do. return. end. + 'd n a'=. 0 2 6 { {. c + c=. d,' ',(':'#~2=#a),":n+1 + t=. 13!:2'' + if. #t do. t=. <;._2 t, ';' -. {:t end. + t=. ~. t, ';' +end. +) +dbview=: 3 : 0 +if. _1 = 4!:0 <'jdbview_jdbview_' do. + 'require'~'~system/util/dbview.ijs' +end. +jdbview_jdbview_ }. 13!:13'' +) +cocurrent 'z' +dir=: 3 : 0 +'n' dir y +: +ps=. '/' +y=. jpath y,(0=#y)#'*' +y=. y,((':',ps) e.~ {:y)#'*' +if. 0=#dr=. 1!:0 y do. empty'' return. end. +fls=. 'd' ~: 4{"1>4{"1 dr +if. (1=#dr) *. 0={.fls do. + r=. x dir y,ps,'*' + if. #r do. r return. end. +end. +if. fmt=. 2=3!:0 x do. opt=. 2 1 +else. opt=. 2{.x end. +if. 0={:opt do. fls=. 1#~#dr=. fls#dr end. +if. 0=#dr do. empty'' return. end. +nms=. {."1 dr +nms=. nms ,&.> fls{ps;'' +if. IFWIN do. + nms=. tolower &.> nms +end. +ndx=. /: (":,.fls),.>nms +if. 0=opt do. + list >ndx{nms +elseif. 1=opt do. + path=. (+./\.y=ps)#y + path&,&.>ndx{nms +elseif. fmt<2=opt do. + ndx{nms,.}."1 dr +elseif. fmt do. + 'nms ts size'=. |:3{."1 dr + if. IFWIN do. + nms=. tolower L:0 nms + end. + ds=. '

' ((-.fls)#i.#fls) } 12 ":,.size + mth=. _3[\' JanFebMarAprMayJunJulAugSepOctNovDec' + f=. > @ ([: _2&{. [: '0'&, ": )&.> + 'y m d h n s'=. f&> ,<"1 |: 100|ts + m=. (1{"1 ts){mth + time=. d,.'-',.m,.'-',.y,.' ',.h,.':',.n,.':',.s + dat=. (>nms),.ds,.' ',.time + dat /: fls,. /:/: >(3|'dns'i.x){ts;nms;size +elseif. 1 do. + 'invalid left argument' +end. +) +dircompare=: 3 : 0 +0 dircompare y +: +if. 0=#y do. + '''long dirtree timestamps'' dircompare dir1;dir2' + return. +end. + +opt=. 3 {. x +res=. opt dircompares y +if. 0 = L. res do. return. end. + +ps=. '/' +'a b c'=. res + +'x y'=. jpath each cutopen y +x=. x, ps #~ (*#x) *. ps~:_1{.x +y=. y, ps #~ (*#y) *. ps~:_1{.y + +r=. 'comparing ',x,' and ',y,LF + +if. #a do. + r=. r,LF,'not in ',y,':',LF,,(list a),.LF +end. + +if. #b do. + r=. r,LF,'not in ',x,':',LF,,(list b),.LF +end. + +if. +/ # &> c do. + 'cf cd'=. c + r=. r,LF,'not same in both:',LF,,(list cf),.LF + if. {.opt do. + r=. r,LF,;(,&(LF2)) &.> cd + end. + +end. + +if. 0=#;res do. r=. r,'no difference',LF end. + +}:r +) +dircompares=: 3 : 0 +0 dircompares y +: +ps=. '/' +opt=. 3{. x +'x y'=. jpath each cutopen y +x=. x, ps #~ (*#x) *. ps~:_1{.x +y=. y, ps #~ (*#y) *. ps~:_1{.y + +if. 1{opt do. + dx=. dirtree x [ dy=. dirtree y +else. + dx=. 2 0 dir x [ dy=. 2 0 dir y +end. + +if. dx -: dy do. 'no difference' return. end. +if. 0 e. #dx do. 'first directory is empty' return. end. +if. 0 e. #dy do. 'second directory is empty' return. end. + +f=. #~ [: +./\. =&ps +sx=. f x +sy=. f y +fx=. {."1 dx +fy=. {."1 dy + +if. 1{opt do. + fx=. (#sx)}.&.>fx + fy=. (#sy)}.&.>fy + dx=. fx 0 }"0 1 dx + dy=. fy 0 }"0 1 dy +end. + +r=. j),.sy&,&.>j + + if. 0=2{opt do. + f=. 'no difference'&-: @ (_13&{.) + msk=. -. f &> cmp + j=. msk#j + cmp=. msk#cmp + end. + + r=. r,< j; d +if. 1 e. m do. ; (m # d) ,each LF else. 0 0$'' end. +) +dirpath=: 3 : 0 +0 dirpath y +: +r=. '' +t=. jpath y +ps=. '/' +if. #t do. t=. t, ps -. {:t end. +dirs=. @ (4&{"1) +subdir=. ifdir # ] +while. #dirs do. + fpath=. (>{.dirs) &, + dirs=. }.dirs + dat=. 1!:0 fpath '*' + if. #dat do. + dat=. subdir dat + if. #dat do. + r=. r, fpath each /:~ {."1 dat + dirs=. (fpath @ (,&ps) each {."1 dat),dirs + end. + end. +end. +if. x do. + f=. 1!:0 @ (,&(ps,'*')) + g=. 0:`(0: e. ifdir) + h=. g @. (*@#) @ f + r=. r #~ h &> r +end. +if. #t do. r=. r,<}:t end. +if. IFWIN do. + r=. tolower each r +end. +/:~ r +) +dirss=: 4 : 0 +if. (2=#x) *. 1=L. x do. + x dirssrplc y return. +end. + +sub=. ' '&(I.@(e.&(TAB,CRLF))@]}) +fls=. {."1 dirtree y +if. 0 e. #fls do. + 'no files in directory: ',y return. +end. +fnd=. '' +while. #fls do. + dat=. 1!:1 {.fls + fls=. }.fls + ndx=. I. x E. dat + if. rws=. #ndx do. + dat=. (20$' '),dat,30$' ' + dat=. (rws,50)$sub(,ndx+/i.50){dat + fnd=. fnd,LF2,fl,' (',(":#ndx),')' + fnd=. fnd,,LF,.dat + end. +end. +if. #fnd do. 2}.fnd else. 'not found: ',x end. +) +dirssrplc=: 4 : 0 +fls=. {."1 dirtree y +if. 0 e. #fls do. + 'no files found' return. +end. +r=. (x&fssrplc) each fls +b=. r ~: <'no match found' +j=. >b # fls , each ': '&, each r +}: , j ,. LF +) +dirtree=: 3 : 0 +0 dirtree y +: +if. 0=4!:0 <'DirTreeX_j_' do. + ex=. boxxopen DirTreeX_j_ +else. + ex=. '' +end. +r=. i.0 3 +ps=. '/' +y=. jpath y +y=. y #~ (+./\ *. +./\.) y~:' ' +y=. y,(0=#y)#'*' +if. ps={:y do. y=. y,'*' end. +if. -. '*' e. y do. + if. 1 = #j=. 1!:0 y do. + select. 'hd' = 1 4 { >4{,j + case. 0 1 do. x dirtree y,ps,'*' return. + case. 1 1 do. i.0 3 return. + end. + end. +end. +ts=. 100"_ #. 6: {. 0: >. <. - # {. 1980"_ +'path ext'=. (b#y);(-.b=. +./\.y=ps)#y +if. #dl=. 1!:0 y do. + att=. > 4{"1 dl + fl=. (('h' ~: 1{"1 att) *. 'd' ~: 4{"1 att)#dl + if. #fl do. + r=. r,(path&,&.>{."1 fl),.1 2{"1 fl + end. +end. +if. #dl=. 1!:0 path,'*' do. + att=. > 4{"1 dl + dr=. {."1 (('h' ~: 1{"1 att) *. 'd' = 4{"1 att) # dl + dr=. dr -. ex + if. #dr do. + r=. r,;x&dirtree@(path&,@,&(ps,ext)) &.> dr + end. +end. +r=. r #~ (ts x) <: ts &> 1{"1 r +if. IFWIN *. #r do. + (tolower L:0 {."1 r) 0 }"0 1 r +end. +) +dirused=: [: (# , +/ @ ; @ (2: {"1 ])) 0&dirtree +cocurrent 'z' + +fboxname=: <@jpath_j_@(8 u: >) ::] +fexists=: #~ fexist +f2utf8=: ] +fappend=: 4 : 0 +(,x) (#@[ [ 1!:3) :: _1: fboxname y +) +fappends=: 4 : 0 +(fputs x) (#@[ [ 1!:3) :: _1: fboxname y +) +fapplylines=: 1 : 0 +0 u fapplylines y +: +y=. > fboxname y +s=. 1!:4 ) @ boxopen +fexist=: (1:@(1!:4) :: 0:) @ (fboxname &>) @ boxopen +fgets=: 3 : 0 +y=. (-(26{a.)={:y) }. y +if. 0=#y do. '' return. end. +y,LF -. {:y=. toJ y +) +fmakex=: (] 1!:7~ 'x' 2 5 8} 1!:7) @ fboxname +fpathcreate=: 3 : 0 +if. 0=#y do. 1 return. end. +p=. (,'/'-.{:) jpathsep y +if. # 1!:0 }: p do. 1 return. end. +for_n. I. p='/' do. 1!:5 :: 0: < n{.p end. +) +fpathname=: +./\.@:=&'/' (# ; -.@[ # ]) ] +fread=: 3 : 0 +if. 1 = #y=. boxopen y do. + 1!:1 :: _1: fboxname y +else. + 1!:11 :: _1: (fboxname {.y),{:y +end. +: +x freads y +) +freadblock=: 3 : 0 +'f p'=. y +f=. > fboxname f +s=. 1!:4 : s do. '';p return. end. +if. 1e6 < s-p do. + dat=. 1!:11 f;p,1e6 + len=. 1 + dat i: LF + if. len > #dat do. + 'file not in LF-delimited lines' 13!:8[3 + end. + p=. p + len + dat=. len {. dat +else. + dat=. 1!:11 f;p,s-p + dat=. dat, LF -. {: dat + p=. s +end. +(toJ dat);p +) +freadr=: 3 : 0 +'f s'=. 2{.boxopen y +f=. fboxname f +max=. 1!:4 :: _1: f +if. max -: _1 do. return. end. +pos=. 0 +step=. 10000 +whilst. blk = cls +do. + blk=. step<.max-pos + if. 0=blk do. 'file not organized in records' return. end. + dat=. 1!:11 f, fboxname x +y=. > fboxname y +if. x -: y do. return. end. +if. IFUNIX do. + 2!:0 'mv "',y,'" "',x,'"' +else. + 'kernel32 MoveFileW i *w *w' 15!:0 (uucp y);uucp x +end. +) +freplace=: 4 : 0 +y=. boxopen y +dat=. ,x +f=. #@[ [ 1!:12 +dat f :: _1: (fboxname {.y),{:y +) +fsize=: (1!:4 :: _1:) @ (fboxname &>) @ boxopen +fss=: 4 : 0 +y=. fboxname y +size=. 1!:4 :: _1: y +if. size -: _1 do. return. end. +blk=. (#x) >. 100000 <. size +r=. i.pos=. 0 +while. pos < size do. + dat=. 1!:11 y,@{ , @ (1!:0) @ fboxname) :: _1: +fputs=: 3 : 0 +dat=. ":y +if. 0 e. $dat do. + '' +else. + if. 1>:#$dat do. + toHOST dat,(-.({:dat) e. CRLF) # LF + else. + ,dat,"1 toHOST LF + end. +end. +) +ftype=: 3 : 0 +d=. (}: ^: ('/'={:)) ucp y +d=. 1!:0 fboxname d +if. #d do. + >: 'd' = 4 { > 4 { ,d +else. + 0 +end. +) +fview=: 3 : 0 +if. 3 ~: nc <'textview_z_' do. + sminfo 'textview not available.' return. +end. +txt=. freads y +if. txt -: _1 do. + sminfo 'file not found: ',,>y return. +end. +textview txt +) +fwrite=: 4 : 0 +(,x) (#@[ [ 1!:2) :: _1: fboxname y +) +fwritenew=: 4 : 0 +dat=. ,x +if. dat -: fread y do. 0 return. end. +dat fwrite y +) +fwrites=: 4 : 0 +(fputs x) (#@[ [ 1!:2) :: _1: fboxname y +) +ftostring=: fputs +fstring=: fgets +cocurrent 'z' +install=: 3 : 0 +require 'pacman' +if. -. checkaccess_jpacman_ '' do. return. end. +'update' jpkg '' +select. y +case. 'gtkide' do. + getgtkbin 0 + 'install' jpkg 'base library ide/gtk gui/gtk' +case. 'all' do. + getgtkbin 0 + 'install' jpkg 'all' +end. +) +getgtkbin=: 3 : 0 +if. UNAME -: 'Linux' do. return. end. +if. (0={.y,0) *. 0 < #1!:0 jpath '~install/gtk/lib' do. return. end. +require 'pacman' +smoutput 'Installing gtk binaries...' +z=. (IFWIN pick 'mac';'win'),(IF64 pick '32';'64'),'.zip' +z=. 'http://www.jsoftware.com/download/gtk',z +'rc p'=. httpget_jpacman_ z +if. rc do. + smoutput 'unable to download: ',z return. +end. +d=. jpath '~install' +if. IFWIN do. + unzip_jpacman_ p;d +else. + hostcmd_jpacman_ 'unzip ',(dquote p),' -d ',dquote d + ('INSTALLPATH';jpath '~install/gtk') dirss jpath '~install/gtk/etc' +end. +if. #1!:0 jpath '~install/gtk/lib' do. + m=. 'Finished install of gtk binaries.' +else. + m=. 'Unable to install gtk binaries.',LF + m=. m,'check that you have write permission for: ',LF,jpath '~install/gtk' +end. +smoutput m +) +cocurrent 'z' +cuts=: 2 : 0 +if. n=1 do. [: u (#@[ + E. i. 1:) {. ] +elseif. n=_1 do. [: u (E. i. 1:) {. ] +elseif. n= 2 do. [: u (E. i. 1:) }. ] +elseif. 1 do. [: u (#@[ + E. i. 1:) }. ] +end. +) +cut=: ' '&$: :([: -.&a: <;._2@,~) +deb=: #~ (+. 1: |. (> d +smsk=. (> (0 , }:)) c +smsk=. -. smsk +. c *. 1|.fmsk +y=. smsk#y,fd +fmsk=. 0:^:(,@1: -: ]) smsk#fmsk +fmsk <;._2 y +) +dltbs=: LF&$: : (4 : 0) +txt=. ({.x), y +a=. txt ~: ' ' +b=. (a # txt) e. x +c=. b +. }. b, 1 +d=. ~: /\ a #^:_1 c ~: }: 0, c +}. (a >: d) # txt +) +dquote=: ('"'&,@(,&'"'))@ (#~ >:@(=&'"')) +dtbs=: 3 : 0 +CRLF dtbs y +: +txt=. y , {.x +blk=. txt ~: ' ' +ndx=. +/\ blk +b=. blk < }. (txt e. x), 0 +msk=. blk >: ndx e. b # ndx +}: msk # txt +) +rplc=: stringreplace~ +fstringreplace=: 4 : 0 +nf=. 'no match found' +y=. boxopen y +try. size=. 1!:4 y catch. nf return. end. +if. size=0 do. nf return. end. +old=. freads y +new=. x stringreplace old +if. old -: new do. nf return. end. +new fwrites y +cnt=. +/ (0 pick x) E. old +(":cnt),' replacement',((1~:cnt)#'s'),' made' +) +quote=: (''''&,@(,&''''))@ (#~ >:@(=&'''')) +nos=. i.@#@] e. #@[ ({~^:a:&0@(,&_1)@(]I.+) { _1,~]) I.@E. +splitnostring=: #@[ }.each [ (nos f. <;.1 ]) , +stringreplace=: 4 : 0 + +txt=. ,y +t=. _2 [\ ,x +old=. {."1 t +new=. {:"1 t +oldlen=. # &> old +newlen=. # &> new + +if. *./ 1 = oldlen do. + + hit=. (;old) i. txt + ndx=. I. hit < #old + + if. 0 e. $ndx do. txt return. end. + + cnt=. 1 + exp=. hit { newlen,1 + hnx=. ndx { hit + bgn=. ndx + +/\ 0, (}: hnx) { newlen - 1 + +else. + + + hit=. old I. @ E. each hit + + if. 0 = +/ cnt do. txt return. end. + + bgn=. set=. '' + + pick=. > @ { + diff=. }. - }: + + for_i. I. 0 < cnt do. + ln=. i pick oldlen + cx=. (i pick hit) -. set, ,bgn -/ i.ln + while. 0 e. b=. 1, <:/\ ln <: diff cx do. cx=. b#cx end. + hit=. ( hit + msk=. 0 < cnt + exp=. (#txt) $ 1 + del=. newlen - oldlen + + if. #add=. I. msk *. del > 0 do. + exp=. (>: (add{cnt) # add{del) (;add{hit) } exp + end. + + if. #sub=. I. msk *. del < 0 do. + sbx=. ; (;sub{hit) + each (sub{cnt) # i. each sub{del + exp=. 0 sbx } exp + end. + + hit=. ; hit + ind=. /: (#hit) $ 1 2 3 + hnx=. (/: ind { hit) { ind + bgn=. (hnx { hit) + +/\ 0, }: hnx { cnt # del + +end. + +ind=. ; bgn + each hnx { cnt # i.each newlen +rep=. ; hnx { cnt # new +rep ind} exp # txt +) +cutpara=: 3 : 0 +txt=. topara y +txt=. txt,LF -. {:txt +b=. (}.b,0) < b=. txt=LF +b <;._2 txt +) +foldtext=: 4 : 0 +if. 0 e. $y do. '' return. end. +y=. ; x&foldpara each cutpara y +y }.~ - (LF ~: |.y) i. 1 +) +foldpara=: 4 : 0 +if. 0=#y do. LF return. end. +r=. '' +x1=. >: x +txt=. y +while. + ind=. ' ' i.~ |. x1{.txt + s=. txt {.~ ndx=. x1 - >: x1 | ind + s=. (+./\.s ~: ' ') # s + r=. r, s, LF + #txt=. (ndx + ind (1,}:b) +. }.c,0 +' ' (I. b) } y +) + +cocurrent <'j' +Alpha=: a. {~ , (a.i.'Aa') +/ i.26 +Num=: a. {~ (a.i.'0') + i.10 +AlphaNum=: Alpha,Num +Boxes=: ((16+i.11) { a.),:'+++++++++|-' +ScriptExt=: '.ijs' +ProjExt=: '.jproj' + +extnone=: {.~ i:&'.' +extproj=: , (ProjExt #~ '.'&e. < 0 < #) +extsrc=: , ('.ijs' #~ '.'&e. < 0 < #) + +addfname=: , (e.&'/\' i: 1:) }. ] +boxdraw=: 3 : '9!:7 y { Boxes' +hostcmd=: [: 2!:0 '(' , ,&' || true)' +fpath=: [: }: +./\.@:=&'/' # ] +maxrecent=: 3 : '(RecentMax <. #r) {. r=. ~.y' +pack=: [: (,. ".&.>) ;: ::] +pdef=: 3 : '0 0$({."1 y)=: {:"1 y' +seldir=: #~ '-d'&-:"1 @ (1 4&{"1) @ > @ (4&{"1) +spath=: #~ [: *./\. '/'&~: +termLF=: , (0 < #) # LF -. {: +termsep=: , (0 < #) # '/' -. {: +tolist=: }.@;@:(LF&,each) +remsep=: }.~ [: - '/' = {: + +path2proj=: ,'/',ProjExt ,~ spath +3 : 0'' +if. IFUNIX do. + filecase=: ] + isroot=: '/' = {. +else. + filecase=: tolower + isroot=: ':' = {.@}. +end. +0 +) +dirtreex=: 3 : 0 +'' dirtreex y +: +y=. jpath y +p=. (+./\. y = '/') # y +d=. 1!:0 y,('/' = {:y) # '*' +if. 0 = #d do. '' return. end. +a=. > 4 {"1 d +m=. 'd' = 4 {"1 a +f=. ( f +end. +) +getfolderdefs=: 3 : 0 +p=. (, '/' , ProjExt ,~ spath) each subdirtree y +t=. p #~ #@(1!:0)&> p +t;'kernel32.dll GetConsoleWindow x'cd'' +'user32.dll ShowWindow n x i'cd t;(0-:y){5 0 +i.0 0 +) +mkdir=: 3 : 0 +a=. termsep y +if. #1!:0 }:a do. 1 return. end. +for_n. I. a='/' do. + 1!:5 :: 0: < n{.a +end. +) +newtempscript=: 3 : 0 +x=. ScriptExt +p=. jpath '~temp/' +d=. 1!:0 p,'*',x +a=. (-#x) }. each {."1 d +a=. a #~ (*./ .e.&'0123456789') &> a +a=. 0, {.@:(0&".) &> a +p, x ,~ ": {. (i. >: #a) -. a +) +nounrep=: 2 }. [: ; [: nounrep1 each ;: +nounrep1=: LF2 , ] , '=: ' , [: nounrep2 ". +nounrep2=: 3 : 0 +if. 0 = #y do. '''''' return. end. +select. 3!:0 y +fcase. 32 do. + y=. ; y ,each LF +case. 2 do. + if. LF e. y do. + y=. y, LF -. {:y + '0 : 0', LF, ; <;.2 y,')' + else. + quote y + end. +case. do. + ": y +end. +) +octal=: 3 : 0 +t=. ,y +x=. a. i. t +n=. x e. 9 10 13 +m=. n < 32 > x +if. (isutf8 t) > 1 e. m do. t return. end. +r=. t ,"0 1 [ 3 # EAV +if. #m=. I. m +. x>126 do. + s=. '\',.}.1 ": 8 (#.^:_1) 255,m{x + r=. s m} r +end. +EAV -.~ ,r +) +rmdir=: 3 : 0 +r=. 1;'not a directory: ',":y +if. 0=#y do. r return. end. +d=. 1!:0 y +if. 1 ~: #d do. r return. end. +if. 'd' ~: 4 { 4 pick {. d do. r return. end. +if. IFWIN do. + shell_jtask_ 'rmdir ',y,' /S /Q' +else. + hostcmd_j_ 'rm -rf --preserve-root ',y +end. +(#1!:0 y);'' +) +scripts=: 3 : 0 +if. 0=#y do. + list 0{"1 Public +elseif. 'v'e.y do. + dir=. Public + a=. >0{"1 dir + b=. >1{"1 dir + a /:~ a,.' ',.b +elseif. 1 do. + 'invalid argument to scripts: ',,":y +end. +) +setfolder=: 3 : 0 +if. 0=#y do. + Folder=: FolderTree=: FolderIds=: '' return. +end. +assert. ({.dir) &, + dir=. }.dir + dat=. seldir 1!:0 fpath '*' + if. #dat do. + dat=. fpath each {."1 dat + r=. r,dat + dir=. (dat ,each '/'),dir + end. +end. +sort filecase each r +) +unixshell=: 3 : 0 +f=. jpath '~temp/shell.sh' +t=. jpath '~temp/shell.txt' +e=. jpath '~temp/shell.err' +('#!/bin/sh',LF,y,LF) fwrite f +'rwx------' 1!:7 "',t,'" 2> "',e,'"' +r=. (fread t);fread e +ferase f;t;e +r +) +unixshellx=: 3 : 0 +'res err'=. unixshell y +if. #err do. + smoutput 'Shell command error: ',LF,LF,err +end. +res +) +htmlhelp=: 3 : 0 +f=. jpath '~addons/docs/help/',y +if. fexist ({.~ i:&'#') f do. + browse 'file://',f +else. + f=. 'http://www.jsoftware.com/docs/help',}.(i.&'/'{.]) 9!:14'' + browse f,'/',y +end. +) +browseref=: 3 : 0 +htmlhelp 'dictionary/',y +) +dquote=: 3 : 0 +if. '"' = {.y do. y else. '"',y,'"' end. +) +browse=: 3 : 0 +cmd=. dlb@dtb y +isURL=. 1 e. '://'&E. +if. IFJHS do. + cmd=. '/' (I. cmd='\') } cmd + if. -. isURL cmd do. + if. -.fexist cmd do. EMPTY return. end. + cmd=. 'file://',cmd + end. + redirecturl_jijxm_=: (' ';'%20') stringreplace cmd + EMPTY return. +end. +browser=. Browser_j_ +if. IFWIN do. + ShellExecute=. 'shell32 ShellExecuteW > i x *w *w *w *w i'&cd + SW_SHOWNORMAL=. 1 + NULL=. <0 + cmd=. '/' (I. cmd='\') } cmd + if. -. isURL cmd do. + if. -.fexist cmd do. EMPTY return. end. + cmd=. 'file://',cmd + end. + if. 0 = #browser do. + r=. ShellExecute 0;(uucp 'open');(uucp cmd);NULL;NULL;SW_SHOWNORMAL + else. + r=. ShellExecute 0;(uucp 'open');(uucp browser);(uucp dquote cmd);NULL;SW_SHOWNORMAL + end. + if. r<33 do. sminfo 'browse error:',browser,' ',cmd,LF2,1{::cderx'' end. + EMPTY return. +end. +if. 0 = #browser do. + browser=. dfltbrowser'' +end. +browser=. dquote (browser;Browser_nox_j_){::~ nox=. IFUNIX *. (0;'') e.~ <2!:5 'DISPLAY' +cmd=. '/' (I. cmd='\') } cmd +if. -. isURL cmd do. + cmd=. 'file://',cmd +end. +cmd=. browser,' ',dquote cmd +try. + 2!:1 cmd, (0=nox)#' >/dev/null 2>&1 &' +catch. + msg=. 'Could not run the browser with the command:',LF2 + msg=. msg, cmd,LF2 + if. IFGTK do. + msg=. msg, 'You can change the browser definition in Edit|Configure|Base',LF2 + end. + sminfo 'Run Browser';msg +end. +EMPTY +) +dfltbrowser=: verb define +select. UNAME +case. 'Win' do. '' +case. 'Darwin' do. 'open' +case. do. + try. + 2!:0'which google-chrome' + 'google-chrome' return. catch. end. + try. + 2!:0'which chromium-browser' + 'chromium-browser' return. catch. end. + try. + 2!:0'which firefox' + 'firefox' return. catch. end. + try. + 2!:0'which konqueror' + 'konqueror' return. catch. end. + try. + 2!:0'which netscape' + 'netscape' return. catch. end. + '' return. +end. +) +Folder=: '' +FolderTree=: FolderIds=: 0 + +Cwh=: 79 24 +jpath=: 3 : 0 +nam=. jpathsep y +if. '~' ~: {. nam do. return. end. +fld=. SystemFolders, UserFolders +ind=. nam i. '/' +tag=. }. ind {. nam +if. 0=#tag do. + tag=. 'home' + nam=. '~home',}.nam + ind=. nam i. '/' +end. +if. tag -: 'addons' do. + bal=. 8 }. nam +end. +par=. '.' = {. tag +if. par do. + len=. ('.' = tag) i. 0 + tag=. len }. tag +end. +ndx=. ({."1 fld) i. pps +pds=. ndx{pds +pps=. ndx{pps +res=. filecase each boxxopen y +len=. # &> pps +for_i. i.#res do. + nam=. i pick res + if. '~' = {. nam,'~' do. continue. end. + msk=. pps = len {. each ./) msk # len) { I. msk + nam=. ('~', > ndx { pds),(<: ndx { len) }. nam + res=. ( '/' +msk=. ndx < len +pps=. msk # ndx {.each pps +pds=. msk # pds +len=. # &> pps +for_i. i.#res do. + nam=. i pick res + if. '~' = {. nam,'~' do. continue. end. + if. '/' = {. nam do. continue. end. + msk=. pps = len {. each ./) msk # len) { I. msk + nam=. ('~.', > ndx { pds),(<: ndx { len) }. nam + res=. (res end. +) +Loaded=: '' +Public=: i. 0 2 +UserFolders=: i. 0 2 +Ignore=: ;: 'colib convert coutil dates debug dir dll files libpath strings text' +buildpublic=: 3 : 0 +dat=. deb toJ y +dat=. a: -.~ <;._2 dat, LF +ndx=. dat i. &> ' ' +short=. ndx {.each dat +long=. ndx }. each dat +long=. extsrc@jpathsep@deb each long +msk=. (<'system','/') = 7 {. each long +long=. (msk{'';'~') ,each long +Public=: sort ~. Public,~ short,.long +empty'' +) +cutnames=: 3 : 0 +if. LF e. y do. + txt=. y, LF + nms=. (txt = LF) <;._2 txt +else. + txt=. y, ' ' + msk=. txt = '"' + com=. (txt = ' ') > ~: /\ msk + msk=. (msk *. ~:/\msk) < msk <: 1 |. msk + nms=. (msk # com) <;._2 msk # txt +end. +nms -. a: +) +3 : 0'' +if. 0=9!:24'' do. + exist=: fexist +else. + exist=: 0: +end. +1 +) +fullname=: 3 : 0 +p=. '/' +d=. jpath y +if. sel + cnt=. +/ &> sel e. each <'/\' + ndx=. ind #~ msk *. cnt=1 + y=. (addfname each ndx { y) ndx } y + ndx=. ind #~ msk *. cnt > 0 + sel=. (<'~addons/') ,each (ndx{y) ,each <'.ijs' + smsk=. (1:@(1!:4) ::0:)@<@jpath &> sel + y=. (smsk#sel) (smsk#ndx) } y +end. +fullname each jpath each y +) +getpath=: ([: +./\. =&'/') # ] +recentmax=: 3 : '({.~ RecentMax <. #) ~.y' +recentfiles_add_j_=: 3 : 0 +RecentFiles_j_=: recentmax (@fboxname file);'%l';(":>:row) +try. + if. IFUNIX do. + if. x do. + 2!:1 cmd + else. + 2!:1 cmd, (0=nox+.(1 -.@e. 'term' E. editor)*.(1 e. '/vi' E. editor)+.'vi'-:2{.editor)#' &' + end. + else. + (x{0 _1) fork_jtask_ cmd + end. +catch. + msg=. '|Could not run the editor:',cmd,LF + msg=. msg,'|You can change the Editor definition in Edit|Configure|Base' + smoutput msg +end. +EMPTY +) +cocurrent 'z' +jpath=: jpath_j_ +load=: 3 : 0 +0 load y +: +fls=. getscripts_j_ y +fn=. ('script',x#'d')~ +for_fl. fls do. + if. Displayload_j_ do. smoutput > fl end. + if. -. fexist fl do. + smoutput 'not found: ',>fl + end. + fn fl + Loaded_j_=: ~. Loaded_j_,fl +end. +empty'' +) + +loadd=: 1&load +require=: 3 : 0 +fls=. Loaded_j_ -.~ getscripts_j_ y +if. # fls do. load fls else. empty'' end. +) +scripts=: scripts_j_ +show=: 3 : 0 +y=. y,(0=#y)#0 1 2 3 +if. (3!:0 y) e. 2 32 do. y=. cutopen y +else. y=. (4!:1 y) -. (,'y');,'y.' end. +wid=. {.wcsize'' +sub=. '.'&(I. @(e.&(9 10 12 13 127 254 255{a.))@]}) +j=. '((1<#$t)#(":$t),''$''),":,t' +j=. 'if. L. t=. ".y do. 5!:5 a) {.each a) ,each LF +) +xedit=: xedit_j_ +wcsize=: 3 : 0 +if. (-.IFGTK+.IFJHS) *. UNAME-:'Linux' do. + |.@".@(-.&LF)@(2!:0) :: (Cwh_j_"_) '/bin/stty size 2>/dev/null' +else. + Cwh_j_ +end. +) +coclass 'jcompare' + +MAXPFX=: 100 +MAXLCS=: *: MAXPFX +cin=: e. , +fmt0=: 'p<0 [>q<] >' & (8!:0) +fmt1=: 'p<1 [>q<] >' & (8!:0) +lcs=: * * 1 + >./\@:(_1&|.)@:(>./\"1@:(_1&|."1)) +mindx=: }.@{.@/:~@(+/"1 ,. ]) +remltws=: 3 : 0 +y=. y, LF +dat=. <;._2 y +msk=. CR = {: &> dat +dat=. (-msk) }. each dat +fn=. #~ ([: (+./\ *. +./\.) -.@(e.&(' ',TAB))) +dat=. fn each dat +dat=. dat ,each msk{'';CR +}: ; dat ,each LF +) +comp=: 4 : 0 + +sep=. ((LF cin x) +. LF cin y) { CRLF +if. 2=#$x do. x=. <@dtb"1 x +else. x=. <;._2 x,sep -. {:x end. +if. 2=#$y do. y=. <@dtb"1 y +else. y=. <;._2 y,sep -. {:y end. +if. x -: y do. 'no difference' return. end. +XY=: x,y +AX=: X=: XY i. x +AY=: Y=: XY i. y +NX=: i.#x +NY=: i.#y +SX=: SY=: '' +while. compend'' do. complcs'' end. +sx=. /:~ SX +sy=. /:~ SY +x=. (fmt0 sx) ,each (sx { AX) { XY +y=. (fmt1 sy) ,each (sy { AY) { XY +r=. (x,y) /: (sx,.0),sy,.1 +}: ; r ,each LF +) +fcomp=: 4 : 0 +'p j n'=. 3 {. x +'ifws ifsep'=. 2 2 #: j +'x y'=. _2 {. ,&p each cutopen y +if. L. n do. + 'nx ny'=. n +else. + nx=. x [ ny=. y +end. +f=. 1!:1 :: _1: +tx=. f x=. fboxname x +if. tx -: _1 do. 'unable to read ',nx return. end. +ty=. f y=. fboxname y +if. ty -: _1 do. 'unable to read ',ny return. end. +tx=. f2utf8 tx +ty=. f2utf8 ty +if. ifsep do. + tx=. toJ tx + ty=. toJ ty +end. +if. ifws do. + tx=. remltws tx + ty=. remltws ty +end. +f=. _3&{.@('0'&,@(":@])) +mth=. _3[\' JanFebMarAprMayJunJulAugSepOctNovDec' +'a m d h n s'=. 6{.1 pick dx=. ,1!:0 x +fx=. (4":d),' ',(m{mth),' ::' 0 3 6 9};f &.> 100|a,h,n,s +'a m d h n s'=. 6{.1 pick dy=. ,1!:0 y +fy=. (4":d),' ',(m{mth),' ::' 0 3 6 9};f &.> 100|a,h,n,s +'nx ny'=. <"1>nx;ny +r=. 'comparing:',LF +r=. r,nx,fx,' ',(":2 pick dx),LF +r=. r,ny,fy,' ',(":2 pick dy),LF +r,tx compare ty +) + +compend=: 3 : 0 +old=. 0 0 +len=. (#X),#Y + +while. -. len -: old do. + old=. len + t=. <./len + m=. 0 i.~ (t {. X) = t {. Y + X=: m }. X + Y=: m }. Y + t=. m - t + n=. - +/ *./\. (t {. X) = t {. Y + X=: n }. X + Y=: n }. Y + NX=: m }. n }. NX + NY=: m }. n }. NY + m=. X e. Y + if. 0 e. m do. + SX=: SX,(-.m)#NX + X=: m # X + NX=: m # NX + end. + m=. Y e. X + if. 0 e. m do. + SY=: SY,(-.m)#NY + Y=: m # Y + NY=: m # NY + end. + len=. (#X),#Y +end. +if. -. 0 e. len do. 1 return. end. +SX=: SX,NX +SY=: SY,NY +0 +) +complcs=: 3 : 0 +lx=. #X +ly=. #Y +if. MAXLCS < lx * ly do. + select. MAXPFX < lx,ly + case. 0 1 do. + ly=. <. MAXLCS % lx + case. 1 0 do. + lx=. <. MAXLCS % ly + case. do. + lx=. ly=. MAXPFX + end. +end. +a=. lx {. X +b=. ly {. Y +m=. ((b =/ a),.0),0 +cm=. lcs ^:_ m +len=. >./ ,cm +rc=. 1 + mindx ($cm) #: I. len = ,cm +cm=. , rc {. cm +msk=. (1+i.len) =/ cm +ndx=. <@I."1 msk +pos=. ; ( ndx) # i.len),.pos +pos=. /:~ pos +'ib ia'=. |: 2 }."1 (~:{."1 pos)#pos +n=. 1 + {: ia +SX=: SX,(<<;:'Outh Errh Inph Proh Thrh' + +STARTF_USESTDHANDLES=: 16b100 +STARTF_USESHOWWINDOW=: 1 +WAIT_TIMEOUT=: 258 +CREATE_NEW_CONSOLE=: 16b10 +DUPLICATE_SAME_ACCESS=: 2 + +cdk=: 1 : '(''kernel32 '',m)&cd' + +WaitForSingleObject=: 'WaitForSingleObject > i x i' cdk +CloseHandle=: 'CloseHandle > i x' cdk"0 +TerminateProcess=: 'TerminateProcess > i x i' cdk +ReadFile=: 'ReadFile > i x *c i *i x' cdk +WriteFile=: 'WriteFile > i x *c i *i x' cdk +GetCurrentProcess=: 'GetCurrentProcess > x' cdk + +DuplicateHandleF=: 'DuplicateHandle > i x x x *x i i i' cdk +CreatePipeF=: 'CreatePipe > i *x *x *c i' cdk +CreateProcessF=: 'CreateProcessW > i x *w x x i i x x *c *c' cdk + +DuplicateHandle=: 3 : 0 +p=. GetCurrentProcess '' +r=. DuplicateHandleF p;y;p;(h=.,_1);0;0;DUPLICATE_SAME_ACCESS +CloseHandle y +{.h +) + +NB. ========================================================= +NB. 'hRead hWrite'=. CreatePipe Inheritable=0 +NB. ... FileRead/FileWrite ... +NB. CloseHandle hRead,hWrite +NB. +NB. Inheritable: 0 none, 1 for read, 2 for write +CreatePipe=: 3 : 0 +'inh size'=. 2{.y,0 +sa=. szero SECURITYATTR +sa=. (sint #SECURITYATTR) 'Cbyt' sset SECURITYATTR sa +sa=. (sint *inh) 'Inhe' sset SECURITYATTR sa +r=. CreatePipeF (hRead=.,_1);(hWrite=.,_1);sa;size +hRead=. {. hRead +hWrite=. {. hWrite +if. 1=inh do. hRead=. DuplicateHandle hRead end. +if. 2=inh do. hWrite=. DuplicateHandle hWrite end. +hRead,hWrite +) + +NB. ========================================================= +NB. hProcess=. [hWriteOut[,hReadIn]] CreateProcess 'program agr1 agr2 ...' +NB. ... +NB. CloseHandle hProcess +CreateProcess=: 3 : 0 +'' CreateProcess y +: +'ow ir'=. 2{.x,0 +si=. szero STARTUPINFO +si=. (sint #STARTUPINFO) 'Cbyt' sset STARTUPINFO si +f=. inh=. 0 +if. +/ir,ow do. + inh=. 1 + f=. CREATE_NEW_CONSOLE + si=. (sint STARTF_USESTDHANDLES+STARTF_USESHOWWINDOW) 'Flag' sset STARTUPINFO si + if. ow do. + si=. (sptr ow) Outh sset STARTUPINFO si + si=. (sptr ow) Errh sset STARTUPINFO si + end. + if. ir do. si=. (sptr ir) Inph sset STARTUPINFO si end. +end. +pi=. szero PROCESSINFO +r=. CreateProcessF 0;(uucp y);0;0;inh; f;0;0;si;pi +if. 0=r do. 0 return. end. +ph=. ptr Proh sget PROCESSINFO pi +th=. ptr Thrh sget PROCESSINFO pi +CloseHandle th +ph +) + +NB. ========================================================= +NB. ph=. h CreateProcess 'program agr1 agr2 ...' +NB. ... +NB. Wait ph;5000 +NB. CloseHandle ph +Wait=: 3 : 0 +r=. WaitForSingleObject y +if. WAIT_TIMEOUT=r do. TerminateProcess (0 pick y);_1 end. +) + +NB. ========================================================= +NB. ph=. h CreateProcess 'program agr1 agr2 ...' +NB. ... +NB. r=. ReadAll h +NB. CloseHandle h,ph +ReadAll=: 3 : 0 +ret=. '' +str=. 4096#'z' +while. 1 do. + r=. ReadFile y;str;(#str);(len=.,_1);0 + len=. {.len + if. (0=r)+.0=len do. + 'ec es'=: cderx'' + if. -.ec e.0 109 do. ret=. _1 end. + break. + end. + ret=. ret,len{.str +end. +ret +) + +NB. ========================================================= +NB. ph=. hr,hw CreateProcess 'program agr1 agr2 ...' +NB. r=. WriteAll hw +NB. CloseHandle hw +NB. r=. ReadAll hr +NB. CloseHandle hr,ph +WriteAll=: 3 : 0 +: +while. #x do. + r=. WriteFile y;x;(#x);(len=.,_1);0 + len=. {. len + if. (0=r)+.0=len do. + 'ec es'=: cderx'' + if. -.ec e.0 109 do. ret=. _1 end. + break. + end. + x=. len}.x +end. +1 +) +NB. task main + +NB. ========================================================= +NB.*fork v run task and optionally wait for completion +NB. +NB. form: [timeout=0] fork cmdline +NB. +NB. timeout: 0 no wait, _1 infinite, >0 timeout +NB. cmdline: 'shortcmd arg1 arg2 ...' +NB. cmdline: '"command with space" arg1 ...' +NB. +NB. e.g. fork 'notepad.exe' +fork=: (3 : 0)`(2!:1)@.IFUNIX +0 fork y +: +ph=. CreateProcess y +if. x do. Wait ph;x end. +CloseHandle ph +empty'' +) + +NB. ========================================================= +NB.*spawn v [monad] get stdout of executed task +NB. +NB. form: stdout=. spawn cmdline +NB. +NB. stdout: _1 fail, '' or stdout stream value if success +NB. cmdline: 'shortcmd arg1 arg2 ...' +NB. cmdline: '"command with space" arg1 ...' +NB. +NB. e.g. spawn 'net users' + +NB.*spawn v [dyad] send stdin and get stdout of task +NB. +NB. form: stdout=. [stdin=''] spawn cmdline +NB. +NB. stdin: input to stream as stdin, '' no input +NB. +NB. e.g. 'i.3 4'spawn'jconsole' +spawn=: (3 : 0)`(2!:0@])@.IFUNIX +'' spawn y +: +'or ow'=. CreatePipe 1 +'ir iw'=. CreatePipe 2,#x +ph=. (ow,ir) CreateProcess y +CloseHandle ir +if. #x do. x WriteAll iw end. +CloseHandle iw +CloseHandle ow +r=. ReadAll or +CloseHandle or +CloseHandle ph +r +) + +NB. ========================================================= +NB.*shell v [monad] get stdout of shell command +NB. +NB. e.g. shell 'dir /b/s' + +NB.*shell v [dyad] send stdin and get stdout of shell command +NB. +NB. e.g. (shell 'dir /b/s') shell 'find ".dll"' +SHELL=: IFUNIX{::'cmd /c ';'' + +shell=: ''&$: : (spawn SHELL,]) + +NB. ========================================================= +NB.*launch v [monad] launch default application for parameter +NB. +NB. launch jpath'~system' NB. file manager +NB. launch jpath'~bin/installer.txt' NB. text editor +NB. launch 'http://jsoftware.com' NB. web browser + +3 : 0'' +LAUNCH=: ('gnome-open';'open';'start') {::~ ('Linux';'Darwin')i. 1 { ndx { SystemFolders_j_ + +NB. --------------------------------------------------------- +NB. following assumes Displayload is set in immex, then +NB. the profile loaded. No need for another ijx window +if. 0=4!:0<'Displayload_j_' do. + Displayload_j_=: 1 + boot=. 3 : ('0!:0 {. p }. jsx {. ARGV + +if. jsx<#ARGV do. + ARGVVERB_z_=: 3 : ((>:jsx)}.ARGV) NB. define in z + ARGVVERB__'' NB. run in base +end. + +EMPTY +) + +NB. ========================================================= +18!:4 <'base' NB. end in base diff --git a/j/system/util/configure.ijs b/j/system/util/configure.ijs new file mode 100644 --- /dev/null +++ b/j/system/util/configure.ijs @@ -0,0 +1,117 @@ +NB. configure + +cocurrent 'jcfg' +coinsert 'j' + +jdefs=: 0 : 0 +Browser +Browser_nox +DirTreeX +Format +EPSReader +PDFReader +RecentMax +XDiff +Tags +UserDict +Editor +Editor_nox +) + +cbname=: {.~ i.&' ' <. i.&'=' + +NB. ========================================================= +cpath=: 3 : 0 +if. -. '~' e. {.&> {:"1 y do. y return. end. +({."1 y),.jpath each {:"1 y +) + +NB. ========================================================= +cbread=: 3 : 0 +dat=. 'b' freads y +if. dat -: _1 do. return. end. +dat=. dat #~ (<'NB.') ~: 3 {. each dat +dat=. dat #~ '#' ~: {.&> dat +dat=. deb each dat +dat #~ 0 < #&> dat +) + +NB. ========================================================= +cbread1=: 3 : 0 +r=. cbread jpath '~config/',y +if. r -: _1 do. cbread jpath '~system/config/',y end. +) + +NB. ========================================================= +cbread2=: 3 : 0 +r0=. cbread jpath '~system/config/',y +if. r0 -: _1 do. r0=. <'' end. NB. avoid domain error +r1=. cbread jpath '~config/',y +if. (0=#r1) +. r1 -: _1 do. r0 return. end. +n0=. cbname each r0 +n1=. cbname each r1 +if. 0 = #n0 -. n1 do. r1 return. end. +new=. (-.n0 e. n1) # r0 +r=. LF2,'NB. ',(50#'='),LF,'NB. new configs',LF,;new,each LF +r fappends jpath '~config/',y +r1,new +) + +NB. ========================================================= +configbase=: 3 : 0 +Snapshots_j_=: 0 +0!:100 ;LF ,each cbread2 'base.cfg' +9!:3 DisplayForm +9!:7 BoxForm { Boxes +9!:17 BoxPos +9!:21 (2&^ ^: (<&_)) MemoryLimit +9!:37 Output +0!:100 ;(}:,'_j_=:',]) each <;.2 jdefs +EMPTY +) + +NB. ========================================================= +configfolders=: 3 : 0 +UserFolders_j_=: i.0 2 +if. IFWIN do. + BINPATH_z_=: filecase BINPATH_z_ + sf=. filecase each {:"1 SystemFolders_j_ + SystemFolders_j_=: ({."1 SystemFolders_j_),.sf +end. +dat=. cbread1 'folders.cfg' +if. (0=#dat) +. dat -: _1 do. return. end. +ndx=. dat i.&> ' ' +ids=. ndx {.each dat +pts=. jpath each filecase each (ndx+1) }. each dat +uf=. ids,.pts +msk=. (=tolower) {.&>ids +SystemFolders_j_=: SystemFolders,msk#uf +UserFolders_j_=: (-.msk)#uf +SystemFolders_j_=: cpath SystemFolders_j_ +UserFolders_j_=: cpath UserFolders_j_ +EMPTY +) + +NB. ========================================================= +configrecent=: 3 : 0 +Folder=: RecentDirmatch=: RecentFif=: RecentFiles=: RecentProjects=: '' +0!:0 ::] < jpath '~config/recent.dat' +Folder_j_=: Folder #~ ( tofoldername each RecentProjects_j_ +EMPTY +) + +NB. ========================================================= +configrun=: 3 : 0 +configbase'' +configfolders'' +configrecent'' +coerase <'jcfg' +18!:4<'z' +) + +configrun$0 diff --git a/j/system/util/jadetag.ijs b/j/system/util/jadetag.ijs new file mode 100644 --- /dev/null +++ b/j/system/util/jadetag.ijs @@ -0,0 +1,10 @@ +NB. initialise system default ctag and define z locale names + +coclass 'jadetag' +coinsert 'ctag' + +Tags=: Tags_j_ +absolutepath=: 1 +cleartags'' +nms=. <;._1 ' cleartags loadtags ta tagcp tagopen tagselect' +". > nms ,each (<'_z_=:') ,each nms ,each (<'_jadetag_') diff --git a/j/system/util/pacman.ijs b/j/system/util/pacman.ijs new file mode 100644 --- /dev/null +++ b/j/system/util/pacman.ijs @@ -0,0 +1,899 @@ +cocurrent 'jpacman' +coinsert 'j' + +BASELIB=: 'base library' +DATAMASK=: 0 +HWNDP=: '' +ISGUI=: 0 +ONLINE=: 0 +PKGDATA=: 0 7$a: +SECTION=: ,<'All' +SYSNAME=: 'Package Manager' +TIMEOUT=: 60 +WWWREV=: REV=: _1 +3 : 0'' +nc=. '--no-cache' +if. IFUNIX do. + if. UNAME-:'Darwin' do. + HTTPCMD=: 'curl -o %O --stderr %L -f -s -S %U' + else. + try. nc=. nc #~ 1 e. nc E. shell 'wget --help' catch. nc=. '' end. + HTTPCMD=: 'wget ',nc,' -O %O -o %L -t %t %U' + end. +else. + exe=. '"',(jpath '~tools/ftp/wget.exe'),'"' + try. nc=. nc #~ 1 e. nc E. shell exe,' --help' catch. nc=. '' end. + HTTPCMD=: exe,' ',nc,' -O %O -o %L -t %t -T %T %U' + UNZIP=: '"',(jpath '~tools/zip/unzip.exe'),'" -o -C ' +end. +) +setfiles=: 3 : 0 +ADDCFG=: jpath '~addons/config/' +makedir ADDCFG +ADDCFGIJS=: ADDCFG,'config.ijs' +JRELEASE=: ({.~i.&'/') 9!:14'' +LIBTREE=: readtree'' +WWW=: 'http://www.jsoftware.com/jal/',JRELEASE,'/' +LIBVER=: jpath '~system/config/version.txt' +) +destroy=: codestroy +CFGFILES=: <;._2 (0 : 0) +addons.txt +library.txt +release.txt +revision.txt +zips.txt +) +LIBDESC=: 0 : 0 +This is the base library of scripts and labs included in the J system. + +Reinstalling or upgrading this library will overwrite files in the system subdirectory. Restart J afterwards. + +Files outside the system subdirectory, such as profile.ijs, are not changed. +) +cutjal=: ([: (* 4 > +/\) ' ' = ]) <;._1 ] +cutjsp=: ([: (* 5 > +/\) ' ' = ]) <;._1 ] +dquote=: '"'&, @ (,&'"') +fname=: #~ ([: *./\. ~:&'/') +hostcmd=: [: 2!:0 '(' , ] , ' || true)'"_ +ischar=: 2 = 3!:0 +rnd=: [ * [: <. 0.5 + %~ +sep2under=: '/' & (I.@('_' = ])}) +termLF=: , (0 < #) # LF -. {: +todel=: ; @: (DEL&, @ (,&(DEL,' ')) each) +tolist=: }. @ ; @: (LF&,@,@":each) +getintro=: ('...' ,~ -&3@[ {. ])^:(<#) +info=: smoutput +getnames=: 3 : 0 + select. L.y + case. 0 do. + if. +/ BASELIB E. y do. + y=. ({:"1 y + y=. (45&getintro &.> idx{y) idx}y +) +deltree=: 3 : 0 + try. + res=. 0< ferase {."1 dirtree y + *./ res,0 #y do. i.0 5 return. end. +m=. _2 |. (LF,')',LF) E. y +r=. _2 }. each m <;._2 y +x=. r i.&> LF +d=. (x+1) }.each r +r=. x {.each r +r=. 3 {."1 cutjal &> ' ' ,each r +x=. d i.&> LF +c=. x {.each d +d=. (x+1) }.each d +r,.c,.d +) +fixjal2=: 3 : 0 +if. 2 > #y do. i.0 2 return. end. +cutjal &> ' ' ,each <;._2 y +) +fixjsp=: 3 : 0 +if. 2 > #y do. i.0 5 return. end. +m=. _2 |. (LF,')',LF) E. y +r=. _2 }. each m <;._2 y +x=. r i.&> LF +d=. (x+1) }.each r +r=. x {.each r +r=. ' ' ,each r +(cutjsp &> r),.d +) +fixlib=: 3 : 0 +msk=. ( #y do. + i.0 6 return. +end. +fls=. <;._2 y +ndx=. fls i.&> ' ' +siz=. <&> 0 ". (ndx+1) }.&> fls +fls=. ndx {.each fls +zps=. <;._2 &> fls ,each '_' +pfm=. 3 {"1 zps +msk=. IFUNIX ~: (1 e. 'win'&E.) &> pfm +msk # zps,.fls,.siz +) +fixrev=: 3 : 0 +{. _1 ". :: _1: y -. CRLF +) +fixupd=: 3 : 0 +_1 ". :: _1: y -. CRLF +) +fixver=: 3 : 0 +if. ischar y do. + y=. y -. CRLF + y=. 0 ". ' ' (I. y='.') } y +end. +3 {. y +) +fixvers=: 3 : 0 +s=. $y +y=. ,y +3 {."1 [ 0 ". s $ ' ' (I. y e. './') } y +) +fmtjal=: 3 : 0 +if. 0 = #y do. '' return. end. +r=. (4 {."1 y) ,each "1 ' ',LF2 +r=. <@; "1 r +; r ,each ({:"1 y) ,each <')',LF +) +fmtjal2=: 3 : 0 +if. 0 = #y do. '' return. end. +; (2 {."1 y) ,each "1 ' ',LF +) +fmtdep=: 3 : 0 +}. ; ',' ,each a: -.~ <;._2 y +) +fmtjsp=: 3 : 0 +if. 0 = #y do. '' return. end. +r=. (4 {."1 y) ,each "1 ' ',LF +r=. <@; "1 r +; r ,each ({:"1 y) ,each <')',LF +) +fmtlib=: 3 : 0 +, 'q<.>,q<.>r<0>3.0,r<0>3.0' 8!:2 y +) +fmtver=: 3 : 0 +if. 0=#y do. '' return. end. +if. ischar y do. y return. end. +}. ; '.' ,each ": each y +) +fmtverlib=: 3 : 0 +fmtver y +) +fixzips=: 3 : 0 +if. 2 > #y do. i.0 5 return. end. +fls=. <;._2 y +ndx=. fls i.&> ' ' +siz=. 0 ". (ndx+1) }.&> fls +fls=. ndx {.each fls +zps=. <;._2 &> fls ,each '_' +zps=. zps,.fls,.<&>siz +pfm=. 3 {"1 zps +lnx=. (1 e. 'linux'&E.) &> pfm +mac=. (1 e. 'darwin'&E.) &> pfm +win=. mac < (1 e. 'win'&E.) &> pfm + +select. UNAME +case. 'Win' do. + zps=. win # zps +case. 'Linux' do. + zps=. lnx # zps +case. 'Darwin' do. + zps=. (lnx +. mac) # zps + zps=. zps /: 3 {"1 zps + zps=. (~: 3 {."1 zps) # zps +end. + +bit=. IF64 pick '64';'32' +pfm=. 3 {"1 zps +exc=. (1 e. bit&E.) &> pfm +zps=. zps \: exc +zps=. (~: 3 {."1 zps) # zps +fnm=. 0 {"1 zps +lnm=. 1 {"1 zps +ver=. 2 {"1 zps +pfm=. 3 {"1 zps +fls=. 4 {"1 zps +siz=. 5 {"1 zps +nms=. fnm ,each '/' ,each lnm +pfm=. (pfm i.&> '.') {.each pfm +ndx=. \: # &> pfm +sort ndx { nms,.pfm,.ver,.fls,.siz +) +fwritenew=: 4 : 0 +if. x -: fread y do. + 0 +else. + x fwrite y +end. +) +platformparent=: 3 : 0 +((< _2 {. y) e. '32';'64') # _2 }. y +) +makedir=: 1!:5 :: 0: @ < +plural=: 4 : 0 +y,(1=x)#'s' +) +sizefmt=: 3 : 0 +select. +/ y >: 1e3 1e4 1e6 1e7 1e9 +case. 0 do. + (": y), ' byte',(y~:1)#'s' +case. 1 do. + (": 0.1 rnd y%1e3),' KB' +case. 2 do. + (": 1 rnd y%1e3),' KB' +case. 3 do. + (": 0.1 rnd y%1e6),' MB' +case. 4 do. + (": 1 rnd y%1e6),' MB' +case. do. + (": 0.1 rnd y%1e9),' GB' +end. +) +shellcmd=: 3 : 0 +if. IFUNIX do. + hostcmd y +else. + spawn_jtask_ y +end. +) +subdir=: 3 : 0 +if. 0=#y do. '' return. end. +a=. 1!:0 y,'*' +if. 0=#a do. '' return. end. +a=. a #~ '-d' -:"1 [ 1 4 {"1 > 4 {"1 a +(: 0 do. + ONLINE=: 0 + log 'Using local copy of catalog. See Preferences to change the setting.' + 1 return. + end. + if. 0 = getonline 'Read Catalog from Server';CHECKREADSVR do. 0 return. end. +case. 1 do. + ONLINE=: 1 +case. 2 do. + if. REV >: 0 do. + if. 0 = getonline 'Read Catalog from Server';CHECKASK do. + log 'Using local copy of catalog. See Preferences to change the setting.' + 1 return. + end. + else. + if. 0 = getonline 'Setup Repository';CHECKSTARTUP do. 0 return. end. + end. +end. +log 'Updating server catalog...' +if. 0 = getserver'' do. + ONLINE=: 0 + log 'Working offline using local copy of catalog.' +else. + log 'Done.' +end. +1 +) +checkstatus=: 3 : 0 +if. 0 e. #LIBS do. '' return. end. +msk=. masklib PKGDATA +ups=. pkgups'' +libupm=. 1 e. msk *. ups +msk=. -. msk +addnim=. +/msk *. pkgnew'' +addupm=. +/msk *. pkgups'' +tot=. +/addnim,addupm,libupm +if. 0 = tot do. + 'All available packages are installed and up to date.' return. +end. +select. 0 < addnim,addupm +case. 0 0 do. + msg=. 'Addons are up to date.' +case. 0 1 do. + msg=. 'All addons are installed, ',(":addupm), ' can be updated.' +case. 1 0 do. + if. addnim = <:#PKGDATA do. + msg=. 'No addons are installed.' + else. + j=. ' addon',('s'#~1: fsize p do. + if. _1-:msg=. freads q do. + if. 0=#msg=. e do. msg=. 'Unexpected error' end. end. + log 'Connection failed: ',msg + info 'Connection failed:',LF2,msg + r=. 1;msg + ferase p;q +else. + r=. 0;p + ferase q +end. +r +) +httpgetr=: 3 : 0 +res=. httpget y +if. 0 = 0 pick res do. + f=. 1 pick res + txt=. freads f + ferase f + 0;txt +end. +) +install=: 3 : 0 +dat=. y +'num siz'=. pmview_applycounts dat +many=. 1 < num +msg=. 'Installing ',(":num),' package',many#'s' +msg=. msg,' of ',(many#'total '),'size ',sizefmt siz +log msg +installdo 1 {"1 dat +log 'Done.' +readlocal'' +pacman_init 0 +) +install_console=: 3 : 0 + if. -. init_console 'server' do. '' return. end. + pkgs=. getnames y + if. pkgs -: ,<'all' do. pkgs=. 1 {"1 PKGDATA end. + pkgs=. pkgs (e. # [) ((pkgnew +. pkgups) # 1&{"1@]) PKGDATA + if. 0 = num=. #pkgs do. '' return. end. + many=. 1 < num + msg=. 'Installing ',(":num),' package',many#'s' + log msg + installdo pkgs + log 'Done.' + readlocal'' + pacman_init '' + checkstatus'' +) +upgrade_console=: 3 : 0 + if. -. init_console 'read' do. '' return. end. + pkgs=. getnames y + if. (0=#pkgs) +. pkgs -: ,<'all' do. pkgs=. 1{"1 PKGDATA end. + pkgs=. pkgs (e. # [) (pkgups # 1&{"1@])PKGDATA + install_console pkgs +) +installdo=: 3 : 0 +msk=. -. y e. :fsize jpath'~addons/',y,'/manifest.ijs' do. + log 'Extraction failed: ',msg + info 'Extraction failed:',LF2,msg + return. +end. +install_addins y +install_config y +) +install_addins=: 3 :0 +fl=. ADDCFG,'addins.txt' +ins=. fixjal2 freads fl +ins=. ins #~ ( txt +msk=. fexist &> ( msk # 1 {"1 PKGDATA) ,. res + res=. (2#LF) joinstring (70&foldtext)&.> res + end. + case. 'showinstalled' do. + res=. (-.@pkgnew # 1 2 3 4&{"1@])PKGDATA + res=. curtailcaption res + case. 'shownotinstalled' do. + res=. (pkgnew # 1 3 4&{"1@])PKGDATA + res=. curtailcaption res + case. 'showupgrade' do. + res=. (pkgups # 1 2 3 4&{"1@])PKGDATA + res=. curtailcaption res + case. 'status' do. + res=. checklastupdate'' + res=. res,LF,checkstatus'' + end. + res +) +showfiles_console=: 4 : 0 + if. -. init_console 'read' do. '' return. end. + pkgs=. getnames y + pkgs=. pkgs (e. # [) (-.@pkgnew # 1&{"1@]) PKGDATA + pkgs=. pkgs -. (pkgs) ,&.> <'/',x,(x-:'history'){::'.ijs';'.txt' + res=. res #~ msk=. (<_1) ~: res=. fread@jpath &.> fn + if. #res do. + res=. ,((<'== '), &.> msk#pkgs) ,. res + res=. (2#LF) joinstring res + end. +) +remove_console=: 3 : 0 + if. -. init_console 'edit' do. '' return. end. + pkgs=. getnames y + if. pkgs -: ,<'all' do. pkgs=. 1 {"1 PKGDATA end. + pkgs=. pkgs (e. # [) (-.@pkgnew # 1&{"1@]) PKGDATA + pkgs=. pkgs -. . fixver freads LIBVER +) +readlocal=: 3 : 0 +readlin'' +ADDONS=: fixjal freads ADDCFG,'addons.txt' +ADDINS=: fixjal2 freads ADDCFG,'addins.txt' +REV=: fixrev freads ADDCFG,'revision.txt' +LASTUPD=: fixupd freads ADDCFG,'lastupdate.txt' +LIBS=: fixlibs freads ADDCFG,'library.txt' +LIB=: fixlib LIBS +ZIPS=: fixzips freads ADDCFG,'zips.txt' +EMPTY +) +readtree=: 3 : 0 +f=. ADDCFG,'tree.txt' +tree=. LF -.~ freads f +if. -. (d),'manifest.ijs' + if. mft -: _1 do. continue. end. + VERSION=: '' + 0!:100 mft + ver=. fmtver fixver VERSION + n=. }: (#p) }. >d + n=. '/' (I.n='\') } n + r=. r,n,' ',ver,LF + s=. s,d +end. +r fwritenew f +s=. (#p) }.each }: each s +install_labs each s +write_config'' +) +refreshjal=: 3 : 0 +'rc p'=. httpget WWW,zipext 'jal' +if. rc do. 0 return. end. +unzip p;ADDCFG +ferase p +if. *./ CFGFILES e. {."1 [ 1!:0 ADDCFG,'*' do. 1 return. end. +msg=. 'Could not install the local repository catalog.' +log msg +info msg +0 +) +updatejal=: 3 : 0 + log 'Updating server catalog...' + if. -. init_console 'server' do. '' return. end. + refreshaddins'' + readlocal'' + pacman_init'' + res=. checklastupdate'' + res,LF,checkstatus'' +) +RELIBMSG=: 0 : 0 +You are now using the XX base library, and can switch to the YY base library. + +This will download the YY version of the base library and overwrite existing files. Addons are not affected. + +OK to switch to the YY library? +) +prelib=: 3 : 0 +old=. LIBTREE +new=. (('stable';'current') i. 2 {"1 PKGDATA +srv=. fixvers > 3 {"1 PKGDATA +{."1 /:"2 srv ,:"1 loc +) +pkgnew=: 3 : 0 +0 = # &> 2 {"1 PKGDATA +) +pkgups=: 3 : 0 +(pkgnew'') < pkglater'' +) +pkgsearch=: 3 : 0 + +./"1 +./ y E."1&>"(0 _) 1{"1 PKGDATA +) +pkgshow=: 3 : 0 + y e.~ 1{"1 PKGDATA +) +setshowall=: 3 : 0 +PKGDATA=: ( '/') {.each nms +SECTION=: 'All';nms +DATAMASK=: (#PKGDATA) $ 1 +EMPTY +) +init_console=: 3 : 0 + if. 0=#y do. y=. 'read' end. + select. y + fcase. 'edit';'server' do. + if. -. checkaccess'' do. 0 return. end. + case. 'read' do. + readconfig'' + if. -. checkaddonsdir'' do. 0 return. end. + setfiles'' + readlocal'' + pacman_init '' + res=. 1 + case. do. res=. 0 + end. + if. y -: 'server' do. res=. getserver'' end. + res +) +jpkg=: 4 : 0 + select. x + case. 'history';'manifest' do. + x showfiles_console y + case. 'install' do. + install_console y + case. 'reinstall' do. + remove_console y + install_console y + case. 'remove' do. + remove_console y + case. ;:'show search showinstalled shownotinstalled showupgrade status' do. + x show_console y + case. 'update' do. + updatejal '' + case. 'upgrade' do. + upgrade_console y + case. do. + msg=. 'Valid options are:',LF + msg=. msg,' history, install, manifest, remove, reinstall, show, search,',LF + msg=. msg,' showinstalled, shownotinstalled, showupgrade, status,',LF + msg,' update, upgrade' + end. +) +jpkg_z_=: 3 : 0 + 'help' jpkg y + : + a=. conew 'jpacman' + res=. x jpkg__a y + destroy__a'' + res +) diff --git a/j/system/util/pm.ijs b/j/system/util/pm.ijs new file mode 100644 --- /dev/null +++ b/j/system/util/pm.ijs @@ -0,0 +1,860 @@ +coclass 'jpm' + +SIZE=: 1e7 +SCREENGLOBALS=: 0 +unpack=: 6!:11 +counter=: 6!:12 +stats=: 6!:13 +start=: 3 : 0 +'' start y +: +reset'' +x=. 2 {. x, (#x) }. 1 0 +if. (0 < #y) *: 2 = 3!:0 y do. + y=. ({. y, SIZE) $ ' ' +end. +([ [: (6!:12) 1:) x 6!:10 y +) +stop=: 6!:10 bind ($0) +reset=: 3 : 0 +4!:55 <'PMTESTDATA' +PM=: $0 +PMREAD=: 0 +PMENCODE=: PMDECODE=: PMSTATS=: $0 +PMNDX=: PMLINES=: PMSPACE=: PMTIME=: $0 +PMNAMES=: PMLOCALES=: '' +) + +reset'' +boxopencols=: ]`(<"1)@.(L. = 0:) +bracket=: ('['"_ , ": , '] '"_) each +dab=: -. & ' ' +firstones=: > (0: , }:) +groupndx=: 4 : '<: (#x) }. (+/\r<#x) /: r=. /: x,y' +info=: wdinfo @ ('Performance Monitor'&;) +lastones=: > (}. , 0:) +maskdef=: [: * [: +/\ _1&= - 0: , }:@:(_2&=) +nolocale=: (i.&'_') {. ] +sort=: /:~ :/: +takeafter=: [: ] (#@[ + E. i. 1:) }. ] +taketo=: [: ] (E. i. 1:) {. ] +takewid=: ] ` ((WID&{.) , '...'"_) @. (WID"_ < #) +unwords=: ;: inverse +usage=: [: +/\ (- 0: , }:) +join=: ,.&.>/ +colsum=: 4 : 0 +nub=. ~. key=. x{"1 y +nub /:~ nub x}"_1 1 key +//. y +) +getmatchindex=: 4 : 0 +bgn=. x +end=. y +level=. +/\ bgn - 0 , }: end +bpos=. I. bgn +blvl=. bpos { level +epos=. I. end +elvl=. epos { level +max=. 1 + #end +bndx=. max #. blvl ,. bpos +endx=. max #. elvl ,. epos +mtch=. bndx groupndx endx +bpos ; (/: mtch { /: bndx) { epos +) +getpm1=: 3 : 0 +'nam loc'=. splitname y +nms=. _1 pick PM +nmx=. nms i. dat +dat=. ": &.> <. | dat +msk=. (-w){.(|. w$1j1 1 1),3$1 +exp=. #!.','~ ({.&msk)@-@# +dat=. exp &.> dat +dat=. (neg{'';'-'),&.>,dat +p=. - >./ # &> dat +p {. &> dat +) +ffmt=: 4 : 0 +n=. ifmt 0 | y +if. x do. + n ,. }."1 (j. x) ": ,. 1 || y +end. +) +SCALE=: 1 1 + +timeformat=: 6 & ffmt +TIMETEXT=: ' Time (seconds)' + +spaceformat=: ifmt +SPACETEXT=: ' Space (bytes)' +getdetail=: 4 : 0 + +'type val'=. x +'name loc gvn'=. y + +rep=. (val+1) linerep {."1 rep +if. lno -: _1 do. + dat ; vid, ' ', 2 pick , rep return. +end. +replno=. _1 , > {."1 rep +repsno=. _1 ; 1 {"1 rep +reptxt=. 2 {"1 rep +len=. # &> repsno +stm=. {."1 dat +lns=. sort (len # replno) {~ (; repsno) i. stm +rep=. 3 {"1 dat +rep=. rep * stm e. {.&> repsno + +val=. (1 2 {"1 dat),. rep +key=. ~. lns +val=. key ,. lns +/ /. val + +val=. replno ,. }."1 (replno e. {."1 val) expand val +val=. val , 1e8, (1 2{+/val), (<0 3){ val + +txt=. (bracket }.replno) ,each reptxt +txt=. vid ; txt , <'total ',vid + +val ; : mend i: 1 +case. _1 do. + bnx=. mbgn i. 1 + enx=. >: (+/\mend) i. nbgn +case. 1 do. + bnx=. (+/\mbgn) i. nbgn - nend + enx=. >: mend i: 1 +end. + +ndx=. PMNDX +lns=. PMLINES +val=. (x pick 'PMTIME';'PMSPACE')~ +if. enx ~: #ndx do. + ndx=. enx {. ndx + lns=. enx {. lns + val=. enx {. val + mbgn=. enx {. mbgn + mend=. enx {. mend +end. + +if. bnx do. + ndx=. bnx }. ndx + lns=. bnx }. lns + val=. bnx }. val + mbgn=. bnx }. mbgn + mend=. bnx }. mend +end. + +msk=. 0 < mbgn usage mend + +if. 0 e. msk do. + ndx=. msk # ndx + lns=. msk # lns + val=. msk # val + mbgn=. msk # mbgn + mend=. msk # mend +end. + +lvl=. mbgn usage mend +if. 1 +. 2 e. lvl do. + rep=. getreps ind;ndx;lns;val + her=. gethdetail ind;ndx;lns;val + tot=. gettdetail ind;ndx;lns;val + + lns=. {."1 rep + assert lns -: {."1 her + assert lns -: {."1 tot + res=. lns ,. ({:"1 tot) ,. ({:"1 her) ,. {:"1 rep +else. + res=. getdetail3 ind;ndx;lns;val +end. +if. 1 ~: scale=. x { SCALE do. + res=. res *"1 [ 1,scale,scale,1 +end. + +) +getdetail3=: 3 : 0 +'ind ndx lns val'=. y +tmsk=. ndx = ind + +tlns=. tmsk # lns +tval=. tmsk # val + +msk=. tlns ~: _2 +tall=. msk # (}.tval,0) - tval +tlns=. msk # tlns +f=. 0:`({: - {.) @. (0: < #) +toff=. msk # tmsk f;._1 val +ther=. tall - toff + +0 colsum tlns,. tall,. ther ,. 1 +) +gethdetail=: 3 : 0 + +'ind ndx lns val'=. y + +all=. (}.val,0) - val +bgn=. lns = _1 +end=. lns = _2 +hit=. ind = ndx +msk=. 1 < bgn usage end +her=. 2 >: bgn usage end +bgn=. msk *. bgn +end=. msk *. end + +'bdx edx'=. bgn getmatchindex end +clr=. <: bdx + +hndx=. ind (I. her) } ndx +hlns=. her } lns ,: (#;.1 hit) # hit # lns +sel=. ind = clr { hndx +clr=. sel # clr +edx=. sel # edx +lns=. (clr{hlns) edx} lns + +msk=. 1 edx} ndx = ind +msk=. msk *. lns ~: _2 +0 colsum msk # lns ,. all +) +gettdetail=: 3 : 0 + +'ind ndx lns val'=. y + +bgn=. lns = _1 +end=. lns = _2 +all=. (}.val,0) - val +j=. (ndx=ind) <;.1 lns +lns=. (# &> j) # {. &> j +lvl=. +/\ bgn - 0, }:end +msk=. 1 < lvl +bnb=. msk *. bgn +enb=. msk *. end +'bdx edx'=. bnb getmatchindex enb +clr=. <: bdx +lns=. (clr{lns) edx} lns + +msk=. lns ~: _2 +0 colsum msk # lns ,. all +) +getreps=: 3 : 0 +'ind ndx lns val'=. y +msk=. (ndx=ind) *. lns ~: _2 +0 colsum (msk # lns) ,. 1 +) +maskit=: 4 : 0 + +bgn=. x +end=. y +sb=. +/\bgn +se=. +/\end +re=. +/\ inverse se + 0 <. <./\sb - se +mskbgn=. 0 < +/\ bgn - 0,}:re +sb=. +/\.bgn +se=. +/\.end +rb=. +/\. inverse sb + 0 <. <./\.se - sb +mskend=. 0 < +/\. end - }.rb,0 + +mskbgn *. mskend +) +f=. '_'"_ = {: +g=. ;&a: +h=. (i:&'_') ({.;}.@}.) ] +k=. [: h }: +splitname=: g`k @. f f. +fullname=: 3 : 0 +'name loc'=. 2 {. boxopen y +if. '_' ~: {:name do. name,'_',loc,'_' else. name end. +) +getnames=: 4 : 0 + +'nms lcs j'=. |: PMDECODE #: x +xjp=. lcs ~: PMLOCALES i. <'jpm' + +if. 0=#y do. xjp return. end. + +y=. ;: y +sns=. splitname &> y +ndx=. y i. <,'~' +rin=. 1 getnames1 x;nms;lcs; rot +) +getnames1=: 4 : 0 + +'ndx nms lcs sel'=. y + +if. 0=#sel do. (#ndx)#x return. end. + +nmx=. PMNAMES i. {."1 sel +lcx=. PMLOCALES i. {:"1 sel + +msk=. (#ndx) # 0 + +len=. #. (0: < #) &> sel +if. 1 e. b=. len=1 do. + msk=. msk +. lcs e. b#lcx +end. +if. 1 e. b=. len=2 do. + msk=. msk +. nms e. b#nmx +end. +if. 1 e. b=. len=3 do. + msk=. msk +. (lcs e. b#lcx) *. nms e. b#nmx +end. +) + +getshortname=: 3 : 0 +'name loc'=. 2 {. boxopen y +if. #loc=. loc -. ' ' do. + ((name i.'_') {. name),'_',loc,'_' +else. + name +end. +) +getnameloc=: 3 : 0 + +y=. dab y + +if. 0 = #y do. + '';'base';'' return. +end. + +if. L. y do. + select. #y + case. 1 do. + name=. dab > y + loc=. 'base' + given=. name + case. 2 do. + 'name loc'=. dab each y + if. #loc do. + given=. name,'_',loc,'_' + else. + given=. name + loc=. 'base' + end. + case. do. + 'invalid name' assert 0 + end. + +else. + + given=. y + 'name loc'=. dab each splitname y + if. 0=#loc do. loc=. 'base' end. + +end. + + +name;loc;given +) +read=: 3 : 0 +if. PMREAD do. 1 return. end. +if. 0 = +/ 6!:13'' do. + smoutput 'There are no PM records' + 0 return. +end. + +PMTIME=: 6!:11 '' +PMSTATS=: 6!:13 '' +6!:10 '' +PM=: PMTIME +locndx=. (1;0) {:: PMTIME +PMNAMES=: 6 pick PMTIME +PMLOCALES=: locndx }. PMNAMES +PMNAMES=: locndx {. PMNAMES +PMNDX=: > 3 {. PMTIME +ndx=. I. (1: e. '__'&E.) &> PMNAMES + +if. #ndx do. + nms=. (('__'&E. i. 1:) {. ]) each ndx { PMNAMES + ndx merge nms +end. +ndx=. I. ('_'"_ = {:) &> PMNAMES + +if. #ndx do. + namx=. 0 { PMNDX + locx=. 1 { PMNDX + nms=. }: each ndx { PMNAMES + ind=. i:&'_' &> nms + loc=. (>: ind) }.each nms + loc=. (<'base') (I. 0=# &> loc) } loc + nms=. ind {.each nms + lcs=. (namx i. ndx) { locx + assert loc -: (lcs-locndx) { PMLOCALES + + ndx merge nms +end. +ind=. (0 { PMNDX) { PMNAMES i. PMNAMES +PMNDX=: ind 0 } PMNDX +PMLINES=: 3 pick PMTIME +PMSPACE=: 0, +/\ }: 4 pick PMTIME +PMTIME=: 5 pick PMTIME +PMDECODE=: 0,(#PMLOCALES),2 +PMENCODE=: (2 * #PMLOCALES),2 1 +PMNDX=: +/ PMENCODE * PMNDX - 0,locndx,1 + +PMREAD=: 1 +) +merge=: 4 : 0 +ndx=. x +nms=. y +namx=. 0 { PMNDX +locx=. 1 { PMNDX +nmx=. PMNAMES i. nms +msk=. nmx < #PMNAMES + +if. 1 e. msk do. + plc=. (namx i. msk#nmx) { locx + rlc=. (namx i. msk#ndx) { locx + b=. plc=rlc + if. 1 e. b do. + inx=. b # I. msk + nwx=. ((inx{ndx), namx) i. namx + new=. nwx { (inx{nmx), namx + PMNDX=: new 0 } PMNDX + end. +end. + +PMNAMES=: nms ndx} PMNAMES +) +EXHDR=: '1234' ;&,&> ':' +linerep=: 4 : 0 +dat=. x (5!:7) y +if. #dat do. + stm=. ;{."1 dat + lns=. {: &> 1 {"1 dat + txt=. {:"1 dat + lno=. <&> ~. lns + sno=. lns showdetail1&y each x +) +showdetail1=: 4 : 0 +tit=. 'all';'here';'rep';{:y +top=. x pick TIMETEXT;SPACETEXT +'name loc given'=. y +res=. x showdetail2 y +if. 0 = L. res do. return. end. + +'mdat mtxt ddat dtxt tdat ttxt'=. res + +if. (#mdat) *. #ddat do. + txt=. mtxt ,each ' ' ,each dtxt ,each ' ' ,each ttxt +else. + txt=. mtxt ,each dtxt +end. + +top, , LF ,. ": tit ,: txt +) +showdetail2=: 4 : 0 +'name loc given'=. y + +'mdat mrep'=. (x,0) getdetail y +'ddat drep'=. (x,1) getdetail y + +if. 0 = (#mdat) + (#ddat) do. + 'not found: ',getshortname given return. +end. + +if. 0 e. (#mdat), (#ddat) do. + tdat=. 0, (1 2 { -: +/ mdat,ddat), {: +/ (1 {. mdat) , 1 {. ddat +else. + tdat=. 0 ; 2 }. x gettotal fullname y +end. + +trep=. <'total definition' +mtxt=. x showdetailfmt mdat; (#rep) {. boxxopen lns +(f all);(f here);(":,.rep); lns +) +detailoption=: 3 : '2 {. y , (#y) }. 0 0' +totaloption=: 3 : '3 {. y , (#y) }. 0 0 90' +showtotal=: 3 : 0 +0 showtotal y +: +if. 0=read '' do. i. 0 0 return. end. +opt=. totaloption x +'x s p'=. opt +if. -. x e. 0 1 do. + r=. 'first number in left argument should be either 0 (time)' + r,' or 1 (space)' return. +end. +if. -. s e. 0 1 do. + r=. 'second number in left argument should be either 0 (distinguish' + r,' names by locale) or 1 (total names over locales)' return. +end. +if. s do. + tit=. 'name (all locales)';'all';'here';'here%';'cum%';'rep' +else. + tit=. 'name';'locale';'all';'here';'here%';'cum%';'rep' +end. +dat=. x showtotalfmt opt showtotal1 y +if. s do. dat=. (<<<1) { dat end. +dat=. > each dat +txt=. tit ,: dat +t=. x pick TIMETEXT;SPACETEXT +t, ,LF ,. ": txt +) +showtotal1=: 4 : 0 +'t s p'=. x + +'nam loc all her rep'=. x gettotal y +if. 0 = #nam do. a: return. end. + +j=. her % +/her +pct=. 0.1 * <. 0.5 + 1000 * j +cpt=. <. 0.5 + 100 * +/\ j +if. t do. f=. spaceformat else. f=. timeformat end. + +nam=. nam, <'[total]' +loc=. loc, <'' +all=. all +her=. her, +/her +pct=. pct,100 +cpt=. cpt,100 +rep=. rep + +nam; loc; all; her; pct; cpt; rep +) +showtotalfmt=: 4 : 0 +'nam loc all her pct cpt rep'=. y + +if. x do. f=. spaceformat else. f=. timeformat end. + +all=. f all +her=. f her +pct=. 1 ffmt pct +cpt=. ":,.cpt +rep=. ":,.rep + +nam; loc; all; her; pct; cpt; rep +) +gettotal=: 4 : 0 + +if. 0=read'' do. a: return. end. + +'t s p'=. x +ndx=. PMNDX +lns=. PMLINES +if. t do. dat=. PMSPACE else. dat=. PMTIME end. +if. 0 e. lns do. + msk=. lns < 0 + dat=. msk # dat + ndx=. msk # ndx + lns=. msk # lns +end. +msk=. (lns = _1) maskit lns = _2 +if. 0 e. msk do. + dat=. msk # dat + ndx=. msk # ndx + lns=. msk # lns +end. + +if. 0 = #ndx do. a: return. end. +ndx=. ndx - 2 | ndx +nub=. ~. ndx + +rms=. nub getnames y +req=. rms#nub +'all her rep'=. t gettotals ndx;lns;dat;nub;rms + +'nx lx j'=. |: PMDECODE #: req +if. s do. + 'all her rep'=. |: nx +//. all,.her,.rep + nx=. ~. nx +end. +ndx=. \: her ,. all +her=. ndx{her +all=. ndx{all +if. p < 100 do. + len=. 1 + 1 i.~ (+/\her) >: (+/her) * p % 100 + curtailed=. len < #her + if. curtailed do. + curall=. +/ len }. all + curher=. +/ len }. her + her=. len {. her + all=. len {. all + ndx=. len {. ndx + end. +else. + curtailed=. 0 +end. + +rep=. ndx{rep +nam=. (ndx{nx) { PMNAMES + +if. s do. + loc=. (#nx) # a: +else. + loc=. (ndx{lx) { PMLOCALES +end. + +if. curtailed do. + her=. her, curher + loc=. loc, a: + nam=. nam, <'[rest]' +end. + +if. 1 ~: scale=. t { SCALE do. + all=. scale * all + her=. scale * her +end. +nam ; loc ; all ; her ; rep +) +gettotals=: 4 : 0 + +'ndx lns dat nub req'=. y + +bgn=. lns = _1 +end=. lns = _2 +f=. 1: = [: +/\ (- (0: , 1: - }:)) +msk=. f each ndx < /. bgn + +ada=. ndx < /. dat * _1 ^ bgn + +all=. msk +/@# &> ada +rep=. <. -: # &> ada +sbg=. }:bgn +snd=. sbg < }.end +dff=. (}. - }:) dat +str=. (bgn # ndx) ,. sbg # dff +edr=. ((0,snd) # ndx) ,. snd #dff +spc=. i.0 2 +level=. +/\ bgn - end +ups=. (1 1 E. bgn) > 1 1 0 0 E. bgn +if. 1 e. ups do. + + ulvl=. ups # level + upos=. I. ups + spd=. (0 1 E. bgn) *. level > 0 + slvl=. spd # level + spos=. I. spd + + if. #spos do. + + lmax=. 1 + ({:upos) >. {:spos + + uelp=. lmax #. ulvl ,. upos + ind=. /: uelp + uelp=. ind { uelp + uvrb=. ind { ups # ndx + + selp=. lmax #. slvl ,. spos + svrb=. (uelp groupndx selp) { uvrb + sdff=. spos { dff + spc=. svrb ,. sdff + end. + +end. +spcr=. i.0 2 +if. +./mrec=. (_2=PMLINES)*.PMNDX=1|.PMNDX do. + rdat=. >(>{.x){PMTIME;PMSPACE + mdif=. mrec # rdat-1|.rdat + spcr=. (mrec # PMNDX) ,.mdif + spcr=. ((0{"1 spcr)e.ndx) # spcr + spcr=. i.0 2 +end. +sum=. str , edr , spc , spcr +her=. (nub i. {."1 sum) +/ /. {:"1 sum + +if. x=0 do. + assert *./ all >: her +end. + +|: req # all ,. her ,. rep +) +JVDET=: 0 : 0 +pc jvdet; +xywh 0 0 200 200;cc dgrid isigraph rightmove bottommove; +pas 0 0;pmove 217 113 215 220; +rem form end; +) +destroy_jvdet=: 3 : 0 +wd'pclose' +destroy__dgrid'' +) +jvdet_cancel=: jvdet_close=: destroy_jvdet + +viewdetail=: 3 : 0 +require 'jzgrid' +0 viewdetail y +: +if. 0=read '' do. i. 0 0 return. end. +'DETSPACE DETEXPAND'=: opt=. detailoption x +y=. getnameloc y +sname=. getshortname 2 pick y +pn=. 'PM',(x pick TIMETEXT;SPACETEXT),' - ',sname + +res=. x showdetail2 y +if. 0 = L. res do. return. end. +'mdat mtxt ddat dtxt tdat ttxt'=. res +if. (#mdat) *. #ddat do. + txt=. mtxt ,each ' ' ,each dtxt ,each ' ' ,each ttxt + txt=. mtxt ,each dtxt ,each ttxt +else. + txt=. mtxt ,each dtxt +end. +data=: > join <"1 each txt + +if. wdisparent 'jvdet' do. + wd 'psel jvdet' +else. + wd JVDET + dgrid=: '' conew 'jzgrid' +end. + +hdr=. 'HDRCOL' ,&< 'All';'Here';'Rep';'Lines' +hdr=. hdr , ('CELLALIGN';2 2 2 0) ,: ('CELLEDIT';0) +show__dgrid hdr , ('GRIDID';'dgrid') , ('GRIDSORT' ; 1) ,: 'CELLDATA' ;< data +wd 'pn *Execution Details for ',sname +wdfit'' +wd 'pshow' +) +JVTOT=: 0 : 0 +pc jvtot; +xywh 0 0 200 200;cc tgrid isigraph rightmove bottommove; +pas 0 0; +rem form end; +) +tgrid_gridhandler=: 3 : 0 +select. y +case. 'dblclick' do. + if. 0 <: Row__tgrid do. + TOTSPACE viewdetail ( each 2 {. dat), 2 }. dat +dataraw=: |: <"1 &> ,.each ((-ftr)&}.) each dat +dat=. x showtotalfmt dat +data=: |: <"1 &> dat + +tgrid=: '' conew 'jzgrid' + +hdr=. 'HDRCOL' ,&< 'Name';'Locale';'All';'Here';'Here%';'Cum%';'Rep' +hdr=. hdr , ('CELLALIGN';0 0 2 2 2 2 2) ,: ('CELLEDIT';0) +show__tgrid hdr , ('GRIDID';'tgrid') , ('GRIDSORT' ; 1) ,: 'CELLDATA' ;< data +wd 'pn *',pn +wdfit'' +wd 'pshow' +) +getused=: 3 : 0 +if. 0=read '' do. i. 0 0 return. end. +'nms lcs j'=. |: PMDECODE #: ~. PMNDX +xjp=. lcs ~: PMLOCALES i. <'jpm' +sort xjp # (nms { PMNAMES) ,. lcs { PMLOCALES +) +getnotused=: 3 : 0 +loc=. 18!:1 [ 0 1 +r=. i.0 2 +for_lc. loc do. + r=. r, (nl__lc 1 2 3) ,. lc +end. +sort r -. getused'' +) diff --git a/j/system/util/pp.ijs b/j/system/util/pp.ijs new file mode 100644 --- /dev/null +++ b/j/system/util/pp.ijs @@ -0,0 +1,376 @@ +coclass 'jpp' +coinsert 'j' +j=. 'assert. break. case. catch. catchd. catcht. continue. do. else. elseif. end.' +CONTROLS=: ;: j,' fcase. for. if. return. select. try. while. whilst.' +CONTROLX=: 0 0 0 0 0 0 0 0 0 0 _1, 0 1 1 0 1 1 1 1 +CONTROLN=: ;: 'case. catch. catchd. catcht. do. else. elseif. end. fcase.' +CONTROLB=: ;: 'for. if. select. try. while. whilst.' +CONTROLM=: CONTROLN -. <'end.' + +FORMEND=: 'rem form end;';,')' +CONTS=: ';xywh';';cc';';cn' +adverbs=: '~ / \ /. \. } b. f. M. t. t:' + +arguments=: 'm n u v x y' + +t=. '= < <. <: > >. >: _: + +. +: * *. *: - -. -: % %. %: ^ ^.' +t=. t,' $ $. $: ~. ~: | |. |: , ,. ,: ; ;: # #. #: ! /: \: [ [: ]' +t=. t,' { {. {: {:: }. }: ". ": ? ?.' +t=. t,' A. c. C. e. E. i. i: I. j. L. o. p. p: q: r. s: u: x:' +t=. t,' _9: _8: _7: _6: _5: _4: _3: _2: _1:' +t=. t,' 0: 1: 2: 3: 4: 5: 6: 7: 8: 9:' +verbs=: t + +t=. '^: . .. .: : :. :: ;. !. !: " ` `: @ @. @: & &. &: &.:' +t=. t,' d. D. D: H. L: S: T.' +conjunctions=: t + +t=. 'assert. break. case. catch. catchd. catcht. continue. do.' +t=. t,' else. elseif. end. fcase. for. goto. if. label.' +t=. t,' return. select. throw. trap. try. while. whilst.' +control_words=: t + +nouns=: 'a. a:' + +j=. ;: adverbs,' ',verbs,' ',conjunctions,' ',control_words,' ',nouns +SystemDefs=: j,;:'=. =:' +EXPDEFINE=: <@;: ;._2 (0 : 0) +1 : 0 +2 : 0 +3 : 0 +4 : 0 +1 define +2 define +3 define +4 define +adverb : 0 +conjunction : 0 +verb : 0 +monad : 0 +dyad : 0 +adverb define +conjunction define +verb define +monad define +dyad define +) +NOUNDEFINE=: <@;: ;._2 '\' -.~ (0 : 0) +0 \: 0 +noun \: 0 +0 \define +noun \define +) +findfor=: 'for_'&-: @ (4&{.) *. ('.'&=) @ {: +info=: mbinfo @ ('Lint'&;) +lastones=: > (}. , 0:) +tolist=: }.@;@:(LF&,@,@":&.>) +findcontrols=: (1: e. (CONTS"_ (1: e. E.) &> <)) &> +firstones=: > (0 , }:) +maskselectside=: +./\ *. +./\. +notquotes=: (+: ~:/\)@(''''&=) +notcomments=: ([: +./\. (=&' ') +: [: +./\ 'NB.'&E. > ~:/\@(''''&=)) +notqc=: (notquotes *. notcomments) f. +debq=: #~ (+. 1: |. (> tok +end=. tok=<;:')' +end=. 2 }. ; (1 0,bgn) < @ ( tok + end=. nounmask < tok=<;:')' + if. bgn pairup end do. 0 return. end. +end. +lvl=. (+/\bgn) - +/\end +if. 2 e. lvl do. + lin=. (<:(bgn#lvl) i. 2) { I. bgn + msg=. lin pick y +elseif. 1 = {:lvl do. + lin=. 1 i.~ *./\.1 = lvl + msg=. 'Definition not completed' +elseif. 1 do. + lin=. lvl i. _1 + msg=. 'Unmatched closing paren' +end. +msg=. 'Could not match begin and end of multi-line definition:',LF,LF,msg +lin;msg +) +commentline=: 3 : 0 +line=. y +ndx=. (y e. ' ',TAB) i. 0 +if. -. 'NB. ' -: 4 {. ndx }. line do. + line return. +end. +pre=. ndx {. line +len=. 57 - +/ 1 + 3 * pre = TAB +if. (,'=') -: ~. (4+ndx) }. line do. + line=. pre,'NB. ',len#'=' +elseif. (,'-') -: ~. (4+ndx) }. line do. + line=. pre,'NB. ',len#'-' +end. +line +) +dellb=: #~ +./\ @: -. @ e.&(' ',TAB) +deltb=: #~ +./\.@: -. @ e.&(' ',TAB) +indent1=: 3 : 0 +tok=. y +x=. I. findfor &> tok +tok=. (<'for.') x} tok ++/ (CONTROLX,0) {~ CONTROLS i. tok +) +maskexps=: 3 : 0 +tok=. words @ (#~ notqc) each y +bgn=. maskexp1 &> tok +end=. tok=<;:')' +end=. 2 }. ; (1 0,bgn) < @ ( tok +if. -. 1 e. bgn do. return. end. +end=. tok = <;:')' +end=. 2 }. ; (1 0,bgn) < @ ( <,y do. 1 return. end. +if. (<'Note') ~: {.y do. 0 return. end. +if. -. (#y) e. 2 3 do. 0 return. end. +('NB.'-:3{.2 pick y,<'NB.') > (1{y) e. SystemDefs +) +maskselect=: 4 : 0 +msk=. x +in=. y +ndx=. msk i. 1 +if. ndx=#msk do. msk return. end. +in=. msk <;.1 in +(ndx#0) ,; maskselect1 each in +) + +maskselect1=: 0 , [: *./\ }. >: {. +pairup=: 4 : 0 +r=. +/\x - y +*./ (0={:r), r e. 0 1 +) +remspaces=: 3 : 0 +msk=. notcomments y +(debq msk#y), (-.msk)#y +) +spacing=: 3 : 0 +in=. 0 +bgn=. 0 +msk=. notcomments y +txt=. msk#y +com=. (-.msk)#y + +if. #txt do. + tok=. words txt + if. tok -: 0 do. return. end. + if. #tok do. + in=. indent1 tok + bgn=. ({.tok) e. CONTROLN + if. 1=#tok do. + txt=. ;tok + else. + txt=. spacing1 dlb txt + end. + else. + txt=. '' + end. +else. + com=. dlb com +end. + +in;bgn;<@:;:@(8&u:) :: 0: +f=. #~ (=&' ') *: 1: |. notquotes *. '=:'&E. +. '=.'&E. +noblankbefore=: f f. ^: _ + +f=. #~ 1: + [: j. (1: |. =&' ') < _1: |. notquotes *. '=:'&E. +. '=.'&E. +blankafter=: f f. ^: _ +spacing1=: blankafter @ noblankbefore +pp=: 3 : 0 +files=. boxxopen y +res=. (#files) $ 0 +for_f. files do. + s=. pp1 f + if. s = _1 do. return. end. + res=. s f_index } res +end. +res +) +pp1=: 3 : 0 +old=. freads y +dat=. pplint old +if. 0 = #dat do. 0 return. end. +if. L. dat do. + 'lin msg'=. dat + msg=. msg, ' in file:',LF,LF, > y + (0 >. lin - 10) flopen >y + if. lin do. + pos=. 1 0 + (+/\LF = toJ old) i. lin + 0 1 + smsetselect pos + end. + info msg + _1 return. +end. +if. dat -: old do. + 0 +else. + 1 [ dat fwrites y +end. +) +pplint=: 3 : 0 +dat=. ucp y + +'fmt wid rms exp sel'=. Format_j_ +if. wid=0 do. spc=. TAB else. spc=. wid#' ' end. +dat=. dat -. 26{a. +if. 0 = #dat do. return. end. +dat=. toJ dat +iftermLF=. LF = {:dat +dat=. <;._2 dat, iftermLF }. LF +dat=. deltb each dat +res=. checkmulti dat +if. L.res do. return. end. +nounx=. I. masknouns dat +nouns=. nounx { dat +dat=. a: nounx} dat +dat=. dellb each dat +if. rms do. + dat=. remspaces each dat +end. +indat=. spacing each dat +if. (<0) e. indat do. + lin=. indat i. <0 + txt=. lin pick dat + cnt=. +/'''' = txt {.~ ('NB.' E. txt) i. 1 + if. 2 | cnt do. + msg=. 'Mismatched quotes' + else. + msg=. 'Could not parse line' + end. + lin;msg + return. +end. + +'in begin dat'=. |: > indat +if. 0 ~: +/ in do. + ins=. +/\ in + if. _1 e. ins do. + lin=. ins i. _1 + msg=. 'Unmatched end of control block' + else. + msk=. (dat = <,')') *. ins > 0 + if. 1 e. msk do. + lin=. msk i. 1 + msg=. 'Unmatched start of control block' + else. + lin=. 0 + msg=. 'Mismatched control words' + end. + end. + lin;msg return. +end. +res=. ppval dat +if. -. res -: 0 do. return. end. +if. -. fmt do. '' return. end. +in=. +/\ in +ins=. _1 |. in +ins=. 0 >. ins - begin +cmt=. 'NB.'&-: @ (3&{.) +ins=. ins * -. cmt &> dat +dat=. ins (([ # spc"_),]) each dat +if. sel do. + msk=. (<'select.') = {. @ words &> dat + msk=. msk maskselect in + dat=. msk (([ # spc"_),]) each dat +end. +if. exp do. + msk=. (dat=<,')') < maskexps dat + dat=. msk (([ # spc"_),]) each dat +end. +dat=. commentline each dat +dat=. nouns nounx } dat +dat=. ; dat ,each LF +dat=. (- -.iftermLF) }. dat + +utf8 dat +) +ppval=: 3 : 0 +dat=. words each y +pos=. <: +/\ # &> dat +dat=. ; dat +bgn=. (dat e. CONTROLB) +. findfor &> dat +end=. dat = <'end.' +lvl=. +/\bgn-end +if. _1 e. lvl do. + lin=. pos I. lvl i. _1 + lin;'Unmatched control end' return. +end. +if. -. 0 = {: lvl do. + lin=. pos I. lvl i: 1 + lin;'Unmatched control begin' return. +end. +if. bgn = #dat do. 0 return. end. +while. max=. >./ lvl do. + b=. max = lvl + b1=. _1 |. b + ndx=. (,1+{:) I. b > +./\ b1 > b + res=. ppval1 ndx{dat + if. res -: 0 do. + dat=. (<'') ndx}dat + lvl=. (max-1) ndx} lvl + else. + 'hit msg'=. res + lin=. pos I. hit + {. ndx + lin;msg + return. + end. +end. +0 +) +ppval1=: 3 : 0 +dat=. y +select. > {. dat +case. 'if.' do. + b=. 0 = +/ dat e. CONTROLM -. ;: 'else. elseif. do.' + e0=. +/ dat = <'else.' + e1=. +/ dat = <'elseif.' + b=. b *. (2 > e0) *. 0 = e0 *. e1 + b=. b *. (+/ dat = <'do.') = 1 + e1 + if. e1 do. + ix=. I. dat = <'elseif.' + dx=. }. I. dat = <'do.' + b=. b *. (#ix) = #dx + if. b do. + b=. b *. (i.@#-:/:) ,ix,.dx + end. + end. +case. 'select.' do. + b=. 0 = +/ dat e. CONTROLM -. ;: 'case. fcase. do.' + ix=. I. dat e. ;: 'case. fcase.' + dx=. I. dat = <'do.' + b=. b *. (#ix) = #dx + if. b do. + b=. b *. (i.@#-:/:) ,ix,.dx + end. +case. 'try.' do. + c=. ;: 'catch. catchd. catcht.' + b=. (1 e. dat e. c) *. 0 = +/ dat e. CONTROLM -. c +case. 'while.';'whilst.' do. + b=. (1 = +/ dat = <'do.') *. 0 = +/ dat e. CONTROLM -. <'do.' +case. do. + b=. 1 = +/ dat = <'do.' + b=. b *. 0 = +/ dat e. CONTROLM -. <'do.' +end. +if. b do. 0 return. end. +0;'Unmatched control words' +) diff --git a/j/system/util/project.ijs b/j/system/util/project.ijs new file mode 100644 --- /dev/null +++ b/j/system/util/project.ijs @@ -0,0 +1,572 @@ +coclass <'jp' +coinsert 'j' +defaultvalue=: 4 : 'if. _1 = 4!:0 #dat do. y return. end. + +com=. ('NB.'&-:)@(3&{.)&> dat +ncm=. com < (1|.0,}.com) +. (0,}._1|.com) +msk=. com +: ncm *. dat=a: +dat=. msk # dat + +f=. 'NB.'&E. <: ~:/\@(e.&'''') +g=. #~ *./\@f +; (g each dat) ,each LF +) +ffoldername=: 3 : 0 +p=. tofoldername_j_ y +if. '~' ~: {.p do. '';p return. end. +x=. ('/' e. p) + p i. '/' +(x{.p);x}.p +) +fixNB=: 3 : 0 +x=. I. 'nb.' E. y +'NB' (0 1 +/~ x) } y +) +getprojfile=: 3 : 0 +if. 0=#y do. '' return. end. +p=. remsep projname2path y +if. -. ProjExt -: (-#ProjExt) {. p do. + p=. remsep p + 'f n'=. fpathname p + p,'/',n,ProjExt +end. +) +getprojname=: 3 : 0 +ProjectName,(0=#ProjectName)#ProjectPath +) +projname2path=: 3 : 0 +if. '~'={. y do. + jpath y +elseif. ('/'={.y) +: d +m=. ferase d +if. _1 e. m do. + 'Unable to delete: ',towords (m=_1)#d +end. +) +dirsubdirs=: 3 : 0 +r=. 1!:0 (termsep jpathsep y),'*' +if. 0=#r do. '' return. end. +{."1 r #~ '-d' -:("1) 1 4{"1 > 4{"1 r +) +dirtreex=: 3 : 0 +y=. jpathsep y +p=. (+./\. y = '/') # y +d=. 1!:0 y,('/' = {:y) # '*' +if. 0 = #d do. '' return. end. +a=. > 4 {"1 d +m=. 'd' = 4 {"1 a +f=. (r end. +) +toprojectfolder1=: 3 : 0 +res=. filecase@jpathsep each boxxopen y +rex=. I. '~' ~: {.&> res +if. 0=#rex do. res return. end. +if. #Folder do. + pid=. termsep jpath '~',Folder + for_i. rex do. + nax=. termsep nam=. i pick res + if. pid matchhead nax do. + res=. (<'~',Folder,(<:#pid) }. nam) i} res + rex=. rex -. i + end. + end. +end. +if. 0=#rex do. res return. end. +pus=. UserFolders,SystemFolders +pds=. {."1 pus +pps=. termsep each {:"1 pus +ndx=. \: # &> pps +pds=. ndx{pds +pps=. ndx{pps +len=. # &> pps +for_i. rex do. + nam=. i pick res + msk=. pps = len {. each ./) msk # len) { I. msk + nam=. ('~', > ndx { pds),(<: ndx { len) }. nam + res=. ({.RecentProjects +) +projopen=: 3 : 0 +projreset'' +if. 0=#y do. return. end. +Project=: getprojfile y +ProjectPath=: }: 0 pick fpathname Project +projpathfolder ProjectPath +if. #Folder do. + p=. (#jpath '~',Folder,'/') }. ProjectPath + ProjectName=: Folder,'/',p +else. + ProjectName=: '' +end. +projread'' +recentproj_add_j_ Project +) +projpathfolder=: 3 : 0 +p=. touserfolder y +f=. (p i. '/') {. p +if. ('~'={.f) *: (<}.f) e. {."1 UserFolders do. + setfolder_j_ '' +else. + setfolder_j_ }.f +end. +) +projreset=: 3 : 0 +projclear'' +Project=: ProjectPath=: ProjectName=: '' +) +projrun=: 3 : 0 +if. #y do. + p=. 0 pick fpathname getprojfile y +else. + p=. ProjectPath,'/' +end. +load ::] p,Run +) +pp_today=: 2 }. [: ": [: <. 100 #. 3 {. 6!:0 +pp_stamp=: [: ":@, 'r<0>2.0' (8!:2) _3 {. 6!:0 +pp_unstamp=: ':' (2 5}"1) 1 1 0 1 1 0 1 1 (#^:_1"1) _6 {.&> ] +pic=: 4 : 0 +'f p'=. fpathname y +path=. remsep f +d=. snapgetpath path +if. d -: 0 do. return. end. +d=. d,'/p',pp_today'' +t=. d,'/',p +dat=. x,(pp_stamp''),EAV +if. _1 -: fread t do. + if. -. pic_inidir d do. 0 return. end. + old=. fread y + if. -. _1 -: old do. + dat=. old,(6#'0'),EAV,dat + end. +end. +dat fappend t +) +pic_files=: 3 : 0 +{."1 [1!:0 (snappath remsep y),'/p','/*',~pp_today'' +) +pic_inidir=: 3 : 0 +if. #1!:0 y do. 1 return. end. +h=. (y i: 'p') {. y +n=. {."1 [ 1!:0 h,'p*' +if. #n do. + direrase h,'plast' + n=. \:~ n -. <'plast' + if. #n do. + if. 1<#n do. + direrase &> ( d +if. 0 = #m do. EMPTY return. end. +p=. ;t&pic_list1 each m +s=. >}."1 p +p=. ({."1 p),<'total' +(>p),.' ',.":s,+/s +) +pic_list1=: 4 : 0 +fp=. (snappath fpath y pick FolderTree),'/p',x,'/' +d=. 1!:0 fp,'*' +if. 0=#d do. i. 0 3 return. end. +f=. {."1 d +c=. (EAV+/ .=fread) each ( (<0;ss_today'') (,<@fpath) each y +empty SnapTrees_jp_=: SnapTrees, 4{"1 d +last=. 0 pick d +iftoday=. today -: 7 {. last +if. force do. + if. (p,last) ss_match ProjectPath do. + ss_info 'Last snapshot matches current project.' + 0 return. + end. + if. iftoday do. + f=. pfx,_3 {. '00',": 1 + 0 ". _3 {. last + else. + f=. pfx,'001' + end. + path ss_make f + ss_info 'New snapshot: ',1 pick fpathname f + +else. + if. iftoday do. 0 return. end. + if. (p,last) ss_match path do. 0 return. end. + path ss_make pfx,'001' +end. +d=. (Snapshots-1) }. d +for_s. d do. + f=. p,(>s),'/' + 1!:55 f&, each {."1 [ 1!:0 f,'*' + 1!:55 rmdir_j_ each d #~ n=2 +case. 101 do. + ; {. &> rmdir_j_ each d #~ n=1 +end. +) +ss_dir=: 3 : 0 +p=. jpath '~snap/.snp/' +d=. 1!:0 p,'*' +d=. ('d' = 4 {"1 > 4 {"1 d) # {."1 d +d=. ( r +n=. 2 * -. m +r=. m#r +p=. (*./\.@:~:&'/' # ]) each r +p=. r ,each '/' ,each p ,each p) (I.m) } n +r=. (tofoldername_j_ each r) (I.m) } (#d) # <'' +d;r;n +) +ss_files=: 3 : 0 +t=. 1!:0 y,'*' +if. 0=#t do. return. end. +att=. > 4{"1 t +msk=. ('h' = 1{"1 att) +: 'd' = 4{"1 att +t=. /:~ msk # t +if. _1 = 4!:0 <'ss_exclude' do. + exs=. '.' ,each SnapshotX_j_ + ss_exclude_jp_=: [: +./ exs & ((1 e. E.) &>/) +end. +t #~ -. ss_exclude {."1 t +) +ss_find=: 3 : 0 +y=. y,(0=#y)#ProjectPath +'d r'=. ss_dir'' +ndx=. r i. 4 {"1 d + \:~ {."1 d +else. + '' +end. +) +ss_make=: 4 : 0 +fm=. x,'/' +to=. y,'/' +if. 0 = ss_mkdir to do. 0 return. end. +f=. {."1 ss_files fm +fm=. (