Simplify pairwise pext implementation; drop 12-bit as no longer competitive

This commit is contained in:
Marshall Lochbaum 2023-08-01 21:31:20 -04:00
parent 7fe1ab930a
commit e09d385df5

View File

@ -299,33 +299,30 @@ fn pext{T}(x:T, m:T) {
def h = k>>1 # Increase size from h to k
{x,z} := build{h}
def low = lowbits{k} # Low bit in each new group
if (k <= 3) {
if (k == 2) {
z0 := z & low
zm := z>>1 & low
if (k == 2) tup{
x - (x>>1 & z0),
z0 + zm
} else tup{ # Faster 1->3 jump, currently unused
x - ((x>>1&mod{low*3}) & (z|z0<<1)) - (x>>2 & (z & zm)),
(z0 + zm) + (z>>2 & low)
}
tup{ x - (x>>1 & z0), zm + z0 }
} else {
# Shift high x group down by low z, then add halves of z
even:T = mod{low*(1<<h - 1)}
# SWAR shifter: shift x by sh*o, in length-k groups
def shift{sh, o, x} = {
l := o & low; m := l<<k - l
s := (x & m)>>sh | (x &~ m)
if (2*sh<=k/2) shift{2*sh, o>>1, s} else s
if (2*sh<k/2) shift{2*sh, o>>1, s} else s
}
# Shift high x group down by low z, then add halves of z
odd:T = mod{low*(1<<k - 1<<h)} # Top half
ze := z&~odd
z1 := ze + low*(1<<(k-1) - 1) # z-1, as signed k-bit
move := odd &~ (z1<<1) # Only groups where z>0 move
tup{
(x&even) | shift{1, z, x&~even},
if (k>4) (z + z>>h)&even else ((z&~even)>>h) + (z&even)
(x&~move) | shift{1, z1, x&move}>>1,
(z&odd)>>h + ze
}
}
}
# Finally, compose groups with regular shifts
def g = 8 # 12 performs about the same
def g = 8
{b,z} := build{g}
o := z*lowbits{g} # Offsets by prefix sum
def s = 1<<g - 1