From 492e97e2ca6db129c7a75103a4bd7cbf5af83f5e Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sun, 9 Jul 2023 19:31:04 -0400 Subject: [PATCH] Right argument narrowing for numeric Bins --- src/builtins/grade.h | 47 ++++++++++++++++++++++++++++-------- src/singeli/src/bins.singeli | 23 ++++++++++++++++++ 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/src/builtins/grade.h b/src/builtins/grade.h index 35efb726..7891bc53 100644 --- a/src/builtins/grade.h +++ b/src/builtins/grade.h @@ -27,8 +27,8 @@ // 4-byte branchless binary search, 4-byte output // SHOULD support fast character searches // Boolean 𝕨 or 𝕩: lookup table (single binary search on boolean 𝕨) -// Different widths: widen narrower argument -// SHOULD narrow wider-type 𝕩 if it isn't much shorter +// Different widths: generally widen narrower argument +// Narrow wider-type 𝕩 instead if it isn't much shorter // SHOULD trim wider-type 𝕨 and possibly narrow // Same-width numbers: // Output type based on ≠𝕨 @@ -393,8 +393,10 @@ static u64 CAT(bit_boundary,GRADE_UD(up,dn))(u64* x, u64 n) { return b + POPC(v); } -extern B CAT(GRADE_UD(le,ge),c2)(B,B,B); +#define LE_C2 CAT(GRADE_UD(le,ge),c2) +extern B LE_C2(B,B,B); extern B select_c2(B t, B w, B x); +extern B mul_c2(B, B, B); B GRADE_CAT(c2)(B t, B w, B x) { if (isAtm(w) || RNK(w)==0) thrM(GRADE_CHR": 𝕨 must have rankβ‰₯1"); @@ -421,7 +423,7 @@ B GRADE_CAT(c2)(B t, B w, B x) { B c = IGet(w, 0); if (LIKELY(wexe? we : xe; - 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; + #define WIDEN(E, X) switch (E) { default:UD; case el_i16:X=toI16Any(X);break; case el_i32:X=toI32Any(X);break; case el_f64:X=toF64Any(X);break; } + if (xe > we) { + if (xia/4 < wia) { // Narrow x + assert(el_i8 <=we && we<=el_i32); + assert(el_i16<=xe && xe<=el_f64); + i32 pre = -1; pre<<=(8<<(we-el_i8))-1; + pre = GRADE_UD(pre,-1-pre); // Smallest value of w's type + i32 w0 = o2iG(IGetU(w,0)); + // Saturation is correct except it can move low values past + // pre. Post-adjust with multΓ—r + if (w0 == pre) mult = LE_C2(m_f64(0), m_i32(pre), incG(x)); + // Narrow x with saturating conversion + B xn; void *xp = m_tyarrc(&xn, elWidth(we), x, el2t(we)); + u8 ind = xe xe) WIDEN(we, x) + #undef WIDEN #else if (!elInt(we) | !elInt(xe)) goto gen; w=toI32Any(w); x=toI32Any(x); @@ -484,7 +509,7 @@ B GRADE_CAT(c2)(B t, B w, B x) { for (u64 i=0; ibf) d = b + } +} + +exportT{ + 'si_saturate', + each{{a}=>saturate{...a}, merge{ + tup{tup{i16,i8}, tup{i32,i8}, tup{i32,i16}}, + join{table{bind{tup,f64}, tup{i8,i16,i32}, tup{1,0}}} + }} +}