chore: make sw pext generic over T

This commit is contained in:
Rekai Nyangadzayi Musuka 2023-12-02 16:44:29 -06:00
parent 611549c8e9
commit 4a353f5081
1 changed files with 21 additions and 46 deletions

View File

@ -326,62 +326,37 @@ const pext = struct {
}; };
} }
fn sw(comptime T: type, value: T, mask: T) T { inline fn sw(comptime T: type, value: T, mask: T) T {
// TODO: rewrite in idiomatic zig / understand the algorithm and write an original implementation // FIXME: will be replaced in the future by https://github.com/ziglang/zig/issues/14995 (hopefully?)
// code source: https://stackoverflow.com/questions/41720249/detecting-matching-bits-in-c
// note: will be replaced in the future by https://github.com/ziglang/zig/issues/14995 (hopefully?)
return switch (T) { return switch (T) {
u32 => { u32, u64 => {
var _value: T = value; // code source: https://stackoverflow.com/questions/41720249/detecting-matching-bits-in-c
var _mask: T = mask; // TODO: rewrite more in generic/idiomatic zig
const log2_bits = @typeInfo(Log2Int(T)).Int.bits;
_value &= _mask; var val: T = value & mask;
var mk: T = ~_mask << 1; var msk: T = mask;
var mk: T = ~msk << 1;
var mp: T = undefined; var mp: T = undefined;
var mv: T = undefined; var mv: T = undefined;
var t: T = undefined; var t: T = undefined;
inline for (0..@typeInfo(Log2Int(T)).Int.bits) |i| { inline for (0..log2_bits) |i| {
mp = mk ^ (mk << 1); // parallel suffix inline for (0..log2_bits) |j| {
mp = mp ^ (mp << 2); const m = if (j == 0) mk else mp;
mp = mp ^ (mp << 4); mp = m ^ (m << (1 << j)); // parallel suffix
mp = mp ^ (mp << 8); }
mp = mp ^ (mp << 16);
mv = (mp & _mask); // bits to move mv = (mp & msk); // bits to move
_mask = ((_mask ^ mv) | (mv >> (1 << i))); // compress _mask msk = ((msk ^ mv) | (mv >> (1 << i))); // compress mask
t = (_value & mv); t = (val & mv);
_value = ((_value ^ t) | (t >> (1 << i))); // compress _value val = ((val ^ t) | (t >> (1 << i))); // compress val
mk &= ~mp; mk &= ~mp;
} }
return _value; return val;
},
u64 => {
var _value: T = value;
var _mask: T = mask;
_value &= _mask;
var mk: T = ~_mask << 1;
var mp: T = undefined;
var mv: T = undefined;
var t: T = undefined;
inline for (0..@typeInfo(Log2Int(T)).Int.bits) |i| {
mp = mk ^ (mk << 1); // parallel suffix
mp = mp ^ (mp << 2);
mp = mp ^ (mp << 4);
mp = mp ^ (mp << 8);
mp = mp ^ (mp << 16);
mp = mp ^ (mp << 32);
mv = (mp & _mask); // bits to move
_mask = ((_mask ^ mv) | (mv >> (1 << i))); // compress _mask
t = (_value & mv);
_value = ((_value ^ t) | (t >> (1 << i))); // compress _value
mk &= ~mp;
}
return _value;
}, },
else => @compileError("pext is sunsupported for " ++ @typeName(T) ++ "."), else => @compileError("pext is sunsupported for " ++ @typeName(T) ++ "."),
}; };