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 def h = k>>1 # Increase size from h to k
{x,z} := build{h} {x,z} := build{h}
def low = lowbits{k} # Low bit in each new group def low = lowbits{k} # Low bit in each new group
if (k <= 3) { if (k == 2) {
z0 := z & low z0 := z & low
zm := z>>1 & low zm := z>>1 & low
if (k == 2) tup{ tup{ x - (x>>1 & z0), zm + z0 }
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)
}
} else { } 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 # SWAR shifter: shift x by sh*o, in length-k groups
def shift{sh, o, x} = { def shift{sh, o, x} = {
l := o & low; m := l<<k - l l := o & low; m := l<<k - l
s := (x & m)>>sh | (x &~ m) 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{ tup{
(x&even) | shift{1, z, x&~even}, (x&~move) | shift{1, z1, x&move}>>1,
if (k>4) (z + z>>h)&even else ((z&~even)>>h) + (z&even) (z&odd)>>h + ze
} }
} }
} }
# Finally, compose groups with regular shifts # Finally, compose groups with regular shifts
def g = 8 # 12 performs about the same def g = 8
{b,z} := build{g} {b,z} := build{g}
o := z*lowbits{g} # Offsets by prefix sum o := z*lowbits{g} # Offsets by prefix sum
def s = 1<<g - 1 def s = 1<<g - 1