fix a⊒b on mixed-width characters

This commit is contained in:
dzaima 2023-12-15 20:00:44 +02:00
parent 840c40748f
commit 66b5c1fc0a

View File

@ -9,9 +9,9 @@
// SHOULD have fast path when cell sizes don't match // SHOULD have fast path when cell sizes don't match
// One input empty: fast not-found // One input empty: fast not-found
// Character elements: // Character elements:
// Character versus number array is fast not-found for ∊ and ⊐ // Character versus number array is fast not-found
// SHOULD have fast character-number path for ⊒
// Reinterpret as integer elements // Reinterpret as integer elements
// Mixed c8 & c16 get widened to c16 to use in signed 16-bit tables
// COULD try p=⌜n when all arguments are short (may not be faster?) // COULD try p=⌜n when all arguments are short (may not be faster?)
// p⊐n & n∊p with short n: p⊸⊐¨n // p⊐n & n∊p with short n: p⊸⊐¨n
// p⊐n & n∊p with boolean p: based on ⊑p and p⊐¬⊑p // p⊐n & n∊p with boolean p: based on ⊑p and p⊐¬⊑p
@ -227,7 +227,7 @@ static NOINLINE usz indexOfOne(B l, B e) {
#endif #endif
} }
#define CHECK_CHRS_ELSE \ #define CHECK_CHRS_ELSE /* runs block if arguments are numerical; goes to chrEls if arguments are char arrs, updating we/xe to integers; widens mixed c8,c16 to c16,c16 */ \
if (!elNum(we)) { \ if (!elNum(we)) { \
if (elChr(we)) { \ if (elChr(we)) { \
if (elNum(xe)) goto none_found; \ if (elNum(xe)) goto none_found; \
@ -235,9 +235,10 @@ static NOINLINE usz indexOfOne(B l, B e) {
if (we>xe) x=taga(cpyC16Arr(x)); \ if (we>xe) x=taga(cpyC16Arr(x)); \
else w=taga(cpyC16Arr(w)); \ else w=taga(cpyC16Arr(w)); \
we = xe = el_i16; \ we = xe = el_i16; \
goto tyEls; \ goto chrEls; \
} \ } \
we-=el_c8-el_i8; xe-=el_c8-el_i8; goto tyEls; \ we-= el_c8-el_i8; \
xe-= el_c8-el_i8; goto chrEls; \
} \ } \
} else if (!elNum(xe)) { \ } else if (!elNum(xe)) { \
if (elChr(xe)) goto none_found; \ if (elChr(xe)) goto none_found; \
@ -266,7 +267,7 @@ B indexOf_c2(B t, B w, B x) {
decG(w); return i64EachDec(wia, x); decG(w); return i64EachDec(wia, x);
} }
CHECK_CHRS_ELSE { tyEls: // Both numbers CHECK_CHRS_ELSE { chrEls:
if (wia>32 && xia<=(we<=el_i8?1:3)) { if (wia>32 && xia<=(we<=el_i8?1:3)) {
SGetU(x); SGetU(x);
B r; B r;
@ -390,7 +391,7 @@ B memberOf_c2(B t, B w, B x) {
decG(x); return i64EachDec(0, w); decG(x); return i64EachDec(0, w);
} }
CHECK_CHRS_ELSE { tyEls: // Both numbers CHECK_CHRS_ELSE { chrEls:
if (xia>32 && wia<=(xe<=el_i8?1:xe==el_i32?4:6)) { if (xia>32 && wia<=(xe<=el_i8?1:xe==el_i32?4:6)) {
SGetU(w); SGetU(w);
i8* rp; r = m_i8arrc(&rp, w); i8* rp; r = m_i8arrc(&rp, w);
@ -462,7 +463,6 @@ B memberOf_c2(B t, B w, B x) {
decG(x); decG(x);
return r; return r;
} }
#undef CHECK_CHRS_ELSE
B count_c2(B t, B w, B x) { B count_c2(B t, B w, B x) {
bool split = 0; (void) split; bool split = 0; (void) split;
@ -479,10 +479,15 @@ B count_c2(B t, B w, B x) {
i32* rp; B r = m_i32arrc(&rp, x); i32* rp; B r = m_i32arrc(&rp, x);
TALLOC(usz, wnext, wia+1); TALLOC(usz, wnext, wia+1);
wnext[wia] = wia; wnext[wia] = wia;
if (wia==0 || xia==0) {
none_found:
TFREE(wnext); decG(r);
decG(w); return i64EachDec(wia, x);
}
CHECK_CHRS_ELSE { chrEls:
if (we<=el_i16 && xe<=el_i16) { if (we<=el_i16 && xe<=el_i16) {
if (we==el_bit) { w = toI8Any(w); we = TI(w,elType); } if (we==el_bit) { w = toI8Any(w); we = el_i8; }
if (xe==el_bit) { x = toI8Any(x); xe = TI(x,elType); } if (xe==el_bit) { x = toI8Any(x); xe = el_i8; }
el8or16:;
usz it = elRange(we); // Range of writes usz it = elRange(we); // Range of writes
usz ft = elRange(xe); // Range of lookups usz ft = elRange(xe); // Range of lookups
usz t = it>ft? it : ft; // Table allocation width usz t = it>ft? it : ft; // Table allocation width
@ -503,16 +508,16 @@ B count_c2(B t, B w, B x) {
if (xe==el_i8) { GET(i8) } else { GET(i16) } if (xe==el_i8) { GET(i8) } else { GET(i16) }
#undef GET #undef GET
TFREE(tab0); TFREE(tab0);
} else if (we>=el_c8 && we<=el_c16 && xe>=el_c8 && xe<=el_c16) { goto dec_nwx;
we-= el_c8-el_i8; xe-= el_c8-el_i8; }
goto el8or16;
} else {
#if SINGELI #if SINGELI
if (we==xe && wia<=INT32_MAX && (we==el_i32 || (we==el_f64 && (split || canCompare64_norm2(&w,wia,&x,xia)))) && else if (we==xe && wia<=INT32_MAX && (we==el_i32 || (we==el_f64 && (split || canCompare64_norm2(&w,wia,&x,xia)))) &&
si_count_c2_hash[we-el_i32](rp, tyany_ptr(w), wia, tyany_ptr(x), xia, (u32*)wnext)) { si_count_c2_hash[we-el_i32](rp, tyany_ptr(w), wia, tyany_ptr(x), xia, (u32*)wnext)) {
goto dec_nwx; goto dec_nwx;
} }
#endif #endif
}
H_b2i* map = m_b2i(64); H_b2i* map = m_b2i(64);
SGetU(x) SGetU(x)
SGetU(w) SGetU(w)
@ -528,13 +533,12 @@ B count_c2(B t, B w, B x) {
rp[i] = j; rp[i] = j;
} }
free_b2i(map); free_b2i(map);
}
#if SINGELI
dec_nwx:; dec_nwx:;
#endif
TFREE(wnext); decG(w); decG(x); TFREE(wnext); decG(w); decG(x);
return reduceI32Width(r, wia); return reduceI32Width(r, wia);
} }
#undef CHECK_CHRS_ELSE
// if nanBad and input contains a NaN, doesn't consume and returns m_f64(0) // if nanBad and input contains a NaN, doesn't consume and returns m_f64(0)
// otherwise, consumes and returns an array with -0 (and NaNs if !nanBad) normalized // otherwise, consumes and returns an array with -0 (and NaNs if !nanBad) normalized