c++ - Isolating a string of 1's in a character -
i need come function takes char , index of set bit in , isolates string of 1's containing bit.
i.e.
char isolate(unsigned char arg, int i);
for example:
isolate(221,2) return 28 (11011101 >>> 00011100)
isolate(221,6) return 192 (11011101 >>> 1100000)
a lookup table seems clumsy solution require ~256*8=2048 entries.
i thinking of examining each individual bit left , right of index:
char isolate(char arg, int i) { char result=0; char mask = 1<<i; for(char mask = 1<<i; arg & mask != 0; mask>>=1) result |= mask; for(char mask = 1<<i; arg & mask != 0; mask<<=1) result |= mask; return result; }
but seems bit ugly. how can better this?
warning: none of tested or relevant*, may interesting.
isolating rightmost run of 1s easy, this: x ^ (x & ((x|(x-1))+1))
(explanation below), let's work that.
first x|(x-1)
smears rightmost 1 right, adding 1 turns bits 0 including rightmost run of 1's, anding x
removes rightmost run of 1's, , finally, xoring x
leaves rightmost run of 1s.
then need make sure range we're looking rightmost one. that's less amenable simple bitmath, if there's count leading zeros (clz
), it's not hard:
int shift = 32 - clz(~x & ((1 << i) - 1)); //replace 32 word size x = (x >> shift) << shift;
((1 << i) - 1)
makes mask of part right-end of run we're looking in (it just miss end, that's ok), clz
looks first 0 right of i
in x
, shifts remove bits don't want at.
apply first formula, isolating rightmost run of 1s, result of run of ones i
in. i
had better in run, or things go sideways (more accurately, return first run of 1s starts @ index higher i
)
*: question, none of matters. 2kb table not clumsy solution unless have tiny amount of memory available, , if that's case, input short loops aren't bad.
Comments
Post a Comment