randomizable squeeze

This commit is contained in:
dzaima 2025-05-26 01:21:09 +03:00
parent 60cefa158b
commit 3ab5c87a76
13 changed files with 74 additions and 24 deletions

View File

@ -83,7 +83,7 @@ B add_c1(B t, B x) {
} }
B sub_c2(B,B,B); B sub_c2(B,B,B);
#define SUB_BODY(FEXPR) return sub_c2(t, m_f64(0), x); #define SUB_BODY(FEXPR) return sub_c2(t, m_f64(0), x);
#define NOT_BODY(FEXPR) x = squeeze_numTry(x, &xe); return xe==el_bit? bit_negate(x) : C2(sub, m_f64(1), x); #define NOT_BODY(FEXPR) x = squeeze_numTry(x, &xe, SQ_ANY); return xe==el_bit? bit_negate(x) : C2(sub, m_f64(1), x);
GC1i("-", sub, -v, el_bit, bit_sel(x,m_f64(0),m_f64(-1)), SUB_BODY) GC1i("-", sub, -v, el_bit, bit_sel(x,m_f64(0),m_f64(-1)), SUB_BODY)
GC1i("|", stile, fabs(v), el_bit, x, STILE_BODY) GC1i("|", stile, fabs(v), el_bit, x, STILE_BODY)

View File

@ -730,7 +730,7 @@ NOINLINE B for_cells_SA(B f, B w, B x, ur xcr, ur xr, u32 chr) { // w⊸F⎉xcr
if (isArr(w) && xcr==1) { if (isArr(w) && xcr==1) {
if (!TI(w,arrD1)) { if (!TI(w,arrD1)) {
u8 xe; u8 xe;
w = squeeze_numTry(w, &xe); w = squeeze_numTry(w, &xe, SQ_ANY);
if (xe==el_B) break; if (xe==el_B) break;
} }
assert(xr > 1); assert(xr > 1);

View File

@ -280,7 +280,7 @@ B group_c2(B t, B w, B x) {
ur xr = RNK(x); ur xr = RNK(x);
if (isArr(w) && RNK(w)==1 && xr>=1) { if (isArr(w) && RNK(w)==1 && xr>=1) {
u8 we = TI(w,elType); u8 we = TI(w,elType);
if (!elInt(we)) w = squeeze_numTry(w, &we); if (!elInt(we)) w = squeeze_numTry(w, &we, SQ_ANY);
if (elInt(we)) { if (elInt(we)) {
usz wia = IA(w); usz wia = IA(w);
usz* xsh = SH(x); usz* xsh = SH(x);

View File

@ -337,7 +337,7 @@ B scan_c1(Md1D* d, B x) { B f = d->f;
if (xe==el_i32) { i32* xp=i32any_ptr(x); for (usz i=1; i<ia; i++) { c = c!=xp[i]; bitp_set(rp,i,c); } decG(x); return r; } if (xe==el_i32) { i32* xp=i32any_ptr(x); for (usz i=1; i<ia; i++) { c = c!=xp[i]; bitp_set(rp,i,c); } decG(x); return r; }
UD; UD;
} }
if (rtid==n_or) { x=squeeze_numTry(x, &xe); if (xe==el_bit) return scan_or(x, ia); } if (rtid==n_or) { x=squeeze_numTry(x, &xe, SQ_ANY); if (xe==el_bit) return scan_or(x, ia); }
} }
base:; base:;
if (ia!=n && ia >= 6 * (u64)n && isPervasiveDy(f)) return scan_arith(f, m_f64(0), x, SH(x)); if (ia!=n && ia >= 6 * (u64)n && isPervasiveDy(f)) return scan_arith(f, m_f64(0), x, SH(x));

View File

@ -230,7 +230,7 @@ B select_c2(B t, B w, B x) {
decG(w); decG(w);
u8 w0e = TI(w0,elType); u8 w0e = TI(w0,elType);
if (elNum(w0e)) return C2(select, w0, x); if (elNum(w0e)) return C2(select, w0, x);
w0 = squeeze_numTry(w0, &w0e); w0 = squeeze_numTry(w0, &w0e, SQ_MSGREQ(SQ_NUM));
if (elNum(w0e)) return C2(select, w0, x); if (elNum(w0e)) return C2(select, w0, x);
w = m_vec1(w0); w = m_vec1(w0);
} }
@ -372,7 +372,7 @@ B select_c2(B t, B w, B x) {
// else fallthrough - want to do integer 𝕨 if possible // else fallthrough - want to do integer 𝕨 if possible
} }
case el_B: case el_c8: case el_c16: case el_c32: { case el_B: case el_c8: case el_c16: case el_c32: {
w = squeeze_numTry(w, &we); w = squeeze_numTry(w, &we, SQ_MSGREQ(SQ_NUM));
if (RANDOMIZE_HEURISTICS && we==el_f64) goto generic_l; // avoid infinite loop if (RANDOMIZE_HEURISTICS && we==el_f64) goto generic_l; // avoid infinite loop
if (elNum(we)) goto retry; if (elNum(we)) goto retry;
goto def_xf_base; goto def_xf_base;
@ -952,7 +952,7 @@ B select_rows_B(B x, ux csz, ux cam, B inds) { // consumes inds,x; ⥊ inds⊸
} }
u8 ie = TI(inds,elType); u8 ie = TI(inds,elType);
if (csz<=2? ie!=el_bit : csz<=128? ie>el_i8 : !elInt(ie)) { if (csz<=2? ie!=el_bit : csz<=128? ie>el_i8 : !elInt(ie)) {
inds = squeeze_numTry(inds, &ie); inds = squeeze_numTry(inds, &ie, SQ_BEST);
if (!elInt(ie)) goto generic; if (!elInt(ie)) goto generic;
} }
void* ip = tyany_ptr(inds); void* ip = tyany_ptr(inds);
@ -1023,7 +1023,7 @@ B select_ucw(B t, B o, B w, B x) {
} else { } else {
we = TI(w,elType); we = TI(w,elType);
if (!elInt(we)) { if (!elInt(we)) {
w = squeeze_numTry(w, &we); w = squeeze_numTry(w, &we, SQ_MSGREQ(SQ_NUM));
if (!elNum(we)) goto def; if (!elNum(we)) goto def;
} }
} }

View File

@ -1207,7 +1207,7 @@ NOINLINE B rotate_highrank(bool inv, B w, B x) {
if (wia==0) { r=x; goto decW_ret; } if (wia==0) { r=x; goto decW_ret; }
u8 we = TI(w,elType); u8 we = TI(w,elType);
if (!elNum(we)) { if (!elNum(we)) {
w = squeeze_numTry(w, &we); w = squeeze_numTry(w, &we, SQ_NUM);
if (!elNum(we)) thrF("𝕨⌽%U𝕩: 𝕨 contained non-number", INV); if (!elNum(we)) thrF("𝕨⌽%U𝕩: 𝕨 contained non-number", INV);
} }
bool origF64 = we==el_f64; bool origF64 = we==el_f64;

View File

@ -577,7 +577,7 @@ B slash_c1(B t, B x) {
usz xia = IA(x); usz xia = IA(x);
B r; B r;
u8 xe = TI(x,elType); u8 xe = TI(x,elType);
if (xe!=el_bit && s<=xia) x = squeeze_numTry(x, &xe); if (xe!=el_bit && s<=xia) x = squeeze_numTry(x, &xe, SQ_NUM);
if (xe==el_bit) { if (xe==el_bit) {
r = where(x, xia, s); r = where(x, xia, s);
} else if (RARE(xia > (usz)I32_MAX+1)) { } else if (RARE(xia > (usz)I32_MAX+1)) {
@ -630,7 +630,7 @@ B slash_c2(B t, B w, B x) {
if (isArr(w)) { if (isArr(w)) {
we = TI(w,elType); we = TI(w,elType);
if (!elInt(we)) { if (!elInt(we)) {
w = squeeze_numTry(w, &we); w = squeeze_numTry(w, &we, SQ_MSGREQ(SQ_NUM));
if (!elNum(we)) goto base; if (!elNum(we)) goto base;
} }
ur wr = RNK(w); ur wr = RNK(w);
@ -670,7 +670,7 @@ B slash_c2(B t, B w, B x) {
if (xl>6 || (xl<3 && xl!=0)) goto arrW_base; if (xl>6 || (xl<3 && xl!=0)) goto arrW_base;
if (s<=wia) { if (s<=wia) {
if (s==0) { r = zeroCells(x); goto decWX_ret; } if (s==0) { r = zeroCells(x); goto decWX_ret; }
w = squeeze_numTry(w, &we); w = squeeze_numTry(w, &we, SQ_NUM);
if (we==el_bit) goto wbool; if (we==el_bit) goto wbool;
} }
// s≠0 now // s≠0 now
@ -1021,7 +1021,7 @@ B slash_im(B t, B x) {
break; break;
} }
case el_c8: case el_c16: case el_c32: case el_B: { case el_c8: case el_c16: case el_c32: case el_B: {
x = squeeze_numTry(x, &xe); x = squeeze_numTry(x, &xe, SQ_NUM);
if (elNum(xe)) goto retry; if (elNum(xe)) goto retry;
B* xp = TO_BPTR(x); B* xp = TO_BPTR(x);
for (usz i=0; i<xia; i++) o2i64(xp[i]); for (usz i=0; i<xia; i++) o2i64(xp[i]);
@ -1069,7 +1069,7 @@ B slash_ucw(B t, B o, B w, B x) {
usz ia = IA(x); usz ia = IA(x);
u8 we = TI(w,elType); u8 we = TI(w,elType);
if (we != el_bit) { if (we != el_bit) {
w = squeeze_numTry(w, &we); w = squeeze_numTry(w, &we, SQ_NUM);
if (we != el_bit) { if (we != el_bit) {
if (!elNum(we)) goto base; if (!elNum(we)) goto base;
i64 bounds[2]; i64 bounds[2];

View File

@ -121,7 +121,7 @@ B parseFloat_c1(B t, B x) {
if (isAtm(x)) thrM("•ParseFloat 𝕩: Expected a character list argument"); if (isAtm(x)) thrM("•ParseFloat 𝕩: Expected a character list argument");
if (TI(x,elType)!=el_c8) { if (TI(x,elType)!=el_c8) {
u8 xe; u8 xe;
x = squeeze_chrTry(x, &xe); x = squeeze_chrTry(x, &xe, SQ_BEST);
if (xe!=el_c8) { if (xe!=el_c8) {
if (IA(x)==0) goto empty; if (IA(x)==0) goto empty;
if (elChr(xe)) malformed: thrM("•ParseFloat 𝕩: Malformed input"); if (elChr(xe)) malformed: thrM("•ParseFloat 𝕩: Malformed input");

View File

@ -131,10 +131,10 @@ B withFill(B x, B fill) { // consumes both
if (!FL_HAS(x,fl_squoze)) { if (!FL_HAS(x,fl_squoze)) {
u8 xe; u8 xe;
if (isNum(fill)) { if (isNum(fill)) {
x = squeeze_numTry(x, &xe); x = squeeze_numTry(x, &xe, SQ_ANY);
if (elNum(xe)) return x; if (elNum(xe)) return x;
} else if (isC32(fill)) { } else if (isC32(fill)) {
x = squeeze_chrTry(x, &xe); x = squeeze_chrTry(x, &xe, SQ_ANY);
if (elChr(xe)) return x; if (elChr(xe)) return x;
} }
} }

View File

@ -630,10 +630,46 @@ DEBUG_FN void g_pst(void) { vm_pstLive(); fflush(stdout); fflush(stderr); }
#if RANDOMIZE_HEURISTICS #if RANDOMIZE_HEURISTICS
#include "../utils/wyhash.h" #include "../utils/wyhash.h"
#ifndef MATCH_ERROR_MESSAGES
#define MATCH_ERROR_MESSAGES 1
#endif
u64 seed; u64 seed;
bool heuristic_rand(bool heuristic, bool true_req, bool false_req) { bool heuristic_rand(bool heuristic, bool true_req, bool false_req) {
assert(heuristic? true_req : false_req); assert(heuristic? true_req : false_req);
if (!true_req | !false_req) return heuristic; if (!true_req | !false_req) return heuristic;
return wyrand(&seed) & 1; return wyrand(&seed) & 1;
} }
SqRes squeeze_numTryImpl(B x);
SqRes squeeze_chrTryImpl(B x);
static u32 squeeze_processReq(u32 req) {
if (MATCH_ERROR_MESSAGES) {
req|= req / SQ_MSGREQ(1);
}
return req & (SQ_NUM|SQ_INT|SQ_CHR|SQ_BEST);
}
static SqRes squeeze_ret(B x) {
return (SqRes){x, TI(x,elType)};
}
// TODO randomize level of squeezing
SqRes squeeze_numTryRand(B x, u32 req) {
req = squeeze_processReq(req);
u8 xe = TI(x,elType);
if (MAY_T(req&SQ_BEST)) return squeeze_numTryImpl(x);
if ((req&SQ_NUM) && !elNum(xe)) return squeeze_numTryImpl(x);
if ((req&SQ_INT) && !elInt(xe)) return squeeze_numTryImpl(x);
return squeeze_ret(x);
}
SqRes squeeze_chrTryRand(B x, u32 req) {
req = squeeze_processReq(req);
u8 xe = TI(x,elType);
if (MAY_T(req&SQ_BEST)) return squeeze_chrTryImpl(x);
if ((req&SQ_CHR) && !elChr(xe)) return squeeze_chrTryImpl(x);
return squeeze_ret(x);
}
#endif #endif

View File

@ -283,17 +283,31 @@ B squeeze_any(B x); // consumes; accepts any array, returns one with the smalles
B squeeze_deep(B x); // consumes; accepts any object, returns an object with all parts necessary for equality checking & hashing squeezed; if this function errors due to OOM, the argument won't yet be consumed B squeeze_deep(B x); // consumes; accepts any object, returns an object with all parts necessary for equality checking & hashing squeezed; if this function errors due to OOM, the argument won't yet be consumed
typedef struct { B r; u8 re; } SqRes; typedef struct { B r; u8 re; } SqRes;
#define SQ_UNPACK(F) SqRes r = F(x); *re_out = r.re; assert(r.re == TI(r.r,elType)); return r.r;
#if RANDOMIZE_HEURISTICS
SqRes squeeze_numTryRand(B x, u32 req);
SqRes squeeze_chrTryRand(B x, u32 req);
#define SQ_UNPACK(F) SqRes r = F##Rand(x, req); *re_out = r.re; assert(r.re == TI(r.r,elType)); return r.r;
#else
SqRes squeeze_numTryImpl(B x); SqRes squeeze_numTryImpl(B x);
SqRes squeeze_chrTryImpl(B x); SqRes squeeze_chrTryImpl(B x);
#define SQ_UNPACK(F) SqRes r = F##Impl(x); *re_out = r.re; assert(r.re == TI(r.r,elType)); return r.r;
#endif
B squeeze_numNew(B x); // consumes; doesn't try using any existing flags; primarily intended for squeezing a newly-created array; returns bitarr for IA(x)==0 B squeeze_numNew(B x); // consumes; doesn't try using any existing flags; primarily intended for squeezing a newly-created array; returns bitarr for IA(x)==0
B squeeze_chrNew(B x); // consumes; doesn't try using any existing flags; primarily intended for squeezing a newly-created array; returns c8arr for IA(x)==0 B squeeze_chrNew(B x); // consumes; doesn't try using any existing flags; primarily intended for squeezing a newly-created array; returns c8arr for IA(x)==0
static B squeeze_numNewTy(u8 xe, B x) { debug_assert(TI(x,elType)==xe); return squeeze_numNew(x); } // squeeze_numNew but with a known eltype; currently eltype isn't used for anything static B squeeze_numNewTy(u8 xe, B x) { debug_assert(TI(x,elType)==xe); return squeeze_numNew(x); } // squeeze_numNew but with a known eltype; currently eltype isn't used for anything
static B squeeze_numTry(B x, u8* re_out) { SQ_UNPACK(squeeze_numTryImpl) } // consumes; always returns bitarr for IA(x)==0; utilizes squoze/sortedness flags static B squeeze_numTry(B x, u8* re_out, u32 req) { SQ_UNPACK(squeeze_numTry) } // consumes; always returns bitarr for IA(x)==0; utilizes squoze/sortedness flags
static B squeeze_chrTry(B x, u8* re_out) { SQ_UNPACK(squeeze_chrTryImpl) } // consumes; always returns bitarr for IA(x)==0; utilizes squoze/sortedness flags static B squeeze_chrTry(B x, u8* re_out, u32 req) { SQ_UNPACK(squeeze_chrTry) } // consumes; always returns bitarr for IA(x)==0; utilizes squoze flag
// req parameter options (these matter for heuristic randomization, but otherwise are unused):
#define SQ_ANY 0 // no requirements placed on result, i.e. can be a no-op or even widen type
#define SQ_INT 1 // must squeeze to elInt(xe) if possible
#define SQ_CHR 1 // must squeeze to elChr(xe) if possible
#define SQ_NUM 2 // must squeeze to elNum(xe) if possible
#define SQ_BEST 4 // must squeeze to smallest type possible
#define SQ_MSGREQ(X) ((X)<<8) // if the settings in X aren't followed, different error messages may be produced
B squeeze_numOut(B x); // consumes; squeeze_numTry but without re_out B squeeze_numOut(B x); // consumes; squeeze_numTry but without re_out
B squeeze_chrOut(B x); // consumes; squeeze_chrTry but without re_out B squeeze_chrOut(B x); // consumes; squeeze_chrTry but without re_out

View File

@ -330,7 +330,7 @@ static u32 styG(B x) {
if (nonChr.u!=bi_N.u) thrF("FFI: Array provided for :c%S contained %S", desc+1, genericDesc(nonChr)); if (nonChr.u!=bi_N.u) thrF("FFI: Array provided for :c%S contained %S", desc+1, genericDesc(nonChr));
u8 xe = TI(x,elType); u8 xe = TI(x,elType);
if (elChrOk(x, umax, xe)) return; if (elChrOk(x, umax, xe)) return;
B sq = squeeze_chrTry(incG(x), &xe); B sq = squeeze_chrTry(incG(x), &xe, SQ_BEST);
bool ok = elChrOk(sq, umax, xe); bool ok = elChrOk(sq, umax, xe);
decG(sq); decG(sq);
if (!ok) { if (!ok) {

View File

@ -97,7 +97,7 @@ NOINLINE B dyArith_AA(DyTableAA* table, B w, B x) {
case e_call_sqx: { case e_call_sqx: {
u8 xe = TI(x,elType); u8 xe = TI(x,elType);
assert(xe==el_f64); assert(xe==el_f64);
x = squeeze_numTry(x, &xe); x = squeeze_numTry(x, &xe, SQ_NUM);
if (xe==el_f64) goto rec; if (xe==el_f64) goto rec;
e = &table->entsAA[TI(w,elType)*8 + xe]; e = &table->entsAA[TI(w,elType)*8 + xe];
goto newEnt; goto newEnt;
@ -189,7 +189,7 @@ NOINLINE B dyArith_SA(DyTableSA* table, B w, B x) {
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_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_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_i32: e=&table->ents[el_i32]; width=2; type=t_c32arr; goto f1;
case el_f64: x=squeeze_numTry(x, &xe); if (xe!=el_f64) goto newXEc; else goto rec; case el_f64: x=squeeze_numTry(x, &xe, SQ_CHR); 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_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_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_c32: e=&table->ents[el_c32]; width=2; type=t_i32arr; goto f1;
@ -288,7 +288,7 @@ static NOINLINE B or_SA(B t, B w, B x) {
f64 wf = o2fG(w); f64 wf = o2fG(w);
return bit_sel(x, m_f64(bqn_or(wf, 0)), m_f64(bqn_or(wf, 1))); return bit_sel(x, m_f64(bqn_or(wf, 0)), m_f64(bqn_or(wf, 1)));
} }
x = squeeze_numTry(x, &xe); x = squeeze_numTry(x, &xe, SQ_NUM);
if (xe==el_bit) goto bitsel; if (xe==el_bit) goto bitsel;
if (!elNum(xe)) return arith_recd(or_c2, w, x); if (!elNum(xe)) return arith_recd(or_c2, w, x);
x = toF64Any(x); x = toF64Any(x);