Hacker News new | ask | show | jobs
by phlip9 1340 days ago
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...