Simplify pairwise pext implementation; drop 12-bit as no longer competitive
This commit is contained in:
parent
7fe1ab930a
commit
e09d385df5
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user