t = 0x2020c6 >> x
return (t << (t & 31)) >> 2785 karma · joined March 29, 2017
t = 0x2020c6 >> x
return (t << (t & 31)) >> 27 ((year * 1073750999) & 3221352463) <= 126976
How this works is surprisingly complex, I am thinking of writing a whole blog post about it... (((x + 393206) & (x + 524188)) ^ ((x + 916504) & (x + 514288))) >> 17
This is for integer log 10, but could be adapted for number of digits. It needs a wrapper for 64 bit to invoke it multiple times, but most numbers in a JSON are small, so it might even be competitive; it needs only 4 cycles with enough instruction level parallelism.I gathered this idea from the output of a superoptimizer, it was fun to figure out how it works. For spoilers, see [1].
[1] https://github.com/rust-lang/rust/blob/master/library/core/s...
> In theory at least, the compiler can see that rule only has 256 values and create a reduced version of ca1d_rule_apply for each value. Whether it actually does is not of much practical concern when the rendering code is the bottle neck. However it’s interesting to see if the compiler can deduce the best solution or whether anything trips it up.
The compiler is unlikely to get the optimal result here. The core of this is finding the best instruction sequence for a ternary boolean operation encoded in 8 bits; it's the same job needed for emulating the AVX512F "vpternlog" instruction. This can always be done in at most 5 instructions (or 4 if you have andnot/ornot/xornot), but it's not straightforward to do this. Here is some code that calculates optimal instruction sequences (by letting z3 do the heavy lifting): https://github.com/falk-hueffner/ternary-logic-optimization
mask = -1 << i;
return (x & ~mask) | ((x >> 1) & mask);
but with xor we can do it in one less instruction: mask = -1 << i;
return ((x ^ (x >> 1)) & mask) ^ x;The use case is a bit different (the task includes finding ingredients mentioned in a longer text, and it'll rather not parse something rather than parsing it wrong), but it works fairly OK and can even parse things like "3/4 cup plus 2 tablespoons packed light-brown sugar".
[1] http://hueffner.de/falk/hueffner-studienarbeit-atomix.pdf Section 5.5
c = x ^ y;
return popcount(((c >> 1) | 0x8080808080808080) - c) & 0x8080808080808080);Indeed, even 8-bit fields can be added in parallel, using the fact that ^ is like a + that does not produce a carry:
uint64_t signmask = 0x8080808080808080;
uint64_t sum_without_sign_bits = ((x & ~signmask) + (y & ~signmask));
uint64_t sum_of_sign_bits = (x ^ y) & signmask;
return sum_without_sign_bits ^ sum_of_sign_bits; bool isvowel(char c) {
return (1u << (c&31)) & 0x208222;
} bool isPerfect(uint64_t x) {
int ctz = __builtin_ctzll(x);
return ((0x40051056 >> ctz) & 1) && ((x >> ctz) + 1) == (uint64_t(1) << (ctz + 1));
}I haven't checked how this relates to the code in this library.