new array-atom arith

This commit is contained in:
dzaima 2022-09-05 22:52:53 +03:00
parent 629076d001
commit c0b2164dc8
5 changed files with 401 additions and 207 deletions

View File

@ -7,6 +7,8 @@ static f64 pfmod(f64 a, f64 b) {
if (a<0 != b<0 && r!=0) r+= b;
return r;
}
static f64 bqn_or(f64 w, f64 x) { return (w+x)-(w*x); }
B add_c2(B, B, B); B ceil_c2(B, B, B);
B sub_c2(B, B, B); B div_c2(B, B, B);
B not_c2(B, B, B); B pow_c2(B, B, B);
@ -59,52 +61,6 @@ B floor_c2(B, B, B);
#define DOI8(EXPR,A,W,X,BASE) { Ri8(A) for (usz i=0; i<ia; i++) { i16 wv=W; i16 xv=X; i16 rv=EXPR; if (RARE(rv!=( i8)rv)) { decG(r); goto BASE; } rp[i]=rv; } goto dec_ret; }
#define DOI16(EXPR,A,W,X,BASE) { Ri16(A) for (usz i=0; i<ia; i++) { i32 wv=W; i32 xv=X; i32 rv=EXPR; if (RARE(rv!=(i16)rv)) { decG(r); goto BASE; } rp[i]=rv; } goto dec_ret; }
#define DOI32(EXPR,A,W,X,BASE) { Ri32(A) for (usz i=0; i<ia; i++) { i64 wv=W; i64 xv=X; i64 rv=EXPR; if (RARE(rv!=(i32)rv)) { decG(r); goto BASE; } rp[i]=rv; } goto dec_ret; }
#define REG_SA(NAME, EXPR) \
if (xe==el_bit) return bit_sel1Fn(NAME##_c2,w,x,1); \
if (xe==el_i8 && q_i8 (w)) { PI8 (x) i8 wc=o2iu(w); DOI8 (EXPR,x,wc,xp[i],sa8B ) } sa8B :; \
if (xe==el_i16 && q_i16(w)) { PI16(x) i16 wc=o2iu(w); DOI16(EXPR,x,wc,xp[i],sa16B) } sa16B:; \
if (xe==el_i32 && q_i32(w)) { PI32(x) i32 wc=o2iu(w); DOI32(EXPR,x,wc,xp[i],sa32B) } sa32B:; \
if (xe==el_f64) { Rf64(x) PF(x) DOF(EXPR,w,w.f,xp[i]) goto dec_ret; }
#define REG_AS(NAME, EXPR) \
if (we==el_bit) return bit_sel1Fn(NAME##_c2,w,x,0); \
if (we==el_i8 && q_i8 (x)) { PI8 (w) i8 xc=o2iu(x); DOI8 (EXPR,w,wp[i],xc,as8B ) } as8B :; \
if (we==el_i16 && q_i16(x)) { PI16(w) i16 xc=o2iu(x); DOI16(EXPR,w,wp[i],xc,as16B) } as16B:; \
if (we==el_i32 && q_i32(x)) { PI32(w) i32 xc=o2iu(x); DOI32(EXPR,w,wp[i],xc,as32B) } as32B:; \
if (we==el_f64) { Rf64(w) PF(w) DOF(EXPR,x,wp[i],x.f) goto dec_ret; }
#define NO_SI_AA(N)
#if SINGELI
#define SI_SA_I(N,S,W,BASE) R##S(x); usz rlen=avx2_##N##SA##_##S((W).u, (void*)xp, (void*)rp, ia); if(RARE(rlen!=ia)) { decG(r); goto BASE; } goto dec_ret;
#define SI_AS_I(N,S,X,BASE) R##S(w); usz rlen=avx2_##N##AS##_##S((void*)wp, (X).u, (void*)rp, ia); if(RARE(rlen!=ia)) { decG(r); goto BASE; } goto dec_ret;
#define SI_SA(NAME, EXPR) \
void* xp = tyany_ptr(x); \
switch(xe) { default: UD; \
case el_bit: return bit_sel1Fn(NAME##_c2,w,x,1); \
case el_i8 : { SI_SA_I(NAME, i8,w,saBad) } \
case el_i16: { SI_SA_I(NAME,i16,w,saBad) } \
case el_i32: { SI_SA_I(NAME,i32,w,saBad) } \
case el_f64: { SI_SA_I(NAME,f64,w,saBad) } \
case el_c8: case el_c16: case el_c32: case el_B:; /*fallthrough*/ \
} saBad:;
#define SI_AS(NAME, EXPR) \
void* wp = tyany_ptr(w); \
switch(we) { default: UD; \
case el_bit: return bit_sel1Fn(NAME##_c2,w,x,0); \
case el_i8 : { SI_AS_I(NAME, i8,x,asBad) } \
case el_i16: { SI_AS_I(NAME,i16,x,asBad) } \
case el_i32: { SI_AS_I(NAME,i32,x,asBad) } \
case el_f64: { SI_AS_I(NAME,f64,x,asBad) } \
case el_c8: case el_c16: case el_c32: case el_B:; /*fallthrough*/ \
} asBad:;
#define SI_AA(N) return dyArith_AA(&N##DyTableAA, w, x);
#define IFN_SINGELI(X)
#else
#define SI_AA NO_SI_AA
#define SI_AS REG_AS
#define SI_SA REG_SA
#define IFN_SINGELI(X) X
#endif
#define GC2f(SYMB, NAME, EXPR) B NAME##_c2_arr(B t, B w, B x) { \
if (isArr(w)|isArr(x)) { B r; \
@ -146,13 +102,39 @@ B floor_c2(B, B, B);
#if SINGELI
#define AR_DISPATCH(NAME) FORCE_INLINE B NAME##_AA(B t, B w, B x) { return dyArith_AA(&NAME##DyTableAA, w, x); }
AR_DISPATCH(add) AR_DISPATCH(floor)
AR_DISPATCH(sub) AR_DISPATCH(or)
AR_DISPATCH(mul) AR_DISPATCH(ceil)
AR_DISPATCH(and)
#undef AR_DISPATCH
#define AA_DISPATCH(NAME) FORCE_INLINE B NAME##_AA(B t, B w, B x) { return dyArith_AA(&NAME##DyTableAA, w, x); }
AA_DISPATCH(add) AA_DISPATCH(or)
AA_DISPATCH(sub)
AA_DISPATCH(mul) AA_DISPATCH(and)
AA_DISPATCH(ceil) AA_DISPATCH(floor)
#undef AA_DISPATCH
#define SA_DISPATCH(NAME) FORCE_INLINE B NAME##_SA(B t, B w, B x) { return dyArith_SA(&NAME##DyTableNA, w, x); }
#define AS_DISPATCH(NAME) FORCE_INLINE B NAME##_AS(B t, B w, B x) { return dyArith_SA(&NAME##DyTableAN, x, w); }
SA_DISPATCH(add)
SA_DISPATCH(sub) AS_DISPATCH(sub)
SA_DISPATCH(mul) SA_DISPATCH(and)
SA_DISPATCH(ceil) SA_DISPATCH(floor)
#undef SA_DISPATCH
#else
#define NO_SI_AA(N)
#define SI_AA NO_SI_AA
#define SI_AS REG_AS
#define SI_SA REG_SA
#define REG_SA(NAME, EXPR) \
if (xe==el_bit) return bit_sel1Fn(NAME##_c2,w,x,1); \
if (xe==el_i8 && q_i8 (w)) { PI8 (x) i8 wc=o2iu(w); DOI8 (EXPR,x,wc,xp[i],sa8B ) } sa8B :; \
if (xe==el_i16 && q_i16(w)) { PI16(x) i16 wc=o2iu(w); DOI16(EXPR,x,wc,xp[i],sa16B) } sa16B:; \
if (xe==el_i32 && q_i32(w)) { PI32(x) i32 wc=o2iu(w); DOI32(EXPR,x,wc,xp[i],sa32B) } sa32B:; \
if (xe==el_f64) { Rf64(x) PF(x) DOF(EXPR,w,w.f,xp[i]) goto dec_ret; }
#define REG_AS(NAME, EXPR) \
if (we==el_bit) return bit_sel1Fn(NAME##_c2,w,x,0); \
if (we==el_i8 && q_i8 (x)) { PI8 (w) i8 xc=o2iu(x); DOI8 (EXPR,w,wp[i],xc,as8B ) } as8B :; \
if (we==el_i16 && q_i16(x)) { PI16(w) i16 xc=o2iu(x); DOI16(EXPR,w,wp[i],xc,as16B) } as16B:; \
if (we==el_i32 && q_i32(x)) { PI32(w) i32 xc=o2iu(x); DOI32(EXPR,w,wp[i],xc,as32B) } as32B:; \
if (we==el_f64) { Rf64(w) PF(w) DOF(EXPR,x,wp[i],x.f) goto dec_ret; }
static B bitAA0(B w, B x, usz ia) { UD; }
static NOINLINE B bitAA1(B w, B x, usz ia) {
u64* rp; B r = m_bitarrc(&rp, x);
@ -204,12 +186,12 @@ B floor_c2(B, B, B);
}
AR_I_AA("×", mul, wv*xv, 2, {})
AR_I_AA("", and, wv*xv, 2, {})
AR_I_AA("", or , (wv+xv)-(wv*xv), 1, {})
AR_I_AA("", or , bqn_or(wv, xv), 1, {})
AR_I_AA("", floor, wv>xv?xv:wv, 2, {})
AR_I_AA("", ceil , wv>xv?wv:xv, 1, {})
AR_I_AA("+", add, wv+xv, 0, {})
AR_I_AA("-", sub, wv-xv, 0, {
IFN_SINGELI(if (we==el_c32 && xe==el_i32) {
if (we==el_c32 && xe==el_i32) {
u32* wp = c32any_ptr(w); usz wia = IA(w);
u32* rp; r = m_c32arrc(&rp, w);
i32* xp = i32any_ptr(x);
@ -218,82 +200,80 @@ B floor_c2(B, B, B);
if (rp[i]>CHR_MAX) thrM("-: Invalid character"); // safe - see add
}
goto dec_ret;
})
}
})
#undef AR_I_AA
#define AR_I_AS(CHR, NAME, EXPR, DO_AS, EXTRA) NOINLINE B NAME##_AS(B t, B w, B x) { \
B r; u8 we=TI(w,elType); EXTRA \
if (isF64(x)) { usz ia=IA(w); DO_AS(NAME,EXPR) } \
ARITH_SLOW; return arith_recd(NAME##_c2, w, x); \
dec_ret: decG(w); return r; \
}
#define AR_I_SA(CHR, NAME, EXPR, DO_SA, EXTRA) NOINLINE B NAME##_SA(B t, B w, B x) { \
B r; u8 xe=TI(x,elType); EXTRA \
if (isF64(w)) { usz ia=IA(x); DO_SA(NAME,EXPR) } \
ARITH_SLOW; return arith_recd(NAME##_c2, w, x); \
dec_ret: decG(x); return r; \
}
static NOINLINE B bit_sel1Fn(BBB2B f, B w, B x, bool bitX) { // consumes both
B b = bitX? x : w;
u64* bp = bitarr_ptr(b);
usz ia = IA(b);
bool b0 = ia? bp[0]&1 : 0;
bool both = false;
for (usz i = 0; i < ia; i++) if (bitp_get(bp,i) != b0) { both=true; break; }
B e0=m_f64(0), e1=m_f64(0); // initialized to have something to decrement later
bool h0=both || b0==0; if (h0) e0 = bitX? f(bi_N, inc(w), m_f64(0)) : f(bi_N, m_f64(0), inc(x));
bool h1=both || b0==1; if (h1) e1 = bitX? f(bi_N, w, m_f64(1)) : f(bi_N, m_f64(1), x);
// non-bitarr arg has been consumed
B r = bit_sel(b, e0, h0, e1, h1); // and now the bitarr arg is consumed too
dec(e0); dec(e1);
return r;
}
AR_I_SA("-", sub, wv-xv, SI_SA, {})
AR_I_SA("×", mul, wv*xv, SI_SA, {})
AR_I_SA("", and, wv*xv, REG_SA, {})
AR_I_SA("", or , (wv+xv)-(wv*xv), REG_SA, {})
AR_I_SA("", floor, wv>xv?xv:wv, REG_SA, {})
AR_I_SA("", ceil , wv>xv?wv:xv, REG_SA, {})
AR_I_SA("+", add, wv+xv, SI_SA, {
if (isC32(w) && xe==el_i32) {
u32 wv = o2cu(w);
i32* xp = i32any_ptr(x); usz xia = IA(x);
u32* rp; r = m_c32arrc(&rp, x);
for (usz i = 0; i < xia; i++) {
rp[i] = (u32)(xp[i]+(i32)wv);
if (rp[i]>CHR_MAX) thrM("+: Invalid character"); // safe to only check this as wv already must be below CHR_MAX, which is less than U32_MAX/2
}
goto dec_ret;
}
})
#undef AR_I_SA
AR_I_AS("-", sub, wv-xv, SI_AS, {
if (we==el_c32 && isC32(x)) {
i32 xv = (i32)o2cu(x);
u32* wp = c32any_ptr(w); usz wia = IA(w);
i32* rp; r = m_i32arrc(&rp, w);
for (usz i = 0; i < wia; i++) rp[i] = (i32)wp[i] - xv;
goto dec_ret;
}
})
#undef AR_I_AS
#endif // !SINGELI
#define AR_I_AS(CHR, NAME, EXPR, DO_AS, EXTRA) NOINLINE B NAME##_AS(B t, B w, B x) { \
B r; u8 we=TI(w,elType); EXTRA \
if (isF64(x)) { usz ia=IA(w); DO_AS(NAME,EXPR) } \
ARITH_SLOW; return arith_recd(NAME##_c2, w, x); \
dec_ret: decG(w); return r; \
}
#define AR_I_SA(CHR, NAME, EXPR, DO_SA, EXTRA) NOINLINE B NAME##_SA(B t, B w, B x) { \
B r; u8 xe=TI(x,elType); EXTRA \
if (isF64(w)) { usz ia=IA(x); DO_SA(NAME,EXPR) } \
ARITH_SLOW; return arith_recd(NAME##_c2, w, x); \
dec_ret: decG(x); return r; \
}
static NOINLINE B bit_sel1Fn(BBB2B f, B w, B x, bool bitX) { // consumes both
B b = bitX? x : w;
u64* bp = bitarr_ptr(b);
usz ia = IA(b);
bool b0 = ia? bp[0]&1 : 0;
bool both = false;
for (usz i = 0; i < ia; i++) if (bitp_get(bp,i) != b0) { both=true; break; }
B e0=m_f64(0), e1=m_f64(0); // initialized to have something to decrement later
bool h0=both || b0==0; if (h0) e0 = bitX? f(bi_N, inc(w), m_f64(0)) : f(bi_N, m_f64(0), inc(x));
bool h1=both || b0==1; if (h1) e1 = bitX? f(bi_N, w, m_f64(1)) : f(bi_N, m_f64(1), x);
// non-bitarr arg has been consumed
B r = bit_sel(b, e0, h0, e1, h1); // and now the bitarr arg is consumed too
dec(e0); dec(e1);
return r;
}
AR_I_SA("-", sub, wv-xv, SI_SA, {})
AR_I_SA("×", mul, wv*xv, SI_SA, {})
AR_I_SA("", and, wv*xv, REG_SA, {})
AR_I_SA("", or , (wv+xv)-(wv*xv), REG_SA, {})
AR_I_SA("", floor, wv>xv?xv:wv, REG_SA, {})
AR_I_SA("", ceil , wv>xv?wv:xv, REG_SA, {})
AR_I_SA("+", add, wv+xv, SI_SA, {
if (isC32(w) && xe==el_i32) {
u32 wv = o2cu(w);
i32* xp = i32any_ptr(x); usz xia = IA(x);
u32* rp; r = m_c32arrc(&rp, x);
for (usz i = 0; i < xia; i++) {
rp[i] = (u32)(xp[i]+(i32)wv);
if (rp[i]>CHR_MAX) thrM("+: Invalid character"); // safe to only check this as wv already must be below CHR_MAX, which is less than U32_MAX/2
}
goto dec_ret;
}
})
#undef AR_I_SA
AR_I_AS("-", sub, wv-xv, SI_AS, {
if (we==el_c32 && isC32(x)) {
i32 xv = (i32)o2cu(x);
u32* wp = c32any_ptr(w); usz wia = IA(w);
i32* rp; r = m_i32arrc(&rp, w);
for (usz i = 0; i < wia; i++) rp[i] = (i32)wp[i] - xv;
goto dec_ret;
}
})
#define add_AS(T, W, X) add_SA(T, X, W)
#define mul_AS(T, W, X) mul_SA(T, X, W)
#define and_AS(T, W, X) and_SA(T, X, W)
#define or_AS(T, W, X) or_SA(T, X, W)
#define floor_AS(T, W, X) floor_SA(T, X, W)
#define ceil_AS(T, W, X) ceil_SA(T, X, W)
#undef AR_I_AS
#define AR_F_TO_ARR(NAME) return NAME##_c2_arr(t, w, x);
#define AR_I_TO_ARR(NAME) \
@ -326,7 +306,7 @@ AR_I_SCALAR("-", sub, w.f-x.f, {
})
AR_I_SCALAR("×", mul, w.f*x.f, {})
AR_I_SCALAR("", and, w.f*x.f, {})
AR_I_SCALAR("", or , (w.f+x.f)-(w.f*x.f), {})
AR_I_SCALAR("", or , bqn_or(w.f, x.f), {})
AR_I_SCALAR("", floor, w.f>x.f?x.f:w.f, {})
AR_I_SCALAR("", ceil , w.f>x.f?w.f:x.f, {})
#undef AR_I_SCALAR

View File

@ -52,7 +52,7 @@ typedef struct EntAA {
} EntAA;
typedef struct DyTableAA {
EntAA entsAA[8*8]; // one for each instruction
EntAA entsAA[el_B*el_B]; // one for each instruction
BBB2B mainFn;
char* repr;
} DyTableAA;
@ -130,7 +130,7 @@ NOINLINE B dyArith_AA(DyTableAA* table, B w, B x) {
}
case e_call_sqx: {
assert(TI(x,elType)==el_f64);
x = num_squeeze(x);
x = num_squeezeChk(x);
u8 xe = TI(x,elType);
if (xe==el_f64) goto rec;
e = &table->entsAA[TI(w,elType)*8 + xe];
@ -147,6 +147,135 @@ NOINLINE B dyArith_AA(DyTableAA* table, B w, B x) {
}
typedef struct DyTableSA DyTableSA;
typedef bool (*ForBitsel)(DyTableSA*, B w, B* r);
typedef u64 (*AtomArrFnC)(u8* r, u64 w, u8* x, u64 len);
typedef B (*DyArithChrFn)(DyTableSA*, B, B, usz, u8);
typedef struct {
// >=el_i8 el_bit
union { AtomArrFnC f1; ForBitsel bitsel; };
union { AtomArrFnC f2; };
} EntSA;
struct DyTableSA {
EntSA ents[el_B];
BBB2B mainFn;
char* repr;
DyTableSA* chrAtom;
};
bool bad_forBitselNN_SA(DyTableSA* table, B w, B* r) { return false; }
#define bad_forBitselCN_SA bad_forBitselNN_SA
B bad_chrAtomSA(DyTableSA* table, B w, B x, usz ia, u8 xe) { return arith_recd(table->mainFn, w, x); }
#define bad_chrAtomAS bad_chrAtomSA
u64 failAtomArr1(u8* r, u64 w, u8* x, u64 len) { return 0; }
u64 failAtomArr2(u8* r, u64 w, u8* x, u64 len) { return 1; }
u8 nextType[] = {
[t_i8arr ] = t_i16arr, [t_c8arr ] = t_c16arr,
[t_i16arr] = t_i32arr, [t_c16arr] = t_c32arr,
[t_i32arr] = t_f64arr, [t_c32arr] = t_empty,
[t_f64arr] = t_empty,
};
B dyArith_SA(DyTableSA* table, B w, B x) {
usz ia = IA(x);
u8 xe = TI(x,elType);
u8 width, type; // when one argument is a number, both + and - have character array result iif the other argument is a character array; therefore result type doesn't need a lookup
u64 wa;
EntSA* e;
if (!isF64(w)) {
if (!isC32(w)) goto rec;
DyTableSA* t2 = table->chrAtom;
if (t2==NULL) goto rec;
table = t2;
wa = o2cu(w);
newXEc:
switch(xe) { default: UD;
case el_bit: goto bitsel;
case el_i8: if (wa==( u8)wa) { e=&table->ents[el_i8 ]; width=0; type=t_c8arr; goto f1; } else goto cwiden_i8;
case el_i16: if (wa==(u16)wa) { e=&table->ents[el_i16]; width=1; type=t_c16arr; goto f1; } else goto cwiden_i16;
case el_i32: e=&table->ents[el_i32]; width=2; type=t_c32arr; goto f1;
case el_f64: x=num_squeezeChk(x); xe=TI(x,elType); if (xe!=el_f64) goto newXEc; else goto rec;
case el_c8: if (wa==( u8)wa) { e=&table->ents[el_c8 ]; width=0; type=t_i8arr; goto f1; } goto cwiden_c8; // TODO check for & use unsigned w
case el_c16: if (wa==(u16)wa) { e=&table->ents[el_c16]; width=1; type=t_i16arr; goto f1; } goto cwiden_c16;
case el_c32: e=&table->ents[el_c32]; width=2; type=t_i32arr; goto f1;
case el_B: goto rec;
}
cwiden_i8: if (q_c16(w)) { type=t_c16arr; goto cpy_i16; }
cwiden_i16: { type=t_c32arr; goto cpy_i32; }
cwiden_c8: if (q_c16(w)) { type=t_i16arr; goto cpy_c16; }
cwiden_c16: { type=t_i32arr; goto cpy_c32; }
goto rec;
}
switch(xe) { default: UD;
case el_bit: goto bitsel;
case el_i8: if (q_i8 (w)) { e=&table->ents[el_i8 ]; width=0; type=t_i8arr; goto wint; } goto iwiden_i8;
case el_i16: if (q_i16(w)) { e=&table->ents[el_i16]; width=1; type=t_i16arr; goto wint; } goto iwiden_i16;
case el_i32: if (q_i32(w)) { e=&table->ents[el_i32]; width=2; type=t_i32arr; goto wint; } goto iwiden_i32;
case el_f64: e=&table->ents[el_f64]; width=3; type=t_f64arr; goto wf64;
case el_c8: if (q_i8 (w)) { e=&table->ents[el_c8 ]; width=0; type=t_c8arr; goto wint; } goto iwiden_c8;
case el_c16: if (q_i16(w)) { e=&table->ents[el_c16]; width=1; type=t_c16arr; goto wint; } goto iwiden_c16;
case el_c32: if (q_i32(w)) { e=&table->ents[el_c32]; width=2; type=t_c32arr; goto wint; } goto rec;
case el_B: goto rec;
}
wint: wa=(u32)o2iu(w); goto f1;
wf64: wa=w.u; goto f1;
iwiden_i8: if (q_i16(w)) { wa=(u32)o2iu(w); type=t_i16arr; goto cpy_i16; }
iwiden_i16: if (q_i32(w)) { wa=(u32)o2iu(w); type=t_i32arr; goto cpy_i32; }
iwiden_i32: { wa=w.u; type=t_f64arr; goto cpy_f64; }
iwiden_c8: if (q_i16(w)) { wa=(u32)o2iu(w); type=t_c16arr; goto cpy_c16; }
iwiden_c16: if (q_i32(w)) { wa=(u32)o2iu(w); type=t_c32arr; goto cpy_c32; }
goto rec;
// TODO reuse the copied array for the result; maybe even alternate copy & operation to stay in cache
cpy_c16: x = taga(cpyC16Arr(x)); width=1; e=&table->ents[el_c16]; goto f1;
cpy_c32: x = taga(cpyC32Arr(x)); width=2; e=&table->ents[el_c32]; goto f1;
cpy_i16: x = taga(cpyI16Arr(x)); width=1; e=&table->ents[el_i16]; goto f1;
cpy_i32: x = taga(cpyI32Arr(x)); width=2; e=&table->ents[el_i32]; goto f1;
cpy_f64: x = taga(cpyF64Arr(x)); width=3; e=&table->ents[el_f64]; goto f1;
AtomArrFnC fn; B r;
f1: fn = e->f1;
u64 got = fn(m_tyarrlc(&r, width, x, type), wa, tyany_ptr(x), ia);
if (got==ia) goto decG_ret;
decG(r);
type = nextType[type];
if (type==t_empty) goto rec;
fn = e->f2;
if (fn(m_tyarrlc(&r, width+1, x, type), wa, tyany_ptr(x), ia)==0) goto decG_ret;
decG(r);
goto rec;
decG_ret: decG(x); return r;
rec: return arith_recd(table->mainFn, w, x);
bitsel: {
B opts[2];
if (!table->ents[el_bit].bitsel(table, w, opts)) goto rec;
return bit_sel(x, opts[0], 1, opts[1], 1);
}
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#include "../gen/dyarith.c"
@ -157,4 +286,36 @@ static void powAAu_f64_f64_f64(u8* r, u8* w, u8* x, u64 len) { for (u64 i = 0;
static void stileAAu_f64_f64_f64(u8* r, u8* w, u8* x, u64 len) { for (u64 i = 0; i < len; i++) ((f64*)r)[i] = pfmod(((f64*)x)[i], ((f64*)w)[i]); }
static void logAAu_f64_f64_f64(u8* r, u8* w, u8* x, u64 len) { for (u64 i = 0; i < len; i++) ((f64*)r)[i] = log(((f64*)x)[i])/log(((f64*)w)[i]); }
#define BI_C2(N, W, X) ({ B w_ = (W); N##_c2(w_, w_, X); })
// bool sub_forBitselCN_SA (DyTableSA* table, B w, B* r) { u32 v=o2cu(w); r[0] = m_c32(v-0); r[1] = m_c32(v-1); if (v==0) BI_C2(sub, w, m_f64(1)); return true; }
bool add_forBitselNN_SA (DyTableSA* table, B w, B* r) { f64 f=o2fu(w); r[0] = m_f64(f+0); r[1] = m_f64(f+1); return true; }
bool sub_forBitselNN_SA (DyTableSA* table, B w, B* r) { f64 f=o2fu(w); r[0] = m_f64(f-0); r[1] = m_f64(f-1); return true; }
bool subR_forBitselNN_SA(DyTableSA* table, B w, B* r) { f64 f=o2fu(w); r[0] = m_f64(0-f); r[1] = m_f64(1-f); return true; }
bool mul_forBitselNN_SA (DyTableSA* table, B w, B* r) { f64 f=o2fu(w); r[0] = m_f64(f*0); r[1] = m_f64(f*1); return true; }
bool min_forBitselNN_SA (DyTableSA* table, B w, B* r) { f64 f=o2fu(w); r[0] = m_f64(f<=0?f:0); r[1] = m_f64(f<=1?f:1); return true; }
bool max_forBitselNN_SA (DyTableSA* table, B w, B* r) { f64 f=o2fu(w); r[0] = m_f64(f>=0?f:0); r[1] = m_f64(f>=1?f:1); return true; }
bool add_forBitselCN_SA(DyTableSA* table, B w, B* r) { u32 wc=o2cu(w); if(wc+1<=CHR_MAX) return false; r[0] = m_c32(wc); r[1] = m_c32(wc+1); return true; }
bool sub_forBitselCN_SA(DyTableSA* table, B w, B* r) { u32 wc=o2cu(w); if(wc !=0 ) return false; r[0] = m_c32(wc); r[1] = m_c32(wc-1); return true; }
B sub_c2R(B t, B w, B x) { return sub_c2(t, x, w); }
static NOINLINE B or_SA(B t, B w, B x) {
if (!isF64(w)) return arith_recd(or_c2, w, x);
if (LIKELY(TI(x,elType)==el_bit)) {
bitsel:
return bit_sel(x, BI_C2(or, w, m_f64(0)), 1, BI_C2(or, w, m_f64(1)), 1);
}
x = num_squeezeChk(x);
if (TI(x,elType)==el_bit) goto bitsel;
f64* rp;
B r = m_f64arrc(&rp, x);
usz ia = a(x)->ia;
x = toF64Any(x);
orSAc_f64_f64_f64((u8*)rp, w.u, tyany_ptr(x), ia);
decG(x);
return r;
}
#include "../gen/arTables.c"

View File

@ -21,22 +21,6 @@ def assert{x & x==1} = 1
def assert{x:u1} = emit{void, 'si_assert', x}
def tern{c, T, F & anyInt{c}} = {
if(c) T
else F
}
def tern{c, t:T, f:T & anyInt{c}} = {
res:T = f
if (c) res = t
res
}
def min{a, b & knum{a} & knum{b}} = tern{a<b, a, b}
def max{a, b & knum{a} & knum{b}} = tern{a>b, a, b}
# various checks
def knum{x} = match{kind{x},'number'}
def isreg{x} = match{kind{x},'register'}
@ -113,6 +97,21 @@ def maxvalue{T & isunsigned{T}} = (1<<width{T})-1
def minvalue{T & issigned{T}} = - (1<<(width{T}-1))
def maxvalue{T & issigned{T}} = (1<<(width{T}-1))-1
def tern{c, T, F & anyInt{c}} = {
if(c) T
else F
}
def tern{c, t:T, f:T & anyInt{c}} = {
res:T = f
if (c) res = t
res
}
def min{a, b & knum{a} & knum{b}} = tern{a<b, a, b}
def max{a, b & knum{a} & knum{b}} = tern{a>b, a, b}
# tuple operations
def broadcast{T, v & isprim{T}} = v
def any{v:T & isprim{T}} = v

View File

@ -22,9 +22,12 @@ def fmt_op{X== max}= 'max'
def rootty{T & isprim{T}} = T
def rootty{T & isvec{T}} = eltype{T}
def is_s{X} = issigned{rootty{X}}
def is_u{X} = isunsigned{rootty{X}}
def ty_sc{O, R} = R # keep floats as-is
def ty_sc{O, R & issigned{O} & isunsigned{rootty{R}}} = ty_s{R}
def ty_sc{O, R & isunsigned{O} & issigned{rootty{R}}} = ty_u{R}
def ty_sc{O, R & is_s{O} & is_u{R}} = ty_s{R}
def ty_sc{O, R & is_u{O} & is_s{R}} = ty_u{R}
def bqn_or{a, b} = (a+b)-(a*b)
@ -37,7 +40,7 @@ def arithChk1{F==__sub, M, w:T, x:T, r:T & isvec{T} & width{eltype{T}}<=16} = an
def arithChk2{F, M, w:T, x:T & issigned{rootty{T}} & (match{F,__add} | match{F,__sub})} = {
def arithChk2{F, M, w:T, x:T & is_s{T} & (match{F,__add} | match{F,__sub})} = {
r:= F{w,x}
tup{r, arithChk1{F, M, w, x, r}}
}
@ -81,9 +84,9 @@ def arithChk2{F, M, w:T, x:T & match{F,__mul} & isvec{T} & i32==eltype{T}} = {
def runner{u, R, F} = {
def c = ~u
def run{F, OO, M, w, x} = { show{'todo', fmt_op{F}, c, w, x}; emit{void,'__builtin_abort'}; w }
def run{F, OO, M, w, x} = { show{'todo', c, R, fmt_op{F}, w, x}; emit{void,'__builtin_abort'}; w }
def run{F, OO, M, w:T, x:T & c} = {
def run{F, OO, M, w:T, x:T & c & R!=u32} = {
def r2 = arithChk2{F, M, w, x}
if (rare{tupsel{1,r2}}) OO{}
tupsel{0,r2}
@ -92,54 +95,24 @@ def runner{u, R, F} = {
def run{F, OO, M, w, x & u} = F{w, x} # trivial base implementation
def toggleTop{x:X} = x ^ broadcast{X, 1<<(width{eltype{X}}-1)}
def run{F==__sub, OO, M, w:VU, x:VU & isunsigned{eltype{VU}}} = { # 'b'-'a'
def run{F==__sub, OO, M, w:VU, x:VU & is_u{VU}} = { # 'b'-'a'
def VS = ty_s{VU}
run{F, OO, M, VS~~toggleTop{w}, VS~~toggleTop{x}}
}
def run{F, OO, M, w:VU, x:VS & isunsigned{eltype{VU}} & issigned{eltype{VS}}} = { # 'a'+3, 'a'-3
def run{F, OO, M, w:VU, x:VS & is_u{VU} & is_s{VS}} = { # 'a'+3, 'a'-3
toggleTop{VU~~run{F, OO, M, VS~~toggleTop{w}, x}}
}
# def run{F==__add, OO, M, w:VS, x:VU & issigned{eltype{VS}} & isunsigned{eltype{VU}}} = run{F, OO, M, x, w} # 3+'a' → 'a'+3
def run{F==__add, OO, M, w:VS, x:VU & is_s{VS} & is_u{VU}} = run{F, OO, M, x, w} # 3+'a' → 'a'+3
def run{F, OO, M, w:VW, x:VX & c & R==u32 & (match{F,__add} | match{F,__sub})} = { # 'a'+1, 'a'-1
r:= F{ty_u{w}, ty_u{x}}
if (any{M{r > broadcast{type{r}, 1114111}}}) OO{}
to_el{R, VW}~~r
}
run
}
# old atom F array & array F atom
def arithAny{VT, F, W, X, r, len} = {
def bulk = vcount{VT}
def run = runner{eltype{VT}==f64, eltype{VT}, F}
maskedLoop{bulk, len, {i, M} => storeBatch{r, i, run{F, {} => return{i}, M, W{i}, X{i}}, M}}
len
}
# cast a guaranteed float to a more specific type; return{0} if not possible
def cast_fB{T, x:(u64) & f64==T} = from_B{f64, x}
def cast_fB{T, x:(u64) & issigned{T} & T<i64} = {
f:f64 = from_B{f64, x}
r:T = ftrunc{T, f}
if (rare{f!=fext{r}}) return{cast{Size,0}}
r
}
def arithAS{VT, F, w, x, r, len} = { xv:= broadcast{VT, x}; arithAny{VT, F, {i}=>load{*VT~~w, i}, {i}=>xv, r, len} }
def arithSA{VT, F, w, x, r, len} = { wv:= broadcast{VT, w}; arithAny{VT, F, {i}=>wv, {i}=>load{*VT~~x, i}, r, len} }
arithAS{F,VT}(w: *u8, x: u64, r: *u8, len: Size) : Size = { def T=eltype{VT}; arithAS{VT, F, *T ~~ w, cast_fB{T, x}, *T~~r, len} }
arithSA{F,VT}(w: u64, x: *u8, r: *u8, len: Size) : Size = { def T=eltype{VT}; arithSA{VT, F, cast_fB{T, w}, *T ~~ x, *T~~r, len} }
'avx2_addAS_i8' = arithAS{__add,[32]i8 }; 'avx2_addSA_i8' = arithSA{__add,[32]i8 }
'avx2_addAS_i16' = arithAS{__add,[16]i16}; 'avx2_addSA_i16' = arithSA{__add,[16]i16}
'avx2_addAS_i32' = arithAS{__add,[ 8]i32}; 'avx2_addSA_i32' = arithSA{__add,[ 8]i32}
'avx2_addAS_f64' = arithAS{__add,[ 4]f64}; 'avx2_addSA_f64' = arithSA{__add,[ 4]f64}
'avx2_subAS_i8' = arithAS{__sub,[32]i8 }; 'avx2_subSA_i8' = arithSA{__sub,[32]i8 }
'avx2_subAS_i16' = arithAS{__sub,[16]i16}; 'avx2_subSA_i16' = arithSA{__sub,[16]i16}
'avx2_subAS_i32' = arithAS{__sub,[ 8]i32}; 'avx2_subSA_i32' = arithSA{__sub,[ 8]i32}
'avx2_subAS_f64' = arithAS{__sub,[ 4]f64}; 'avx2_subSA_f64' = arithSA{__sub,[ 4]f64}
'avx2_mulAS_i8' = arithAS{__mul,[32]i8 }; 'avx2_mulSA_i8' = arithSA{__mul,[32]i8 }
'avx2_mulAS_i16' = arithAS{__mul,[16]i16}; 'avx2_mulSA_i16' = arithSA{__mul,[16]i16}
'avx2_mulAS_i32' = arithAS{__mul,[ 8]i32}; 'avx2_mulSA_i32' = arithSA{__mul,[ 8]i32}
'avx2_mulAS_f64' = arithAS{__mul,[ 4]f64}; 'avx2_mulSA_f64' = arithSA{__mul,[ 4]f64}
# new array F array
def arithAAimpl{vw, mode, F, W, X, R, w, x, r, len} = {
# show{fmt_op{F}, mode, W, X, R}
if (R==u1) {
@ -180,4 +153,28 @@ def arithAA{mode, F, W, X, R} = {
else arithAAu{vw, mode, F, W, X, R}
}
# mode: 0:overflow-checked, needed; 1:overflow-erroring; 2: overflow-checked, not needed
arithSAf{vw, mode, F, swap, W, X, R}(r:*u8, w:u64, x:*u8, len:u64) : u64 = {
# show{fmt_op{F}, swap, mode, W, X, R}
def bulk = vw / max{width{W}, width{R}}
def TY = [bulk]R
def overflow = tern{mode==1, {i}=>return{1}, {i}=>return{i}}
def run = runner{(R==f64) | (mode==2), R, F}
def getW{v} = trunc{W, v}
def getW{v & W==f64} = interp_f64{v}
cw:= broadcast{ty_sc{W, TY}, getW{w}}
maskedLoop{bulk, len, {i, M} => {
cx:= loadBatch{*X~~x, i, ty_sc{X, TY}}
storeBatch{*R~~r, i, TY~~run{F, {} => overflow{i}, M, tern{swap,cx,cw}, tern{swap,cw,cx}}, M}
}}
if (mode==1) 0
else len
}
def arithSA{mode, F, swap, W, X, R} = arithSAf{256, mode, F, swap, W, X, R}
'orSAc_f64_f64_f64'=arithSA{2,bqn_or,0,f64,f64,f64}
include './../gen/arDefs'

View File

@ -1,6 +1,4 @@
debug 0=•args
•term.OutRawdebug @+27 "[H" @+27 "[2J" @+27 "[3J"
•Out(3×debug) 200'-'
implstables 2•args
T ={<𝕨𝕨>𝕩}
@ -17,14 +15,7 @@ tmLit ← "uceue"
tyWidth 990123012 # in log2(bytes)
tyName "bit""i8""i16""i32""f64""c8""c16""c32"
tySiType "u1""i8""i16""i32""f64""u8""u16""u32"
ShowTbl {
# 𝕩 ↩ {∧´⥊𝕩≡¨@? @; 𝕩/˜𝕩≢¨@}¨ 𝕩
𝕩 ˘=¨
•Show 𝕩
#•Out •Repr 𝕩
}debug
tySiName "u1""i8""i16""i32""f64""u8""u16""u32"
mdNone 0
mdExact 1
@ -33,21 +24,26 @@ mdBit2i8 ← 3
mdF64Chr 4
mdSqF64 5
singeliFns
GetSingeli { tmwxridsi:
singeliAAFns
GetSingeliAA { tmwxridsi:
{
r@? @;
name id, "AA", tmtmLit, "_", wtyName, "_", xtyName, "_", rtyName
singeliFns <namewxrtmsi
singeliAAFns <namewxrtmsi
name
}
}
singeliASFns
nl@+10
cSrc ""
siSrc ""
Make {𝕊ns:
cbqnrepridsicommutative ns
# array-array
aaAaaB {4𝕩?𝕩idsi; 𝕩}¨¨ ns.aa_ans.aa_b # add ID and singeli fn to entries that don't have it explicit
currTypes 88
@ -94,16 +90,16 @@ Make ← {𝕊ns:
Type {𝕊: 3nmap}
@ # mdNone
{𝕊: GetSingeli e, t, Type@, call(bit=3nmap)"rbyte""bit", s, @} # mdExact
{𝕊: GetSingeli e, t, Type@, call(bit=3nmap)"rbyte""bit", s, ((sm)/"wx")tyName˜m/n} # mdCast
{𝕊: GetSingeli e, t, Type@, call"wxi8", s, @} # mdBit2i8
{𝕊: GetSingeliAA e, t, Type@, call(bit=3nmap)"rbyte""bit", s, @} # mdExact
{𝕊: GetSingeliAA e, t, Type@, call(bit=3nmap)"rbyte""bit", s, ((sm)/"wx")tyName˜m/n} # mdCast
{𝕊: GetSingeliAA e, t, Type@, call"wxi8", s, @} # mdBit2i8
{𝕊: @, t, @, "e_call_sqx", s, @} # mdF64Chr
{𝕊: GetSingeli e, t, Type@, call"wxf64sq", s, @} # mdSqF64
{𝕊: GetSingeliAA e, t, Type@, call"wxf64sq", s, @} # mdSqF64
𝕩
}¨ res
}¨ aaAaaB
# ShowTbl ∾´¨ instrs
{•Show ˘¨𝕩}debug instrs
cSrc
"B ", cbqn, "_c2(B,B,B);", nl
@ -132,6 +128,62 @@ Make ← {𝕊ns:
" .repr = """, repr, """", nl
"};", nl
# array-scalar / scalar-array
ty0 tyName
ty1 @, "i16","i32","f64",@, "c16","c32",@
tyi @, "i8","i16","i32","f64", "i8","i16","i32"
tyc @, "c8","c16","c32",@, "c8","c16","c32"
isc 0, 0, 0, 0, 0, 1, 1, 1
{ 𝕊 swapget:
choices ns.sa
hadChrArr 0
{
0𝕩? @;
charAtm 'c' 𝕩
hasNumArr 'i' 1¨𝕩
hasChrArr 'c' 1¨𝕩
resChr {(2¨𝕩)((2¨𝕩)) 22@} 'c'=𝕩
argarr swap "SA"
canOverflow "f64"¨ tyName
cSrc
"static DyTableSA ", cbqn,"DyTable", swap (charAtm"NC")"A", " = {", nl
" .ents = {", nl
" {.bitsel=", hasNumArr"bad", {𝕊:idswap/"R"} @, "_forBitsel", charAtm"NC", "N_SA},", nl
{ 𝕊 num:
onlyFirst ns.overflowEq 1, ¬numcanOverflow
f1f2 12 {
𝕩@? @𝕩ty1?
charArr numisc
¬ (charAtm¬numcanOverflow) (onlyFirst 𝕨=2) (¬hasChrArr)charArr?
currRes charAtmcharArrresChr
currRes@?
twnumcharAtmtyityc txnumtyName trnumcurrRestyityc
tw@? tx@? tr@?
siName id, argarr, 𝕨"?ce", '_'¨ twtxtr
𝕨 { 𝕊:
siSrc "'", siName, "'=arithSA{", '0'+ 𝕨@, onlyFirst02, 1, ',', si, ',', '0'+swap, (',' 'u'('c'))¨ twtxtr, '}', nl
singeliASFns <siName
} ¬(<siName)singeliASFns
siName;
"failAtomArr"'0'+𝕨
}¨ num@1234567,
num@234@67@
" {.f1=",f1,", .f2=",f2,"},", nl
}¨ 1+7
" },", nl
" .chrAtom = ", hadChrArr"NULL"{𝕊: "&",cbqn,"DyTable", swap "CA"} @, ",", nl
" .mainFn = ", cbqn, "_c2", swap/"R", ",", nl
" .repr = """, repr, """", nl
"};", nl
hadChrArr charAtm
}¨ 2(("ci"¨)) swap(2)¨ choices
}¨ (2-commutative) 0{𝕩.sa} 1{𝕩.as}
siSrc nl
}
@ -150,52 +202,57 @@ Make ← {𝕊ns:
commutative1 repr"+" cbqn"add" si"__add" id"add"
aa_a c_numDiagci8c8c8, ci16c16c16, ei32c32c32, xsqc8f64@, xsqc16f64@, xsqc32f64@ci8i16i16, ci8i32i32, ci16i32i32
aa_b w_numDiagei8c8c16, ei16c16c32
sa"iii""icc""cic" overflowEq1
}
Make {
commutative0 repr"-" cbqn"sub" si"__sub" id"sub"
aa_a c_numDiagcc8c8i8, cc16c16i16, uc32c32i32cc8i8c8, cc16i16c16, ec32i32c32xsqc8f64@, xsqc16f64@, xsqc32f64@
aa_b w_numDiaguc8c8i16, uc16c16i32 ec8i8c16, ec16i16c32
sa"iii""cic""cci" overflowEq1
}
Make¨ { reprcbqn:
commutative1 reprcbqn si"__mul" id"mul"
aa_a bitandc_numDiag # ∾⟨u‿bit‿i8‿i8, u‿bit‿i16‿i16, u‿bit‿i32‿i32, u‿bit‿f64‿f64⟩
aa_b w_numDiag # TODO readd ↑
sa"iii" overflowEq1
}¨ "×""mul", "∧""and"
Make {
commutative1 repr"" cbqn"or" si"bqn_or" id"or"
aa_a bitorrsqf64f64f64 # TODO maybe new instr to squeeze arguments & try to go bitarr-bitarr
aa_b # and maybe use that for ∧ but not ×
sa overflowEq1
}
Make {
commutative1 repr"⌊" cbqn"floor" si"min" id"min"
aa_a bitandu_numDiag aa_b
sa"iii" overflowEq0
}
Make {
commutative1 repr"⌈" cbqn"ceil" si"max" id"max"
aa_a bitoru_numDiag aa_b
sa"iii" overflowEq0
}
# Make¨ { repr‿cbqn‿si:
# commutative⇐0 ⋄ repr‿cbqn‿si⇐ ⋄ id⇐cbqn
# aa_a ⇐ ⟨rsq‿f64‿f64‿f64⟩ ⋄ aa_b ⇐ ⟨⟩
# sa⇐"i" ⋄ as⇐"i" ⋄ overflowEq⇐1
# }¨ ⟨"÷"‿"div"‿"__div", "√"‿"root"‿@, "|"‿"stile"‿@, "⋆"‿"pow"‿@, "⋆⁼"‿"log"‿@⟩
}
siSrc ""
GenSingeli { 𝕊namewxrtmsi:
si@?
siSrc "'", name, "'=arithAA{", '0'+tm, ',', si, ',', wtySiType, ',', xtySiType, ',', rtySiType, '}', nl;
siSrc "'", name, "'=arithAA{", '0'+tm, ',', si, ',', wtySiName, ',', xtySiName, ',', rtySiName, '}', nl;
# else
@
}
GenSingeli¨ singeliFns
GenSingeli¨ singeliAAFns
{𝕊:
impls •FChars siSrc
tables •FChars cSrc
}{𝕊:
# •Out cSrc
•Out cSrc
•Out siSrc
1
} debug
} debug