I have an array that represents an 8x8 "bit" block
unsigned char plane[8]
What I want to do is loop through this "bit" block horizontally
and count up the number of times a change occurs between
a 1 and 0.
When I extract a bit, it is getting stored in an
unsigned char, so basically I want to increase a count
when one char is nonzero and the other is zero.
What I have is the following:
int getComplexity(unsigned char *plane) {
int x, y, count = 0;
unsigned char bit;
for(x = 0; x < 8; x++) {
for(y = 0; y < 8; y++) {
if(y == 0) {
bit = plane[x] & 1 << y;
continue;
}
/*
MISSING CODE
*/
}
}
}
For the missing code, I could do:
if( (bit && !(plane[x] & 1 << y)) || (!bit && (plane[x] & 1 << y)) ) {
bit = plane[x] & 1 << y;
count++;
}
However, what I really want see is if there is some
clever bitwise operation to do this step instead
of having two separate tests.
This is really just a gcc solution because the popcnt intrinsic wont work on every other compiler.
unsigned char plane[8];
static const uint64_t tmask = 0x8080808080808080UL;
uint64_t uplane = *(uint64_t *)plane; // pull the whole array into a single uint
return __builtin_popcnt( ~tmask & (uplane ^ (uplane >> 1) ) );
For x86 the popcnt instruction wasnt actually implemented until sse4.2 was (so rather recently).
Also, although this looks like it relies on endianness, it doesn't because none of the individual bytes are allowed to interact thanks to the mask.
It is making some assumptions about the way memory works :\
As a side note doing this same thing in the "horizontal" direction is just as easy:
return __builtin_popcnt(0xFFFFFFFFFFFFFFUL & ( uplane ^ (uplane >> 8) ) );
Related
I am writing a program in C where I am comparing two bytes of data, and then seeing if the bytes are different, and if so, at which bits.
This is what I have so far:
int var1 = 81; //Binary: 0101 0001
int var2 = 193; //Binary: 1100 0001
int diff = var1 ^ var2; //diff = 1001 0000 / 144
Basically I know how to use the XOR bitwise operator to see which bits are different between the two variables, but from here I don't know how to use diff to figure out which bits are the differences. For example, in my above code I'd want to use diff to output "Bit 5 and Bit 8 are different".
You can use a for loop to get that idea and make bitwise AND with 1 properly left shifted to get the set bits positions
for(size_t i = 0; i < sizeof(int)*8; i++){
if( diff & (1U << i))
printf("%zu is different\n",i+1);
}
Far easier to start with unsigned types when doing bit manipulations.
As #coderredoc inquired about solutions across various platforms, even uncommon ones:
Using int:
When int diff is negative, conversion to an unsigned (via masking with an unsigned) may change its bit pattern.
An int may have more than 8 bits per "byte". Diminishes correctness of sizeof(int)*8.
Various integer types may have padding (rare). Diminishes correctness of sizeof(int)*CHAR_BIT.
// OP wants to report first bit index as 1. 0 is more common.
#define BIT_REPORT_OFFSET 0
int bit_position = 0;
int mask;
do {
mask = 1 << bit_position;
if (diff & mask) {
printf("Bit %d\n", bit_position + BIT_REPORT_OFFSET);
}
bit_position++;
} while (mask < INT_MAX/2);
if (diff < 0) {
printf("Bit %d\n", bit_position + BIT_REPORT_OFFSET);
}
For maximum portability, avoid changing types, changing the value of diff and use constants from <limits.h> rather than compute them.
use unsigned int instead of int; then you can use
for (unsigned int pos = 0; diff; ++pos) {
if (diff & 1)
printf("difference in pos %u\n", pos);
diff >>= 1;
}
or
while (diff) {
int pos = ffs(diff);
printf("difference in pos %d\n", pos);
diff &= ~(1u << pos);
}
To get the different bits position, lets say you have 4 byte integer
for(int bit_index = sizeof(diff) - 1; bit_index >= 0;bit_index-- ) {
if((diff >> bit_index & 1) == 1 ){ /* if particular bit is 1, that bit_index value you can use */
printf("[%d] bit is different or 1 \n",bit_index);
}
Let's say we have a variable x of 64 bits, we also know how many bits of such variable we actually use, say 1 <= nx <= 64 , so the last bit is in position nx - 1. What could be the fastest way to perform a padding of the last bit in the remaining 64 - nx?
I would try something like (pseudocode/C):
uint64_t padd_input(uint64_t x, int nx) {
assert(0 < nx && nx <= 64);
msb = (x & (1ULL<<(nx - 1))) != 0ULL; //or (x >> (nx - 1)) & 0x1ULL;
x |= ((msb<<(64 - nx)) - msb)<<nx;
return x;
}
Is all the shift/masking redundant? Or is there a smarter way to achieve the same thing?
I make an example of I want to achieve, assume the unused part is already set to 0.
Let's say i have 0x7, and nx = 4 in this case there's nothing to do. Assuming instead 0xF the padding has to provide 0xFFFFFFFFFFFFFFFF.
I would do:
uint64_t padd_input(uint64_t x, int nx)
{
uint64_t t = x & (1ULL << (nx-1));
t = t - 1;
x = x | ~t;
return x;
}
or perhaps
uint64_t padd_input(uint64_t x, int nx)
{
uint64_t t = x & (1ULL << (nx-1));
if (t)
{
t = t - 1;
x = x | ~t;
}
return x;
}
as it seems more clear to me.
Note: I have not compared performance of OPs code and my code.
I am trying to calculate the parity bit in a string using the following code. I first calculate a parityByte for the string and then calculate
a parityBit for that byte.
From what I have gathered, these functions should do the trick, but right now I'm not so sure. The program in which I use them fails, and I would like to know if it's because of these or if I should look some other place.
char calculateParity(char *payload, int size){
char r = 0;
int i;
for(i = 0; i < size; i++){
r ^= payload[i];
}
return calcParityBit(r);
}
char calcParityBit(char x){
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
return x & 1;
}
With help from Bit Twiddling Hacks
char calcParityBit (unsigned char v)
{
return (0x6996u >> ((v ^ (v >> 4)) & 0xf)) & 1;
}
This is 5 operations versus 7 (after taking #squeamish ossifrage's good advice).
You must remember:
1) 'x >> a' the same thing for(int i = 0; i < a; i++) x/=2;
because, if you use operator '>>' for SIGNED type, you duplicate first bit, whitch == 1 in signed types;
2) operators '>>' and '<<' returns unsigned int value;
(Error example: unsigned char y = (x << 2) >> 2; for reset (in 0) two first bits)
As r3mainer comments: use unsigned char for the calculation. As char may be signed, the right shifting may replicate the sign bit.
Further, code typically runs best with a return value of int versus char. I recommend using a return value of int or even simply bool.
// Find parity (of any width up to the width of an unsigned)
int calcEvenParityBit(unsigned par, unsigned width) {
while (width > 1) {
par ^= par >> (width/2);
width -= width/2;
}
// Only return Least Significant Bit
return par % 2;
}
int calculateEvenParity(char *payload, int size) {
unsigned char r = 0;
int i;
for(i = 0; i < size; i++) {
r ^= payload[i];
}
return calcEvenParityBit(r, CHAR_BIT);
}
Invert the result for odd parity.
Your function:
char calcParityBit(char x){
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
return x & 1;
}
calculates parity for only three bits of your byte. To calculate parity of the entire 8 bits number, you can do something like this:
char calcParityBit(char x){
return ( (x>>7) ^
(x>>6) ^
(x>>5) ^
(x>>4) ^
(x>>3) ^
(x>>2) ^
(x>>1) ^
(x) ) & 1;
}
As you stick with the least significant bit, the fact that your argument is signed and the shift right operation may fill the shifted bits with '1' if the most significat bit was '1', is irrelevant for this solution (which is derived from yours)
Although it's good practice not to use number with sign if the sign is not of any actual use, and you treat the number as an unsigned one.
To be on the same page, let's assume sizeof(int)=4 and sizeof(long)=8.
Given an array of integers, what would be an efficient method to logically bitshift the array to either the left or right?
I am contemplating an auxiliary variable such as a long, that will compute the bitshift for the first pair of elements (index 0 and 1) and set the first element (0). Continuing in this fashion the bitshift for elements (index 1 and 2) will be computer, and then index 1 will be set.
I think this is actually a fairly efficient method, but there are drawbacks. I cannot bitshift greater than 32 bits. I think using multiple auxiliary variables would work, but I'm envisioning recursion somewhere along the line.
There's no need to use a long as an intermediary. If you're shifting left, start with the highest order int, shifting right start at the lowest. Add in the carry from the adjacent element before you modify it.
void ShiftLeftByOne(int * arr, int len)
{
int i;
for (i = 0; i < len - 1; ++i)
{
arr[i] = (arr[i] << 1) | ((arr[i+1] >> 31) & 1);
}
arr[len-1] = arr[len-1] << 1;
}
This technique can be extended to do a shift of more than 1 bit. If you're doing more than 32 bits, you take the bit count mod 32 and shift by that, while moving the result further along in the array. For example, to shift left by 33 bits, the code will look nearly the same:
void ShiftLeftBy33(int * arr, int len)
{
int i;
for (i = 0; i < len - 2; ++i)
{
arr[i] = (arr[i+1] << 1) | ((arr[i+2] >> 31) & 1);
}
arr[len-2] = arr[len-1] << 1;
arr[len-1] = 0;
}
For anyone else, this is a more generic version of Mark Ransom's answer above for any number of bits and any type of array:
/* This function shifts an array of byte of size len by shft number of
bits to the left. Assumes array is big endian. */
#define ARR_TYPE uint8_t
void ShiftLeft(ARR_TYPE * arr_out, ARR_TYPE * arr_in, int arr_len, int shft)
{
const int int_n_bits = sizeof(ARR_TYPE) * 8;
int msb_shifts = shft % int_n_bits;
int lsb_shifts = int_n_bits - msb_shifts;
int byte_shft = shft / int_n_bits;
int last_byt = arr_len - byte_shft - 1;
for (int i = 0; i < arr_len; i++){
if (i <= last_byt){
int msb_idx = i + byte_shft;
arr_out[i] = arr_in[msb_idx] << msb_shifts;
if (i != last_byt)
arr_out[i] |= arr_in[msb_idx + 1] >> lsb_shifts;
}
else arr_out[i] = 0;
}
}
Take a look at BigInteger implementation in Java, which internally stores data as an array of bytes. Specifically you can check out the funcion leftShift(). Syntax is the same as in C, so it wouldn't be too difficult to write a pair of funciontions like those. Take into account too, that when it comes to bit shifting you can take advange of unsinged types in C. This means that in Java to safely shift data without messing around with sign you usually need bigger types to hold data (i.e. an int to shift a short, a long to shift an int, ...)
I'm rather ashamed to admit that I don't know as much about bits and bit manipulation as I probably should. I tried to fix that this weekend by writing some 'reverse the order of bits' and 'count the ON bits' functions. I took an example from here but when I implemented it as below, I found I had to be looping while < 29. If I loop while < 32 (as in the example) Then when I try to print the integer (using a printBits function i've written) I seem to be missing the first 3 bits. This makes no sense to me, can someone help me out?
Thanks for everyone's help, I've added comments to show changes I've made.
int reverse(int n)
{
int r = 0;
int i = 0;
for(i = 0; i < 29; i++) //Should be i < 32
{
r = (r << 1) + (n & 1); //| instead of + to make it obvious I'm handling bits
n >>=1;
}
return r;
}
Here is my printBits function:
void printBits(int n)
{
int mask = 0X10000000; //unsigned int mask = 0X80000000;
while (mask)
{
if (mask & n)
{
printf("1");
}
else
{
printf("0");
}
mask >>= 1;
}
printf("\n");
}
And a working? reverse function
int reverse2(int n)
{
int r = n;
int s = sizeof(n) * 7; // int s = (sizeof(n) * 8) -1
for (n >>= 1; n; n >>=1)
{
r <<=1;
r |= n & 1;
s--;
r <<= s;
return r;
}
int mask = 0X10000000;
puts a 1 in bit 28. You want 0X80000000.
You have:
int mask = 0x10000000;
There are two problems here. You don't have the high bit set, and if you did, it still (probably) wouldn't work, as your compiler would be using arithmetic shift on a signed int.
You want to change your mask to:
unsigned int mask = 0x80000000;
For arithmetic shift, shifting 0x80000000 right will never become zero, as the sign bit will be magically extended into the other bits. See here for more details on arithmetic shift.
Print Bits is wrong, its 0x80000000 not 0x10000000.
>>> bin (0x80000000)
'0b10000000000000000000000000000000'
>>> bin (0x10000000)
'0b10000000000000000000000000000'
See 0x1... doesnt set the highest bit.
Instead of +, you should use | (bitwise or). And you should use < 32.
As written, this will reverse the lower 29 bits of n into r. The top three bits of n will be left in n (shifted down 29 bits) and not returned.
I would suspect a problem with your printBits function if you see something else.
edit
Your printBits function prints the lower 29 bits of n, so it all makes sense.