Use Singeli code for ⍋bool and ⍒bool with 1- and 2-byte result
This commit is contained in:
parent
6bea10de21
commit
1647e98fd2
@ -202,16 +202,17 @@ B SORT_C1(B t, B x) {
|
||||
#endif
|
||||
|
||||
|
||||
#define GRADE_CHR GRADE_UD("⍋","⍒")
|
||||
extern Arr* bitUD[3]; // from fns.c
|
||||
extern B bit2x[2];
|
||||
extern B grade_bool(B x, usz ia, bool up); // slash.c
|
||||
|
||||
#define GRADE_CHR GRADE_UD("⍋","⍒")
|
||||
B GRADE_CAT(c1)(B t, B x) {
|
||||
if (isAtm(x) || RNK(x)==0) thrM(GRADE_CHR": Argument cannot be a unit");
|
||||
if (RNK(x)>1) x = toCells(x);
|
||||
usz ia = IA(x);
|
||||
if (ia>I32_MAX) thrM(GRADE_CHR": Argument too large");
|
||||
B r;
|
||||
if (ia<=2) {
|
||||
B r;
|
||||
if (ia==2) { SGetU(x); r = incG(bit2x[!(compare(GetU(x,0), GetU(x,1)) GRADE_UD(<=,>=) 0)]); }
|
||||
else if (ia==1) r = taga(ptr_inc(bitUD[1]));
|
||||
else r = emptyIVec();
|
||||
@ -220,18 +221,10 @@ B GRADE_CAT(c1)(B t, B x) {
|
||||
}
|
||||
|
||||
u8 xe = TI(x,elType);
|
||||
i32* rp; B r = m_i32arrv(&rp, ia);
|
||||
if (xe==el_bit) {
|
||||
u64* xp = bitarr_ptr(x);
|
||||
u64 sum = bit_sum(xp, ia);
|
||||
u64 r0 = 0;
|
||||
u64 r1 = GRADE_UD(ia-sum, sum);
|
||||
for (usz i = 0; i < ia; i++) {
|
||||
if (bitp_get(xp,i)^GRADE_UD(0,1)) rp[r1++] = i;
|
||||
else rp[r0++] = i;
|
||||
}
|
||||
goto decG_sq;
|
||||
} else if (xe==el_i8 && ia>8) {
|
||||
if (xe==el_bit) return grade_bool(x, ia, GRADE_UD(1,0));
|
||||
if (ia>I32_MAX) thrM(GRADE_CHR": Argument too large");
|
||||
i32* rp; r = m_i32arrv(&rp, ia);
|
||||
if (xe==el_i8 && ia>8) {
|
||||
i8* xp = i8any_ptr(x); usz n=ia;
|
||||
RADIX_SORT_i8(usz, GRADE);
|
||||
goto decG_sq;
|
||||
|
||||
@ -413,6 +413,49 @@ static NOINLINE B zeroCells(B x) { // doesn't consume
|
||||
return r;
|
||||
}
|
||||
|
||||
B not_c1(B t, B x);
|
||||
B grade_bool(B x, usz xia, bool up) {
|
||||
#define BRANCHLESS_GRADE(T) \
|
||||
T* rp; r = m_##T##arrv(&rp, xia); \
|
||||
u64 r0 = 0; \
|
||||
u64 r1 = l0; \
|
||||
if (up) BG_LOOP(!) else BG_LOOP()
|
||||
#define BG_LOOP(OP) \
|
||||
for (usz i = 0; i < xia; i++) { \
|
||||
bool b = OP bitp_get(xp,i); \
|
||||
rp[b?r0:r1-r0] = i; \
|
||||
r0+=b; r1++; \
|
||||
}
|
||||
B r;
|
||||
u64* xp = bitarr_ptr(x);
|
||||
u64 sum = bit_sum(xp, xia);
|
||||
u64 l0 = up? xia-sum : sum; // Length of first set of indices
|
||||
#if SINGELI && defined(__BMI2__)
|
||||
if (xia < 16) { BRANCHLESS_GRADE(i8) }
|
||||
else if (xia <= 1<<15) {
|
||||
B notx = not_c1(m_f64(0), inc(x));
|
||||
u64* xp0 = bitarr_ptr(notx);
|
||||
u64* xp1 = xp;
|
||||
if (!up) { u64* t=xp1; xp1=xp0; xp0=t; }
|
||||
#define BMI_GRADE(W) \
|
||||
i##W* rp = m_tyarrvO(&r, W/8, xia, t_i##W##arr, W); \
|
||||
bmipopc_1slash##W(xp0, rp , xia); \
|
||||
bmipopc_1slash##W(xp1, rp+l0, xia);
|
||||
if (xia <= 128) { BMI_GRADE(8) } else { BMI_GRADE(16) }
|
||||
#undef BMI_GRADE
|
||||
decG(notx);
|
||||
}
|
||||
#else
|
||||
if (xia <= 128) { BRANCHLESS_GRADE(i8) }
|
||||
else if (xia <= 1<<15) { BRANCHLESS_GRADE(i16) }
|
||||
#endif
|
||||
else if (xia <= 1ull<<31) { BRANCHLESS_GRADE(i32) }
|
||||
else { BRANCHLESS_GRADE(f64) }
|
||||
#undef BRANCHLESS_GRADE
|
||||
#undef BG_LOOP
|
||||
decG(x); return r;
|
||||
}
|
||||
|
||||
void filter_ne_i32(i32* rp, i32* xp, usz len, usz sum, i32 val) {
|
||||
usz b = bsp_max; TALLOC(i16, buf, b + b/16);
|
||||
u64* wp = (u64*)(buf + b);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user