Showing posts with label Bitwise. Show all posts
Showing posts with label Bitwise. Show all posts

Friday, August 17, 2012

Generic Bitcount Algorithm in ANSI C

The purpose of the Bitcount algorithm is to return the number of bits set to 1 in a memory block.

A simple implementation of the Bitcount algorithm would be:
/*
 * Description:
 *  The function returns the number of bits set the 1 in a integer
 * Parameters:
 *  data - the integer who will be verified
 * Returns:
 *  The number of bits set to 1
 */
int SimpleBitCount(unsigned long data)
{
    /*Calculates the number of bits in a unsigned integer*/
    int size = sizeof(data) * 8;
    int counter = 0;
    /*Sets the first bit of the mask*/
    unsigned long mask = 0x0001U;
    int i;
    for(i = 0; i < size; i++)
    {
        /*Checks if an 1 was encountered*/
        if( (mask & data) !=0)
        {
            counter++;
        }
        /*Sets the next bit of the mask, clears the bit before*/
        mask<<=1;
    }
    return counter;
}
The main disadvantage of this implementation is that the data must be a integer or convertible to an integer.
Example:
#include<stdio.h>

int SimpleBitCount(unsigned long data);

int main(void)
{
    unsigned long v1 = 1539;

    long v1_ones   = SimpleBitCount(v1);
    long v1_zeroes = (sizeof(unsigned long)*8) - v1_ones;

    printf("Size %d bits\nOnes: %ld bits\nZeroes: %ld bits",
            sizeof(unsigned long)*8, v1_ones, v1_zeroes);

    return 0;
}
/*Output:
Size 32 bits
Ones: 4 bits
Zeroes: 28 bits
 */
To eliminate the the disadvantage mentioned before we need to make the sent data generic using a void pointer. Since, we couldn't possibly know the size of the sent data we must send the size of the data as a parameter.
/*
 * Description:
 *  The function returns the number of bits set the 1 in a memory block
 * Parameters:
 *  data - a generic pointer to the memory block
 *  bytes - the size of the memory block in bytes
 * Returns:
 *  The number of bits set to 1 in the memory block
 */
long GenericBitCount(void* data, size_t bytes)
{
    unsigned char* iterator = NULL;
    unsigned char  mask;
    unsigned int i, j;
    long counter = 0;

    /*Positions the iterator at the beginning of the memory block*/
    iterator = data;
    /*Iterates through all the bytes in the memory block*/
    for (i = 0; i < bytes; i++)
    {
        /*Reinitializes the mask for checking the first bit*/
        mask = 1;
        /*Iterates through all the bits of a byte from the memory block*/
        for (j = 0; j < 8; j++)
        {
            /*Checks if an 1 was encountered*/
            if ( ( (*iterator) & mask ) !=0 )
            {
                counter++;
            }
            /*Modifies the mask so the next bit from the byte can be checked*/
            mask <<= 1;
        }
        /*Moves the the next byte*/
        iterator = iterator + 1;
    }
    return counter;
}
Example:
#include<stdio.h>
#include<string.h>

typedef struct
{
    char firstByte;
    char secondByte;
}SampleStruct;

long GenericBitCount(void* data, size_t bytes);

int main(void)
{
    unsigned long v1 = 1539;
    char v2[] = "The bird is the word";
    SampleStruct v3 = {0xFF, 0xFF};

    long v1_ones   = GenericBitCount(&v1,sizeof(unsigned long));
    long v1_zeroes = (sizeof(unsigned long)*8) - v1_ones;

    long v2_ones   = GenericBitCount(&v2,sizeof(char) * strlen(v2));
    long v2_zeroes = (sizeof(char) * strlen(v2)*8) - v2_ones;

    long v3_ones   = GenericBitCount(&v3,sizeof(SampleStruct));
    long v3_zeroes = (sizeof(SampleStruct)) * 8 - v3_ones;

    printf("v1 : Size %5d bits Ones: %5ld bits Zeroes: %5ld bits\n"
           "v2 : Size %5d bits Ones: %5ld bits Zeroes: %5ld bits\n"
           "v3 : Size %5d bits Ones: %5ld bits Zeroes: %5ld bits\n",
           sizeof(unsigned long)*8, v1_ones, v1_zeroes,
           sizeof(char)*strlen(v2)*8, v2_ones, v2_zeroes,
           sizeof(SampleStruct)*8, v3_ones, v3_zeroes );

    return 0;
}
/*Output:
v1 : Size    32 bits Ones:     4 bits Zeroes:    28 bits
v2 : Size   160 bits Ones:    67 bits Zeroes:    93 bits
v3 : Size    16 bits Ones:    16 bits Zeroes:     0 bits
 */
As you observed in the example above, the generic bitcount algorithm can any type of data as opposite to the simple bitcount algorithm who can only work with integers.

Tuesday, October 18, 2011

Bitwise Shifts and Rotations in C

In the examples below, I shall use the uint8_t datatype (8 bits integer) from the stdint.h library. If you never used it before or if you have difficulties with the "basic" bitwise operations you should read this first.

1.Shift left operation
Description
Shifting bits left with n positions means moving every bit from its position n positions to the left starting with the leftmost bit. The bits who are added right will have the value 0.
Example:

Bits
7th
6th
5th
4th
3th
2nd
1st
0th

a
0
1
1
0
1
0
1
1
107
a<<3
0
1
0
1
1
0
0
0
88  
In the first row, the bits who will be lost have a red background, and the bits who will be shifted have a green background. In the second row the bits who were added have a red background and the bits who were shifted have a green background.
Syntax
#include<stdio.h>
#include<stdint.h>

int main(void)
{
   uint8_t a = 107U;
   uint8_t ashiftleft3 = a<<3;
   printf("a<<3 %u",ashiftleft3);
   return 0;
}
/*Output
a<<3 88
*/
2.Shift right operation
Description
Shifting bits right with n positions means moving every bit from its position n positions to the right starting with the rightmost bit. The bits who are added left will have the value 0. 
Example:

Bits
7th
6th
5th
4th
3th
2nd
1st
0th

a
0
1
1
0
1
0
1
1
107
a<<3
0
0
0
0
1
1
0
1
13
In the first row, the bits who will be lost have a red background, and the bits who will be shifted have a green background. In the second row the bits who were added have a red background and the bits who were shifted have a green background.
Syntax:
#include<stdio.h>
#include<stdint.h>

int main(void)
{
   uint8_t a = 107U;
   uint8_t ashiftrightt3 = a>>3;
   printf("a>>3 %u",ashiftrightt3);
   return 0;
}
/*Output
a<<3 88
*/
3.Rotate left operation
Description
Rotating left with n positions means moving the first n leftmost bits from their position to the right of the rightmost bit.

Some compilers have the function unsigned int _rotl(unsigned int number, unsigned int bits) which performs a left rotation, but the function is not considered ANSI. Also, the function uses 32 bits instead of 8. The _rotl function can be found in the stdlib.h library.

If you do not have this function for your compiler (or you want its 8 bit version), you can easily implement it as:
uint8_t _rotl(uint8_t value, uint8_t shift)
{
   if ((shift &= 7) == 0)
   {
      return value;
   }
   else
   {
      return ((value << shift) | (value >> (8 - shift)));
   }
}
Example 
Bits
7th
6th
5th
4th
3th
2nd
1st
0th

a
0
1
1
0
1
0
1
1
107
Bits
4th
3th
2nd
1st
0th
7th
6th
5th

_rotl(a,3)
0
1
0
1
1
0
1
1
91
Syntax:
#include<stdio.h>
#include<stdint.h>

uint8_t _rotl(uint8_t value, uint8_t shift);

int main(void)
{
   uint8_t a = 107U;
   uint8_t arotl3 = _rotl(a,3);
   printf("arotl3 %u",arotl3);
   return 0;
}
/*Output
arotl3 91
*/
4.Rotate right operation
Description
Rotating right with n positions means moving the first n rightmost bits from their position to the left of the leftmost bit.

Some compilers have the function unsigned int _rotr(unsigned int number, unsigned int bits) which performs a right rotation, but the function is not considered ANSI. Also, the function uses 32 bits instead of 8. The _rotl function can be found in the stdlib.h library.

If you do not have this function for your compiler (or you want its 8 bit version), you can easily implement it as:
uint8_t _rotr(const uint8_t value, uint8_t shift)
{
    if( (shift &= 7) == 0)
    {
        return value;
    }
    else
    {
        return ( (value >> shift) | (value << (8 - shift)) );
    }
}
Example 
Bits
7th
6th
5th
4th
3th
2nd
1st
0th

a
0
1
1
0
1
0
1
1
107
Bits
2nd
1st
0th
7th
6th
5th
4th
3th

_rotr(a,3)
0
1
1
0
1
1
0
1
109
Syntax
#include<stdio.h>
#include<stdint.h>

uint8_t _rotr(uint8_t value, uint8_t shift);

int main(void)
{
   uint8_t a = 107U;
   uint8_t arotr3 = _rotr(a,3);
   printf("arotl3 %u",arotr3);
   return 0;
}
/*Output
arotl3 109
*/

Question: In which context do you use shifts and rotations?

References:
http://en.wikipedia.org/wiki/Bitwise_operations_in_C

How to Set, Clear, Check, Toggle and Copy Bits in ANSI C

In the examples below, I will use the uint8_t primitive data type from the stdint.h ANSI library. If you never used this datatype or if you find this article a little tough to understand you may want to read this first. 

1.Setting a bit
Description
Setting the x-th bit of a number means changing the x-th bit value to 1.
Example
Considering a number a = 36, we shall set its 6th bit.
Bits 7th 6th 5th 4th 3rd 2nd 1st 0th
a 0 0 0 1 0 1 0 0 36
a set 6 0 1 0 1 0 1 0 0 100
Syntax
#include<stdio.h>
#include<stdint.h>

int main(void)
{
   uint8_t a=36;
   uint8_t b=6;
   a |= (1<<b);
   printf("a set b : %u",a);
   return 0;
}
/*Output
a set b : 100
*/
2.Clearing a bit
Description
Clearing the x-th bit of a number means changing the x-th bit value to 0.
Example
Bits 7th 6th 5th 4th 3rd 2nd 1st 0th
a 0 0 1 0 0 1 0 0 36
a clear 5 0 0 0 0 0 1 0 0 4
Syntax
#include<stdio.h>
#include<stdint.h>

int main(void)
{
   uint8_t a=100;
   uint8_t b=6;
   a &= ~(1<<b);
   printf("a clr b : %u",a);
   return 0;
}
/*Output
a clr b : 36
*/
3.Checking a bit
Description
Checking the x-th bit of a number means verifying the value of x-th bit (which can be 0 or 1).
Example:
a = 36 = 0010 0100
After checking the 5th bit, the value which is returned should be 1.
Syntax
#include<stdio.h>
#include<stdint.h>

int main(void)
{
   uint8_t a=100;
   uint8_t b=6;
   uint8_t checkResult = a & (1<<b);
   printf("a chk b : %u",checkResult);
   return 0;
}
/*Output
a chk b : 64
*/
4.Toggling a bit
Toggling the x-th bit of a number means changing its current value to its complementary value (if the bit is 1, it will be 0 and if the bit is 0 it will be 1).
Example:

Bits 7th 6th 5th 4th 3rd 2nd 1st 0th
a 0 0 1 0 0 1 0 0 36
a toggle 1 0 0 0 0 0 1 0 1 37
a toggle 5 0 0 0 0 0 1 0 0 4

Syntax
#include<stdio.h>
#include<stdint.h>

int main(void)
{
   uint8_t a=36;
   uint8_t b=5;
   a ^= (1<<b);
   printf("a tgl b : %u",a);
   return 0;
}
/*Output
a tgl b : 4
*/
5.Copying bits from a number to another
Description
Copying bits means that you modify certain bits of a number according to the same certain bits of another number. Those "certain bits" are called a mask.
Example:
Let us consider two numbers a and b where a = 36 and b = 6. We will want concatenate the first 4 bits of a and the last 4 bits of b. In order to do this we shall define a mask who needs to have the bits we want to get from a set to 1 and the bits we want to get from b set to 0. So mask will be equal to 240.

Bits 7th 6th 5th 4th 3rd 2nd 1st 0th
a 0 0 1 0 0 1 0 0 36
b 0 0 0 0 0 1 1 0 6
mask 1 1 1 1 0 0 0 0 240
~mask 0 0 0 0 1 1 1 1 15

In order to concatenate a and b, we will need to clear the bits we do not want to be in the final number by using the AND operator. Then we shall concatenate the results using the OR operator.
a' = a AND mask 
b' = b AND (~mask)
res = a' OR b' 

Bits 7th 6th 5th 4th 3rd 2nd 1st 0th
a 0 0 1 0 0 1 0 0 36
b 0 0 0 0 0 1 1 0 6
mask 1 1 1 1 0 0 0 0 240
~mask 0 0 0 0 1 1 1 1 15
a & (mask) 0 0 1 0 0 0 0 0 32
b & (~mask) 0 0 0 0 0 1 1 0 6
a' | b' 0 0 1 0 0 1 1 0 38

Syntax
#include<stdio.h>
#include<stdint.h>

int main(void)
{
   uint8_t a=36;
   uint8_t b=6;
   uint8_t mask = 240;
   a = (a&mask)|( b&(~mask) );
   printf("a cpy b : %u",a);
   return 0;
}
/*Output
a cpy b : 38
*/
Since these operations are used often (especially on embedded systems), here are some macros for them:
#define BitSet(a,b)       ( (a) |=  ( 1<<(b) ) ) 
#define BitClear(a,b)     ( (a) &= ~( 1<<(b) ) )
#define BitCheck(a,b)     ( (a) &   ( 1<<(b) ) ) 
#define BitToggle(a,b)    ( (a) ^=  ( 1<<(b) ) )
#define BitCopy(a,mask,b) ( (a) = ( (a) & (mask) )|( (b) & (~(mask) ) ) 
Question: How often do you use in projects these bitwise operations?

References:
http://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit-in-c
Related Posts Plugin for WordPress, Blogger...