diff --git a/src/builtins/fns.c b/src/builtins/fns.c index dd4aa7bd..ebc416b7 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -206,15 +206,14 @@ B fne_c2(B t, B w, B x) { extern B eq_c2(B, B, B); -extern B drop_c2(B, B, B); extern B slash_c1(B, B); extern B rt_find; B find_c2(B t, B w, B x) { ur wr = isAtm(w) ? 0 : RNK(w); ur xr = isAtm(x) ? 0 : RNK(x); if (wr > xr) thrF("⍷: Rank of 𝕨 must be at most rank of 𝕩 (%i≡=𝕨, %i≡=𝕩)", wr, xr); - u8 xe; - if (xr==1 && (xe=TI(x,elType))!=el_B && xe!=el_bit && (isAtm(w) || TI(w,elType)!=el_B)) { + u8 xe, we; + if (xr==1 && (xe=TI(x,elType))!=el_B && xe!=el_bit && (isAtm(w) || (we=TI(w,elType))!=el_B)) { if (wr == 0) return C2(eq, w, x); usz wl = IA(w); usz xl = IA(x); @@ -237,20 +236,19 @@ B find_c2(B t, B w, B x) { usz s = bit_sum(rp, rl); if (s == 0) break; // Switch to verifying matches individually - if (s < rl/32 && rl <= I32_MAX) { + if (s < rl/16 && rl <= I32_MAX && we != el_bit) { B ind = C1(slash, incG(r)); if (TI(ind,elType)!=el_i32) ind = taga(cpyI32Arr(ind)); usz ni = IA(ind); i32* ip = i32any_ptr(ind); - B ws = C2(drop, m_f64(i), incG(w)); - BSS2A slice = TI(x,slice); + u8* wp = (u8*)tyany_ptr(w) + i*elWidth(we); + usz eq_idx = EQFN_INDEX(we, xe); + EqFn equalp = eqFns[eq_idx]; u8 ed = eqFnData[eq_idx]; for (usz ii = 0; ii < ni; ii++) { usz j = ip[ii]; - B sl = taga(arr_shVec(slice(incG(x), i+j, wl-i))); - if (!equal(ws, sl)) bitp_set(rp, j, 0); - decG(sl); + if (!equalp(wp, xp + (i+j)*xw, wl-i, ed)) bitp_set(rp, j, 0); } - decG(ind); decG(ws); + decG(ind); break; } } diff --git a/src/core/stuff.c b/src/core/stuff.c index 1bccc180..f8cd20e5 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -404,9 +404,6 @@ NOINLINE bool atomEqualF(B w, B x) { // Functions in eqFns compare segments for matching // data argument comes from eqFnData -typedef bool (*EqFn)(void* a, void* b, u64 l, u64 data); -bool notEq(void* a, void* b, u64 l, u64 data) { return false; } - static const u8 n = 99; u8 eqFnData[] = { // for the main diagonal, amount to shift length by; otherwise, whether to swap arguments 0,0,0,0,0,n,n,n, @@ -462,6 +459,7 @@ u8 eqFnData[] = { // for the main diagonal, amount to shift length by; otherwise #undef DEF_EQ_I #undef DEF_EQ #endif +bool notEq(void* a, void* b, u64 l, u64 data) { return false; } EqFn eqFns[] = { F(1_1), F(1_8), F(1_16), F(1_32), F(1_f64), notEq, notEq, notEq, F(1_8), F(8_8), F(s8_16), F(s8_32), F(s8_f64), notEq, notEq, notEq, @@ -496,7 +494,7 @@ NOINLINE bool equal(B w, B x) { // doesn't consume u8 xe = TI(x,elType); if (we<=el_c32 && xe<=el_c32) { // remove & pass a(w) and a(x) to fn so it can do basic loop - u64 idx = we*8 + xe; + usz idx = EQFN_INDEX(we, xe); return eqFns[idx](tyany_ptr(w), tyany_ptr(x), ia, eqFnData[idx]); } return equalSlow(w, x, ia); diff --git a/src/utils/calls.h b/src/utils/calls.h index f6ba9704..360a9c9c 100644 --- a/src/utils/calls.h +++ b/src/utils/calls.h @@ -35,4 +35,10 @@ CMP_DEF(le, AS); #define CMP_AA_IMM(FN, ELT, WHERE, WP, XP, LEN) CMP_AA_CALL(CMP_AA_FN(FN, ELT), WHERE, WP, XP, LEN) #define CMP_AS_IMM(FN, ELT, WHERE, WP, X, LEN) CMP_AS_CALL(CMP_AS_FN(FN, ELT), WHERE, WP, X, LEN) +// Check if the l elements starting at a and b match +typedef bool (*EqFn)(void* a, void* b, u64 l, u64 data); +extern EqFn eqFns[]; +extern u8 eqFnData[]; +#define EQFN_INDEX(W_ELT, X_ELT) ((W_ELT)*8 + (X_ELT)) + void bit_negatePtr(u64* rp, u64* xp, usz count); // count is number of u64-s