From 9511598aa384ef9a275d4c45e2c8fe8296d91ae1 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sun, 9 Jul 2023 11:21:31 -0400 Subject: [PATCH] Fast Bins when either argument is boolean --- src/builtins/grade.h | 45 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/builtins/grade.h b/src/builtins/grade.h index 47f80e79..35efb726 100644 --- a/src/builtins/grade.h +++ b/src/builtins/grade.h @@ -26,7 +26,7 @@ // Non-Singeli, integers and characters: // 4-byte branchless binary search, 4-byte output // SHOULD support fast character searches -// SHOULD special-case boolean 𝕨 or 𝕩 +// Boolean 𝕨 or 𝕩: lookup table (single binary search on boolean 𝕨) // Different widths: widen narrower argument // SHOULD narrow wider-type 𝕩 if it isn't much shorter // SHOULD trim wider-type 𝕨 and possibly narrow @@ -378,7 +378,23 @@ bool CAT(isSorted,GRADE_UD(Up,Down))(B x) { #undef CMP } +// Location of first 1 (ascending) or 0 (descending), by binary search +static u64 CAT(bit_boundary,GRADE_UD(up,dn))(u64* x, u64 n) { + u64 c = GRADE_UD(,~)(u64)0; + u64 *s = x-1; + for (usz l = BIT_N(n)+1, h; (h=l/2)>0; l-=h) { + u64* m = s+h; if (!(c LT *m)) s = m; + } + ++s; // Word containing boundary + u64 b = 64*(s-x); + if (b >= n) return n; + u64 v = GRADE_UD(~,) *s; + if (b+63 >= n) v &= ~(u64)0 >> ((-n)%64); + return b + POPC(v); +} + extern B CAT(GRADE_UD(le,ge),c2)(B,B,B); +extern B select_c2(B t, B w, B x); B GRADE_CAT(c2)(B t, B w, B x) { if (isAtm(w) || RNK(w)==0) thrM(GRADE_CHR": 𝕨 must have rankβ‰₯1"); @@ -431,11 +447,32 @@ B GRADE_CAT(c2)(B t, B w, B x) { if (LIKELY(wexe? we : xe; - if (ze==el_bit) ze = el_i8; - if (ze > we) { switch (ze) { default:UD; case el_i8:w=toI8Any(w);break; case el_i16:w=toI16Any(w);break; case el_i32:w=toI32Any(w);break; case el_f64:w=toF64Any(w);break; } } - if (ze > xe) { switch (ze) { default:UD; case el_i8:x=toI8Any(x);break; case el_i16:x=toI16Any(x);break; case el_i32:x=toI32Any(x);break; case el_f64:x=toF64Any(x);break; } } + if (ze > we) { switch (ze) { default:UD; case el_i16:w=toI16Any(w);break; case el_i32:w=toI32Any(w);break; case el_f64:w=toF64Any(w);break; } } + if (ze > xe) { switch (ze) { default:UD; case el_i16:x=toI16Any(x);break; case el_i32:x=toI32Any(x);break; case el_f64:x=toF64Any(x);break; } } we = ze; #else if (!elInt(we) | !elInt(xe)) goto gen;