Friday, September 21, 2007

Clamping integers to bytes

This is yet another bit hack to avoid branching.

If you want to clamp an n-bit signed integer such that negative values become zero, you can do it with a bitwise AND of the integer and the bitwise NOT of the integer shifted right by n-1 bits. E.g., in the case of 32-bit integers, the following:

int clamp_lower_to_zero(int i)
return (i & ~(i>>31));

This works because in the case of negative numbers, the result of the shift is all 32 bits set to one. In the case of non-negative numbers the result is all 32 bits set to zero. Applying the NOT reverses the situation, so the negative case results in zeroes and the positive case results in ones. Once this is AND-ed with the original value, all negative cases result in zero.

You can use a similar trick to clamp the upper bound of a signed int to 255 (or some other case of 2n-1).

unsigned char clamp_upper_to_255(int i)
return (unsigned char) (((255-i) >> 31) OR i);

When i <= 255, the result of the shift is 0. When i > 255, the result of the shift is 0xffffffff, which is cast to 255 (0xff).

You can combine the two to clamp a signed integer to a byte:

unsigned char clamp_int_to_byte(int i)
return (unsigned char) (((255-i)>>31) OR (i & ~(i>>31)));

Note: I had to use "OR" rather than a vertical bar. Blogger can't seem to handle the bar.

This isn't groundbreaking stuff by any means, but I haven't seen this technique posted anywhere--and people* patent the stupidest things--so, if this hasn't been patented yet, it's documented as prior art here.

*Restraint is exerised in the word choice.


Post a Comment

Subscribe to Post Comments [Atom]

<< Home