From d2950a8df6c232dc190127ee505006d0dfbcc0a1 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sun, 19 Feb 2023 20:34:32 -0500 Subject: [PATCH 1/7] Flat rank 1 Find implementation using primitive calls --- src/builtins/fns.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/builtins/fns.c b/src/builtins/fns.c index 3268c6de..4a026150 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -205,8 +205,53 @@ B fne_c2(B t, B w, B x) { } +extern B eq_c2(B, B, B); +extern B take_c2(B, B, B); +extern B drop_c2(B, B, B); +extern B and_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); + if (xr==1 && TI(x,elType)!=el_B && (isAtm(w) || TI(w,elType)!=el_B)) { + if (wr == 0) return C2(eq, w, x); + usz wl = IA(w); + usz xl = IA(x); + if (wl > xl) { decG(w); decG(x); return emptyIVec(); } + if (wl == 0) { decG(w); decG(x); return taga(arr_shVec(allOnes(xl+1))); } + // Compare elements of w to slices of x + SGetU(w) + usz rl = xl - wl + 1; B rt = m_f64(rl); // Result length + B e = C2(eq, GetU(w,0), C2(take, rt, incG(x))); + for (usz i = 1; i < wl; i++) { + B slice = C2(take, rt, C2(drop, m_f64(i), incG(x))); + e = C2(and, e, C2(eq, GetU(w,i), slice)); + assert(TI(e,elType) == el_bit); + ux* ep = bitarr_ptr(e); + usz s = bit_sum(ep, rl); + if (s == 0) break; + // Switch to verifying matches individually + if (s < rl/256 && rl <= I32_MAX) { + B ind = C1(slash, incG(e)); + 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)); + for (usz ii = 0; ii < ni; ii++) { + usz j = ip[ii]; + B slice = C2(take, m_f64(wl-i), C2(drop, m_f64(i+j), incG(x))); + if (!equal(ws, slice)) bitp_set(ep, j, 0); + decG(slice); + } + decG(ind); decG(ws); + break; + } + } + decG(x); decG(w); + return e; + } return c2rt(find, w, x); } From ea6c7d9a7ab52d82293332ee4d10d77ffe0b3bb4 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sun, 19 Feb 2023 21:08:21 -0500 Subject: [PATCH 2/7] Use a C comparison function instead of a BQN one --- src/builtins/fns.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/builtins/fns.c b/src/builtins/fns.c index 4a026150..8e97dbbf 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -208,14 +208,14 @@ B fne_c2(B t, B w, B x) { extern B eq_c2(B, B, B); extern B take_c2(B, B, B); extern B drop_c2(B, B, B); -extern B and_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); - if (xr==1 && TI(x,elType)!=el_B && (isAtm(w) || TI(w,elType)!=el_B)) { + u8 xe; + if (xr==1 && (xe=TI(x,elType))!=el_B && xe!=el_bit && (isAtm(w) || TI(w,elType)!=el_B)) { if (wr == 0) return C2(eq, w, x); usz wl = IA(w); usz xl = IA(x); @@ -223,18 +223,23 @@ B find_c2(B t, B w, B x) { if (wl == 0) { decG(w); decG(x); return taga(arr_shVec(allOnes(xl+1))); } // Compare elements of w to slices of x SGetU(w) - usz rl = xl - wl + 1; B rt = m_f64(rl); // Result length - B e = C2(eq, GetU(w,0), C2(take, rt, incG(x))); + usz rl = xl - wl + 1; // Result length + u8* xp = tyany_ptr(x); + u64* rp; B r = m_bitarrv(&rp, rl); + CmpASFn eq = CMP_AS_FN(eq, xe); + CMP_AS_CALL(eq, rp, xp, GetU(w,0), rl); + if (wl == 1) goto dec_ret; + usz xw = elWidth(xe); + usz rb = BIT_N(rl); + TALLOC(u64, eq_res, rb); for (usz i = 1; i < wl; i++) { - B slice = C2(take, rt, C2(drop, m_f64(i), incG(x))); - e = C2(and, e, C2(eq, GetU(w,i), slice)); - assert(TI(e,elType) == el_bit); - ux* ep = bitarr_ptr(e); - usz s = bit_sum(ep, rl); + CMP_AS_CALL(eq, eq_res, xp + i*xw, GetU(w,i), rl); + for (usz b = 0; b < rb; b++) rp[b] &= eq_res[b]; + usz s = bit_sum(rp, rl); if (s == 0) break; // Switch to verifying matches individually if (s < rl/256 && rl <= I32_MAX) { - B ind = C1(slash, incG(e)); + 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); @@ -242,15 +247,16 @@ B find_c2(B t, B w, B x) { for (usz ii = 0; ii < ni; ii++) { usz j = ip[ii]; B slice = C2(take, m_f64(wl-i), C2(drop, m_f64(i+j), incG(x))); - if (!equal(ws, slice)) bitp_set(ep, j, 0); + if (!equal(ws, slice)) bitp_set(rp, j, 0); decG(slice); } decG(ind); decG(ws); break; } } - decG(x); decG(w); - return e; + TFREE(eq_res); + dec_ret:; + decG(x); decG(w); return r; } return c2rt(find, w, x); } From fcc5c2e4491d8e1acf494f33cc79f1f64a1e54e0 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sun, 19 Feb 2023 21:14:42 -0500 Subject: [PATCH 3/7] Slice function instead of take/drop --- src/builtins/fns.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/builtins/fns.c b/src/builtins/fns.c index 8e97dbbf..dd4aa7bd 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -206,7 +206,6 @@ B fne_c2(B t, B w, B x) { extern B eq_c2(B, B, B); -extern B take_c2(B, B, B); extern B drop_c2(B, B, B); extern B slash_c1(B, B); extern B rt_find; @@ -238,17 +237,18 @@ 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/256 && rl <= I32_MAX) { + if (s < rl/32 && rl <= I32_MAX) { 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); for (usz ii = 0; ii < ni; ii++) { usz j = ip[ii]; - B slice = C2(take, m_f64(wl-i), C2(drop, m_f64(i+j), incG(x))); - if (!equal(ws, slice)) bitp_set(rp, j, 0); - decG(slice); + B sl = taga(arr_shVec(slice(incG(x), i+j, wl-i))); + if (!equal(ws, sl)) bitp_set(rp, j, 0); + decG(sl); } decG(ind); decG(ws); break; From b56e547e343ab77e81116fb8f4c57dc7654347fe Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 20 Feb 2023 08:20:05 -0500 Subject: [PATCH 4/7] Define eqFns in non-Singeli build --- src/core/stuff.c | 121 +++++++++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 50 deletions(-) diff --git a/src/core/stuff.c b/src/core/stuff.c index 84752482..1bccc180 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -402,37 +402,77 @@ NOINLINE bool atomEqualF(B w, B x) { decG(wd);decG(xd); return true; } +// 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, + 1,0,0,0,0,n,n,n, + 1,1,1,0,0,n,n,n, + 1,1,1,2,0,n,n,n, + 1,1,1,1,0,n,n,n, + n,n,n,n,n,0,0,0, + n,n,n,n,n,1,1,0, + n,n,n,n,n,1,1,2, +}; + #if SINGELI + #define F(X) avx2_equal_##X #define SINGELI_FILE equal #include "../utils/includeSingeli.h" - - typedef bool (*EqFn)(void* a, void* b, u64 l, u64 data); - bool notEq(void* a, void* b, u64 l, u64 data) { return false; } - - #define F(X) avx2_equal_##X - 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, - F(1_16), F(s8_16), F(8_8), F(s16_32), F(s16_f64), notEq, notEq, notEq, - F(1_32), F(s8_32), F(s16_32), F(8_8), F(s32_f64), notEq, notEq, notEq, - F(1_f64), F(s8_f64), F(s16_f64), F(s32_f64), F(f64_f64), notEq, notEq, notEq, - notEq, notEq, notEq, notEq, notEq, F(8_8), F(u8_16), F(u8_32), - notEq, notEq, notEq, notEq, notEq, F(u8_16), F(8_8), F(u16_32), - notEq, notEq, notEq, notEq, notEq, F(u8_32), F(u16_32), F(8_8), - }; - #undef F - 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, - 1,0,0,0,0,n,n,n, - 1,1,1,0,0,n,n,n, - 1,1,1,2,0,n,n,n, - 1,1,1,1,0,n,n,n, - n,n,n,n,n,0,0,0, - n,n,n,n,n,1,1,0, - n,n,n,n,n,1,1,2, - }; +#else + #define F(X) equal_##X + bool F(1_1)(void* w, void* x, u64 l, u64 d) { + u64* wp = w; u64* xp = x; + usz q = l/64; + for (usz i=0; i Date: Mon, 20 Feb 2023 08:44:12 -0500 Subject: [PATCH 5/7] Add eqFns to calls.h and use for Find --- src/builtins/fns.c | 18 ++++++++---------- src/core/stuff.c | 6 ++---- src/utils/calls.h | 6 ++++++ 3 files changed, 16 insertions(+), 14 deletions(-) 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 From 032e32ae1a457f184f0c8ddabe9e851024b20645 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 20 Feb 2023 10:43:24 -0500 Subject: [PATCH 6/7] =?UTF-8?q?Fast=20flat=20=E2=89=A1=CB=98=20and=20?= =?UTF-8?q?=E2=89=A2=CB=98=20in=20most=20cases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/md1.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/builtins/md1.c b/src/builtins/md1.c index f75a90ff..fdfd4d22 100644 --- a/src/builtins/md1.c +++ b/src/builtins/md1.c @@ -284,6 +284,37 @@ static NOINLINE B shift_cells(B f, B x, u8 e, u8 rtid) { return mut_fcd(r, x); } +static B allBit(bool b, usz n) { + return taga(arr_shVec(b ? allOnes(n) : allZeroes(n))); +} +static NOINLINE B match_cells(bool ne, B w, B x, ur wr, ur xr, usz len) { + usz* wsh = SH(w); + if (wr != xr || (wr>1 && !eqShPart(wsh+1, SH(x)+1, wr-1))) { + return allBit(ne, len); + } + usz csz = shProd(wsh, 1, wr); + if (csz == 0) return allBit(!ne, len); + u8 we = TI(w,elType); + u8 xe = TI(x,elType); + if (we>el_c32 || xe>el_c32) return bi_N; + usz ww = csz * elWidth(we); u8* wp = tyany_ptr(w); + usz xw = csz * elWidth(xe); u8* xp = tyany_ptr(x); + u64* rp; B r = m_bitarrv(&rp, len); + if (csz == 1 && we == xe) { + CmpAAFn cmp = ne ? CMP_AA_FN(ne,we) : CMP_AA_FN(eq,we); + CMP_AA_CALL(cmp, rp, wp, xp, len); + } else { + if (we==el_bit || xe==el_bit) return bi_N; + usz eq_idx = EQFN_INDEX(we, xe); + EqFn equalp = eqFns[eq_idx]; u8 ed = eqFnData[eq_idx]; + for (usz i = 0; i < len; i++) { + bitp_set(rp, i, ne^equalp(wp, xp, csz, ed)); + wp += ww; xp += xw; + } + } + return r; +} + B shape_c1(B, B); B cell_c1(Md1D* d, B x) { B f = d->f; if (isAtm(x) || RNK(x)==0) { @@ -397,6 +428,13 @@ B cell_c2(Md1D* d, B w, B x) { B f = d->f; usz cam = SH(w)[0]; if (cam==0) return cell2_empty(f, w, x, wr, xr); if (cam != SH(x)[0]) thrF("˘: Leading axis of arguments not equal (%H ≔ ā‰¢š•Ø, %H ≔ ā‰¢š•©)", w, x); + if (isFun(f)) { + u8 rtid = v(f)->flags-1; + if (rtid==n_feq || rtid==n_fne) { + B r = match_cells(rtid!=n_feq, w, x, wr, xr, cam); + if (!q_N(r)) { decG(w); decG(x); return r; } + } + } S_SLICES(w) S_SLICES(x) M_HARR(r, cam); for (usz i=0,wp=0,xp=0; i Date: Wed, 22 Feb 2023 13:48:45 +0200 Subject: [PATCH 7/7] find & eqfn changes, use toI32Any more --- src/builtins/fns.c | 17 ++++++++--------- src/builtins/group.c | 8 ++++---- src/builtins/md1.c | 5 ++--- src/utils/calls.h | 3 +++ 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/builtins/fns.c b/src/builtins/fns.c index ebc416b7..78230342 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -217,14 +217,15 @@ B find_c2(B t, B w, B x) { if (wr == 0) return C2(eq, w, x); usz wl = IA(w); usz xl = IA(x); - if (wl > xl) { decG(w); decG(x); return emptyIVec(); } - if (wl == 0) { decG(w); decG(x); return taga(arr_shVec(allOnes(xl+1))); } + B r; + if (wl > xl) { r = emptyIVec(); goto dec_ret; } + if (wl == 0) { r = taga(arr_shVec(allOnes(xl+1))); goto dec_ret; } // Compare elements of w to slices of x - SGetU(w) usz rl = xl - wl + 1; // Result length u8* xp = tyany_ptr(x); - u64* rp; B r = m_bitarrv(&rp, rl); + u64* rp; r = m_bitarrv(&rp, rl); CmpASFn eq = CMP_AS_FN(eq, xe); + SGetU(w) CMP_AS_CALL(eq, rp, xp, GetU(w,0), rl); if (wl == 1) goto dec_ret; usz xw = elWidth(xe); @@ -237,16 +238,14 @@ B find_c2(B t, B w, B x) { if (s == 0) break; // Switch to verifying matches individually 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)); + B ind = toI32Any(C1(slash, incG(r))); usz ni = IA(ind); i32* ip = i32any_ptr(ind); 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]; + EqFnObj eqfn = EQFN_GET(we, xe); for (usz ii = 0; ii < ni; ii++) { usz j = ip[ii]; - if (!equalp(wp, xp + (i+j)*xw, wl-i, ed)) bitp_set(rp, j, 0); + if (!EQFN_CALL(eqfn, wp, xp + (i+j)*xw, wl-i)) bitp_set(rp, j, 0); } decG(ind); break; diff --git a/src/builtins/group.c b/src/builtins/group.c index fe0aced4..78e20c01 100644 --- a/src/builtins/group.c +++ b/src/builtins/group.c @@ -134,9 +134,9 @@ static B group_simple(B w, B x, ur xr, usz wia, usz xn, usz* xsh, u8 we) { bitp_set(mp, 0, -1!=o2fG(IGetU(w,0))); B ind = C1(slash, m); - w = C2(select, inc(ind), w); - if (TI(ind,elType)!=el_i32) ind = taga(cpyI32Arr(ind)); - if (TI(w ,elType)!=el_i32) w = taga(cpyI32Arr(w )); + w = C2(select, incG(ind), w); + ind = toI32Any(ind); + w = toI32Any(w); wia = IA(ind); i32* ip = i32any_ptr(ind); @@ -179,7 +179,7 @@ static B group_simple(B w, B x, ur xr, usz wia, usz xn, usz* xsh, u8 we) { x = C2(slash, m, x); xn = *SH(x); neg = 0; } - if (TI(w,elType)!=el_i32) w = taga(cpyI32Arr(w)); + w = toI32Any(w); i32* wp = i32any_ptr(w); for (usz i = 0; i < ria; i++) len[i] = pos[i] = 0; for (usz i = 0; i < xn; i++) len[wp[i]]++; // overallocation makes this safe after n<-1 check diff --git a/src/builtins/md1.c b/src/builtins/md1.c index fdfd4d22..bf43fd5f 100644 --- a/src/builtins/md1.c +++ b/src/builtins/md1.c @@ -305,10 +305,9 @@ static NOINLINE B match_cells(bool ne, B w, B x, ur wr, ur xr, usz len) { CMP_AA_CALL(cmp, rp, wp, xp, len); } else { if (we==el_bit || xe==el_bit) return bi_N; - usz eq_idx = EQFN_INDEX(we, xe); - EqFn equalp = eqFns[eq_idx]; u8 ed = eqFnData[eq_idx]; + EqFnObj eqfn = EQFN_GET(we, xe); for (usz i = 0; i < len; i++) { - bitp_set(rp, i, ne^equalp(wp, xp, csz, ed)); + bitp_set(rp, i, ne^EQFN_CALL(eqfn, wp, xp, csz)); wp += ww; xp += xw; } } diff --git a/src/utils/calls.h b/src/utils/calls.h index 360a9c9c..2caf5320 100644 --- a/src/utils/calls.h +++ b/src/utils/calls.h @@ -40,5 +40,8 @@ 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)) +typedef struct { EqFn fn; u8 data; } EqFnObj; +#define EQFN_GET(W_ELT, X_ELT) ({ u8 eqfn_i_ = EQFN_INDEX(W_ELT, X_ELT); (EqFnObj){.fn=eqFns[eqfn_i_], .data=eqFnData[eqfn_i_]}; }) +#define EQFN_CALL(FN, W, X, L) (FN).fn(W, X, L, (FN).data) void bit_negatePtr(u64* rp, u64* xp, usz count); // count is number of u64-s