| similar: you can do SIMD "within" a single integer type with some fun bit hacks. ex: for an integer (u32, u64, u128), you can test "all at once" whether any byte == 0, or any nibble == 0, etc... like: [0] fn u32_any_byte_eqz(x: u32) -> bool {
let t = x.wrapping_sub(0x0101_0101);
let u = !x & 0x8080_8080;
let v = t & u;
v != 0
}
which generates pretty compact assembly: example::u32_any_byte_eqz:
lea eax, [rdi - 16843009]
andn eax, edi, eax
test eax, -2139062144
setne al
ret
even more powerful, you can test whether any byte `b` is in the range `m < b < n` "all at once", where `0 <= m <= 127` and `0 <= n <= 128`. [1] fn u32_has_byte_between(x: u32, m: u32, n: u32) -> bool {
let mask = 0x0101_0101;
let s = mask * 127;
let y = mask * 128;
let w = mask * (127 + n);
let t = mask * (127 - m);
let u = x & s;
let z = (w - u) & (!x) & (u + t) & y;
z != 0
}
by changing the mask you can also select which bytes/nibbles you care about.i've used these to pretty great effect when writing a montecarlo tree search. you just need some care to tightly bit-pack the core structs, then you're golden. [0]: https://phlip9.com/notes/performance/bit%20hacks/#any-byte-0
[1]: https://phlip9.com/notes/performance/bit%20hacks/#any-byte-b... |