singeli chr_squeeze

This commit is contained in:
dzaima 2022-06-30 01:47:57 +03:00
parent 75bfa5d905
commit 859be5efb2
4 changed files with 140 additions and 81 deletions

View File

@ -73,7 +73,7 @@ B num_squeeze(B x) {
if (xp==NULL) return num_squeezeF(x, ia); if (xp==NULL) return num_squeezeF(x, ia);
#if SINGELI #if SINGELI
or = avx2_squeeze_B((u8*)xp, ia); or = avx2_squeeze_numB((u8*)xp, ia);
if (or==0xfffffffe) goto r_f64; if (or==0xfffffffe) goto r_f64;
goto r_orF64; goto r_orF64;
r_orF64: if (or==0xffffffff) goto r_x; else goto r_or; r_orF64: if (or==0xffffffff) goto r_x; else goto r_or;
@ -98,31 +98,48 @@ B num_squeeze(B x) {
B chr_squeeze(B x) { B chr_squeeze(B x) {
usz ia = a(x)->ia; usz ia = a(x)->ia;
u8 xe = TI(x,elType); u8 xe = TI(x,elType);
if (xe==el_c8) goto r_x;
usz i = 0; usz i = 0;
i32 or = 0; i32 or = 0;
if (xe==el_c16) { switch(xe) { default: UD;
case el_c8: goto r_x;
#if SINGELI
case el_c16: { u32 t = avx2_squeeze_c16((u8*)c16any_ptr(x), ia); if (t==0) goto r_c8; else goto r_x; }
case el_c32: { u32 t = avx2_squeeze_c32((u8*)c32any_ptr(x), ia); if (t==0) goto r_c8; else if (t==1) goto r_c16; else if (t==2) goto r_x; else UD; }
#else
case el_c16: {
u16* xp = c16any_ptr(x); u16* xp = c16any_ptr(x);
for (; i < ia; i++) if (xp[i] != (u8)xp[i]) goto r_x; for (; i < ia; i++) if (xp[i] != (u8)xp[i]) goto r_x;
goto r_c8; goto r_c8;
} }
if (xe==el_c32) { case el_c32: {
u32* xp = c32any_ptr(x); u32* xp = c32any_ptr(x);
bool c8 = true; bool c8 = true;
for (; i < ia; i++) { for (; i < ia; i++) {
if (xp[i] != (u16)xp[i]) goto r_c32; if (xp[i] != (u16)xp[i]) goto r_x;
if (xp[i] != (u8 )xp[i]) c8 = false; if (xp[i] != (u8 )xp[i]) c8 = false;
} }
if (c8) goto r_c8; if (c8) goto r_c8;
else goto r_c16; else goto r_c16;
} }
#endif
case el_bit: case el_i8: case el_i16: case el_i32: case el_f64: case el_B:; /*fallthrough*/
}
B* xp = arr_bptr(x); B* xp = arr_bptr(x);
if (xp!=NULL) { if (xp!=NULL) {
#if SINGELI
u32 t = avx2_squeeze_chrB((u8*)xp, ia);
if (t==0) goto r_c8;
else if (t==1) goto r_c16;
else if (t==2) goto r_c32;
else if (t==3) goto r_x;
else UD;
#else
for (; i < ia; i++) { for (; i < ia; i++) {
if (!isC32(xp[i])) goto r_x; if (!isC32(xp[i])) goto r_x;
or|= o2cu(xp[i]); or|= o2cu(xp[i]);
} }
#endif
} else { } else {
SGetU(x) SGetU(x)
for (; i < ia; i++) { for (; i < ia; i++) {
@ -133,8 +150,8 @@ B chr_squeeze(B x) {
} }
if (or<=U8_MAX ) r_c8: return FL_SET(toC8Any(x), fl_squoze); if (or<=U8_MAX ) r_c8: return FL_SET(toC8Any(x), fl_squoze);
else if (or<=U16_MAX) r_c16: return FL_SET(toC16Any(x), fl_squoze); else if (or<=U16_MAX) r_c16: return FL_SET(toC16Any(x), fl_squoze);
else r_c32: return FL_SET(toC32Any(x), fl_squoze); else goto r_c32; r_c32: return FL_SET(toC32Any(x), fl_squoze);
r_x: return FL_SET(x, fl_squoze); /*when known typed:*/ r_x: return FL_SET(x, fl_squoze);
} }
B any_squeeze(B x) { B any_squeeze(B x) {

View File

@ -20,6 +20,18 @@ def assert{x & x==0} = assert{'failed assertion'}
def assert{x & x==1} = 1 def assert{x & x==1} = 1
def assert{x:u1} = emit{void, 'si_assert', x} def assert{x:u1} = emit{void, 'si_assert', x}
def tern{c, T, F & anyInt{c}} = {
if(c) T
else F
}
def tern{c, t:T, f:T & anyInt{c}} = {
res:T = f
if (c) res = t
res
}
def min{a, b & knum{a} & knum{b}} = tern{a<b, a, b} def min{a, b & knum{a} & knum{b}} = tern{a<b, a, b}
def max{a, b & knum{a} & knum{b}} = tern{a>b, a, b} def max{a, b & knum{a} & knum{b}} = tern{a>b, a, b}
@ -48,12 +60,6 @@ def anyInt{x & isreg{x}|isconst{x}} = isint{x}
def trunc{T, x:U & isint{T} & isint{U} & T<=U} = emit{T, '', x} def trunc{T, x:U & isint{T} & isint{U} & T<=U} = emit{T, '', x}
def trunc{T, x & knum{x}} = cast{T, x} def trunc{T, x & knum{x}} = cast{T, x}
def tern{c, T, F & anyInt{c}} = {
if(c) T
else F
}
def ty_s{w== 8} = i8; def ty_u{w== 8} = u8 def ty_s{w== 8} = i8; def ty_u{w== 8} = u8
def ty_s{w==16} = i16; def ty_u{w==16} = u16 def ty_s{w==16} = i16; def ty_u{w==16} = u16
def ty_s{w==32} = i32; def ty_u{w==32} = u32 def ty_s{w==32} = i32; def ty_u{w==32} = u32

View File

@ -3,23 +3,25 @@ include './sse3'
include './avx' include './avx'
include './avx2' include './avx2'
include './mask' include './mask'
include './cbqnDefs'
include 'util/tup' include 'util/tup'
def preserve_negative_zero = 0 def preserve_negative_zero = 0
def inRangeLen{x:T, start, count & issigned{eltype{T}}} = { def inRangeLen{x:TS, start, count & issigned{eltype{TS}}} = {
def TU = ty_u{T} def TU = ty_u{TS}
(TU~~(x-broadcast{T,start})) < broadcast{TU,count} TU~~(x-broadcast{TS,start}) < broadcast{TU,count}
} }
def inRangeLen{x:T, start, count & isunsigned{eltype{T}}} = { def inRangeLen{x:TU, start, count & isunsigned{eltype{TU}}} = {
def TS = ty_s{T} def TS = ty_s{TU}
def h = 1 << (width{eltype{T}}-1) def h = 1 << (width{eltype{TU}}-1)
(TS~~x)-broadcast{TS,start-h} < broadcast{TS,count-h} TS~~(x-broadcast{TU,start-h}) < broadcast{TS,count-h}
} }
def inRangeIncl{x:T, start, end} = inRangeLen{x, start, end-start+1} def inRangeIncl{x:T, start, end} = inRangeLen{x, start, end-start+1}
def inRangeExcl{x:T, start, end} = inRangeLen{x, start, end-start} def inRangeExcl{x:T, start, end} = inRangeLen{x, start, end-start}
def isSNaN{x:T & isunsigned{eltype{T}}} = inRangeLen{x<<1, (0xFFE<<52)+2, (1<<52)-2} def isSNaN{x:T & isunsigned{eltype{T}}} = inRangeLen{x<<1, (0xFFE<<52)+2, (1<<52)-2}
def q_chr{x:T & isvec{T} & eltype{T}==u64} = inRangeLen{x, cbqn_c32Tag{}<<48, 1<<48}
def fold{F, x:T} = { def fold{F, x:T} = {
show{'WARNING: using fallback fold'} show{'WARNING: using fallback fold'}
@ -39,14 +41,30 @@ def fold{F, x:T & w128{T}} = {
} }
def fold{F, x:T & w256{T}} = fold{F, F{half{x, 0}, half{x, 1}}} def fold{F, x:T & w256{T}} = fold{F, F{half{x, 0}, half{x, 1}}}
squeeze{vw, X0}(x0:*u8, len:Size) : u32 = { squeeze{vw, X, CHR, B}(x0:*u8, len:Size) : u32 = {
def X = tern{X0==u64, f64, X0}
def bulk = vw / width{X} def bulk = vw / width{X}
def XV = [bulk]X def XV = [bulk]X
def E = tern{X==f64, u32, ty_u{X}} def E = tern{X==f64, u32, ty_u{X}}
def EV = [bulk]E def EV = [bulk]E
show{XV, EV, CHR, B}
xp:= *X~~x0 xp:= *X~~x0
r1:= broadcast{EV, 0} r1:= broadcast{EV, 0}
if (CHR) {
def hw = width{E}/2
maskedLoop{bulk, len, {i, M} => {
c:= EV~~loadBatch{xp, i, XV}
if (X!=u16) r1|= M{c} # for u64, just accept the garbage top 32 bits and deal with them at the end
if (B) {
if (any{M{~q_chr{c}}}) return{3}
} else {
if (anyne{broadcast{EV, (1<<hw-1)<<hw} & c, broadcast{EV,0}, M}) return{lb{hw}-2}
}
}}
r2:= cast_i{u32, fold{|, r1}}
if (X>u32 and r2>=65536) return{2}
if (X>u16 and r2>=256) return{1}
0
} else {
if (X==i8) { if (X==i8) {
maskedLoop{bulk, len, {i, M} => { maskedLoop{bulk, len, {i, M} => {
v0:= loadBatch{xp, i, XV} v0:= loadBatch{xp, i, XV}
@ -56,6 +74,9 @@ squeeze{vw, X0}(x0:*u8, len:Size) : u32 = {
} else { } else {
maskedLoop{bulk, len, {i, M} => { maskedLoop{bulk, len, {i, M} => {
v0:= loadBatch{xp, i, XV} v0:= loadBatch{xp, i, XV}
if (isunsigned{X}) {
r1|= EV~~v0
} else {
def toint{x:T & isint{eltype{T}}} = x def toint{x:T & isint{eltype{T}}} = x
def toint{flt:T & X==f64} = { def toint{flt:T & X==f64} = {
int:= cvt2{i32, flt} int:= cvt2{i32, flt}
@ -63,7 +84,7 @@ squeeze{vw, X0}(x0:*u8, len:Size) : u32 = {
def conv{x} = tern{preserve_negative_zero, ty_u{x}, x} def conv{x} = tern{preserve_negative_zero, ty_u{x}, x}
if (anyne{conv{flt}, conv{cvt2{f64, int}}, M}) { # is any not an integer if (anyne{conv{flt}, conv{cvt2{f64, int}}, M}) { # is any not an integer
if (X0==f64) return{0xffff_ffff} if (~B) return{0xffff_ffff} # f64arr→f64arr
maskedLoop{bulk, i, len, {i, M} => { maskedLoop{bulk, i, len, {i, M} => {
def XU = [bulk]u64 def XU = [bulk]u64
@ -76,15 +97,20 @@ squeeze{vw, X0}(x0:*u8, len:Size) : u32 = {
} }
v1:= toint{v0} v1:= toint{v0}
r1|= M{(broadcast{EV, ~E~~1} & EV~~v1) ^ EV~~(v1 >> (width{X}-1))} r1|= M{(broadcast{EV, ~E~~1} & EV~~v1) ^ EV~~(v1 >> (width{X}-1))}
}
}} }}
promote{u32, fold{|, r1}} promote{u32, fold{|, r1}}
} }
}
} }
'avx2_squeeze_i8' = squeeze{256, i8 } 'avx2_squeeze_i8' = squeeze{256, i8, 0, 0}
'avx2_squeeze_i16' = squeeze{256, i16} 'avx2_squeeze_i16' = squeeze{256, i16, 0, 0}
'avx2_squeeze_i32' = squeeze{256, i32} 'avx2_squeeze_i32' = squeeze{256, i32, 0, 0}
'avx2_squeeze_f64' = squeeze{256, f64} 'avx2_squeeze_f64' = squeeze{256, f64, 0, 0}
'avx2_squeeze_B' = squeeze{256, u64} 'avx2_squeeze_numB'= squeeze{256, f64, 0, 1}
#'avx2_squeeze_u16' = squeeze{256, u16}
#'avx2_squeeze_u32' = squeeze{256, u32} 'avx2_squeeze_c16' = squeeze{256, u16, 1, 0}
'avx2_squeeze_c32' = squeeze{256, u32, 1, 0}
'avx2_squeeze_chrB'= squeeze{256, u64, 1, 1}

View File

@ -14,28 +14,37 @@ ctv ← "Ac8"‿"Ac16"‿"Ac32"
cmax 111411228×23 cmax 111411228×23
specF64 r •Import "utils.bqn" specF64 r •Import "utils.bqn"
spec specF64{}"a⍉𝕨"<"foo" spec specF64{}"a⍉𝕨"(@+1114111-5)<"foo"
RandEl r.Range3
{𝕊: r.Range spec} # some special values
{𝕊: -(r.Range 2) × (¯5+r.Range 10) + 2r.Range 64} # random near-power-of-two number
{𝕊: @+01114111(¯5+r.Range 10) + 22+r.Range 20} # random near-power-of-two character
# currently tests an array of 0s, with only one outstanding element
Do { 𝕊: Do { 𝕊:
val {r.Range𝕩𝕩} val RandEl@
{𝕊: r.Range spec} base RandEl@
{𝕊: (¯5+r.Range 10) + 2r.Range 64}
base 0
len 1+r.Range 23+r.Range 7 len 1+r.Range 23+r.Range 7
pos r.Range len pos r.Range len
arr "Ah" Variation val(pos) len<base arr "Ah" Variation val(pos) len<base
vals base(len>1) val
expg (´=)3 {
1=𝕩? 1;
2=𝕩? 2;
3
}•type¨ vals
tOuttIn { tOuttIn {
1=•Type val? expg=1?
msk ((¬int) valval) 1˜ (nminnmax)val msk ´ {((¬int) 𝕩𝕩) 1˜ (nminnmax)𝕩}¨ vals
1msk/ntn "Ah""Af"msk/ntv; 1msk/ntn "Ah""Af"msk/ntv;
(2•Type val) 1len? expg=2?
msk {2•Type val? (1len) (val-@)<cmax; 0} msk ´ {cmax>𝕩-@}¨ vals
1msk/ctn "Ah""Af"msk/ctv; 1msk/ctn "Ah""Af"msk/ctv;
# else expg=3?
"h""fill" "Ah""Af" "h""fill" "Ah""Af"
} }
tIn {'S'1𝕩}¨ "Inc"¨ tIn tIn {'S'1𝕩}¨ "Inc"¨ tIn
@ -50,10 +59,11 @@ Do ← { 𝕊:
} }
¬ (arrv EEqual arr) (arrv EEqual sq) ((<sqt) tOut)? ¬ (arrv EEqual arr) (arrv EEqual sq) ((<sqt) tOut)?
•Out "Fail:" •Out "Fail:"
•Show arrv •Out "Array: "•Fmt arr
•Show sq •Out "Squeezed: "•Fmt sq
•Show Type sq •Out "Testing variation "•Fmt 𝕩
•Show tOut𝕩 •Out "Got: "•Fmt Type sq
•Out "Expected one of: "•Fmt tOut
•Exit 1 •Exit 1
;@ ;@
}¨ tIn }¨ tIn