If a
or b
is a constant (or loop-constant), you can precompute all rotations and sort them, and then do a binary search with the one that isn't a constant as key. That's fewer steps, but the steps are slower in practice (binary search is commonly implemented with a badly-predicted branch), so it might not be better.
In the case that it's really a constant, not a loop-constant, there are some more tricks:
- if
a
is 0 or -1, it's trivial
- if
a
has only 1 bit set, you can do the test like b != 0 && (b & (b - 1)) == 0
- if
a
has 2 bits set, you can do the test like ror(b, tzcnt(b)) == ror(a, tzcnt(a))
if a
has only one contiguous group of set bits, you can use
int x = ror(b, tzcnt(b));
int y = ror(x, tzcnt(~x));
const int a1 = ror(a, tzcnt(a)); // probably won't compile
const int a2 = ror(a1, tzcnt(~a1)); // but you get the idea
return y == a2;
- if many rotations of
a
are the same, you may be able to use that to skip certain rotations instead of testing them all, for example if a == 0xAAAAAAAA
, the test can be b == a || (b << 1) == a
- you can compare to the smallest and biggest rotations of the constant for a quick pre-test, in addition to the
popcnt
test.
Of course, as I said in the beginning, none of this applies when a
and b
are both variables.