Breaking apart bit patterns, shifting and creating new patterns - c

As part of a larger problem, I have to take some binary value: 00000000 11011110 (8)
Then, I have to:
Derive the bit count in this function - so I've done that by finding the place of the most sig fig.
Then store the first 6 numbers of this value into the value 128, such that it equals: 10011110
Then store the last 5 numbers of this value into the value 192, such that it equals: 11000011 10011110
The two bytes should be stored in some array, buffer[]
I have written this function however, position does not appear to initialise properly in gdb and the values are not outputting correctly. This is my attempt:
void create_value(unsigned short init_val, unsigned char buffer[])
{
// get the count
int position = 0;
while (init_val >>= 1)
position++;
// get total
int count = position++;
int start = 128;
for (int i = 0; i < 7; i++)
if (((1 << i) & init_val) != 0) start = start | 1 << i;
buffer[0] = start;
start = 192;
for (int i = 7; i < 11; i++) {
if (((1 << i) & init_val) !=0) start = start | 1 << i;
}
buf[1] = start;
}

After
while (init_val >>= 1)
position++;
init_val will be 0. When you later use
if (((1 << i) & init_val) != 0) start = start | 1 << i;
you will never change start.
So, after reading through what you're trying to do (which is pretty confusingly described), why don't you:
void create_value(unsigned short init_value, unsigned char buffer[])
{
buffer[0] = (init_value & 63) | 128;
buffer[1] = ((init_value >> 6) & 31) | 192;
return;
}
What this does: init_value & 63 masks off all but the lowest 6 bits in init_value, as you wanted. The | 128 then sets the most significant bit of the byte (IFF CHAR_BIT == 8, mind you).
(init_value >> 6) shifts init_value down by 6 bits, so now the original bits 6-11 are bits 0-4. & 31 masks off all bit the lowest 5 bits in this value, | 192 sets the two most significant bits.

Related

Reversing Endianess C

I'm lost on bit shifting operations, I'm trying to reverse byte order on 32 bit ints, what I've managed to look up online I only got this far but cant seem to find why its not working
int32_t swapped = 0; // Assign num to the tmp
for(int i = 0; i < 32; i++)
{
swapped |= num & 1; // putting the set bits of num
swapped >>= 1; //shift the swapped Right side
num <<= 1; //shift the swapped left side
}
And I'm printing like this
num = swapped;
for (size_t i = 0; i < 32; i++)
{
printf("%d",(num >> i));
}
Your code looks likes its attempting to swap bits, and not bytes. If you are wanting to swap bytes, then the 'complete' method would be:
int32_t swapped = ((num >> 24) & 0x000000FF) |
((num >> 8) & 0x0000FF00) |
((num << 8) & 0x00FF0000) |
((num << 24) & 0xFF000000);
I say 'complete', because the last bitwise-and can be omitted, and the first bitwise-and can be omitted if num is unsigned.
If you want to swap the bits in a 32bit number, your loop should probably max out at 16 (if it's 32, the first 16 steps will swap the bits, the next 16 steps will swap them back again).
int32_t swapped = 0;
for(int i = 0; i < 16; ++i)
{
// the masks for the two bits (hi and lo) we will be swapping
// shift a '1' to the correct bit location based on the index 'i'
uint32_t hi_mask = 1 << (31 - i);
uint32_t lo_mask = 1 << i;
// use bitwise and to mask out the original bits in the number
uint32_t hi_bit = num & hi_mask;
uint32_t lo_bit = num & lo_mask;
// shift the bits so they switch places
uint32_t new_lo_bit = hi_bit >> (31 - i);
uint32_t new_hi_bit = lo_bit << (31 - i);
// use bitwise-or to combine back into an int
swapped |= new_lo_bit;
swapped |= new_hi_bit;
}
Code written for readability - there are faster ways to reverse the bits in a 32bit number. As for printing:
for (size_t i = 0; i < 32; i++)
{
bool bit = (num >> (31 - i)) & 0x1;
printf(bit ? "1" : "0");
}

Word every 2 bits to symbol

I have a function that read a word, bit by bit and change to symbol:
I need help to change it to read every 2 bits and change to symbol.
I don't have an idea for it and I need your help guys
void PrintWeirdBits(word w , char* buf){
word mask = 1<<(BITS_IN_WORD-1);
int i;
for(i=0;i<BITS_IN_WORD;i++){
if(mask & w)
buf[i]='/';
else
buf[i]='.';
mask>>=1;
}
buf[i] = '\0';
}
Needed symbols:
00 - *
01 - #
10 - %
11 - !
Here is my proposal for your issue.
Using a lookup table for the symbol decoding will eliminate the need in if statements.
(I assumed word is an unsigned 16 bits data type)
#define BITS_PER_SIGN 2
#define BITS_PER_SIGN_MSK 3 // decimal 3 is 0b11 in binary --> two bits set
// General define could be:
// ((1u << BITS_PER_SIGN) - 1)
#define INIT_MASK (BITS_PER_SIGN_MSK << (BITS_IN_WORD - BITS_PER_SIGN))
void PrintWeirdBits(word w , char* buf)
{
static const char signs[] = {'*', '#', '%', '!'};
unsigned mask = INIT_MASK;
int i;
int sign_idx;
for(i=0; i < BITS_IN_WORD / BITS_PER_SIGN; i++)
{
// the bits of the sign represent the index in the signs array
// just need to align these bits to start from bit 0
sign_idx = (w & mask) >> (BITS_IN_WORD - (i + 1)*BITS_PER_SIGN);
// store the decoded sign in the buffer
buf[i] = signs[sign_idx];
// update the mask for the next symbol
mask >>= BITS_PER_SIGN;
}
buf[i] = '\0';
}
Here it seems to be working.
With small effort it can be updated to a generic code for any bit width of the symbol as long as it is power of two (1, 2, 4, 8) and smaller that BITS_IN_WORD.
Assuming word is unsigned int or an unsigned integer type.
void PrintWeirdBits(word w , char* buf){
word mask = 3 << (BITS_IN_WORD -2);
int i;
word cmp;
for(i=0;i<BITS_IN_WORD/2;i++){
cmp = (mask & w) >> (BITS_IN_WORD -2 -2i);
if(cmp == 0x00)
{
buf[i]='*';
}
else if (cmp == 0x01)
{
buf[i]='#';
}
else if (cmp == 0x02)
{
buf[i]='%';
}
else
{
buf[i]='!';
}
mask>>=2;
}
buf[i] = '\0';
}
The important part is
cmp = (mask & w) >> (BITS_IN_WORD -2 -2i);
Here mask and the input w is bitwise ANDed and the result is right shifted to get the value in the first two bits. These bits are compared to get the result.

Effective bits calculation along the array in specified position on STM32

I'm wondering if someone know effective approach to calculate bits in specified position along array?
Assuming that OP wants to count active bits
size_t countbits(uint8_t *array, int pos, size_t size)
{
uint8_t mask = 1 << pos;
uint32_t result = 0;
while(size--)
{
result += *array++ & mask;
}
return result >> pos;
}
You can just loop the array values and test for the bits with a bitwise and operator, like so:
int arr[] = {1,2,3,4,5};
// 1 - 001
// 2 - 010
// 3 - 011
// 4 - 100
// 5 - 101
int i, bitcount = 0;
for (i = 0; i < 5; ++i){
if (arr[i] & (1 << 2)){ //testing and counting the 3rd bit
bitcount++;
}
}
printf("%d", bitcount); //2
Note that i opted for 1 << 2 which tests for the 3rd bit from the right or the third least significant bit just to be easier to show. Now bitCount would now hold 2 which are the number of 3rd bits set to 1.
Take a look at the result in Ideone
In your case you would need to check for the 5th bit which can be represented as:
1 << 4
0x10000
16
And the 8th bit:
1 << 7
0x10000000
256
So adjusting this to your bits would give you:
int i, bitcount8 = 0, bitcount5 = 0;
for (i = 0; i < your_array_size_here; ++i){
if (arr[i] & 0x10000000){
bitcount8++;
}
if (arr[i] & 0x10000){
bitcount5++;
}
}
If you need to count many of them, then this solution isn't great and you'd be better off creating an array of bit counts, and calculating them with another for loop:
int i, j, bitcounts[8] = {0};
for (i = 0; i < your_array_size_here; ++i){
for (j = 0; j < 8; ++j){
//j will be catching each bit with the increasing shift lefts
if (arr[i] & (1 << j)){
bitcounts[j]++;
}
}
}
And in this case you would access the bit counts by their index:
printf("%d", bitcounts[2]); //2
Check this solution in Ideone as well
Let the bit position difference (e.g. 7 - 4 in this case) be diff.
If 2diff > n, then code can add both bits at the same time.
void count(const uint8_t *Array, size_t n, int *bit7sum, int *bit4sum) {
unsigned sum = 0;
unsigned mask = 0x90;
while (n > 0) {
n--;
sum += Array[n] & mask;
}
*bit7sum = sum >> 7;
*bit4sum = (sum >> 4) & 0x07;
}
If the processor has a fast multiply and n is still not too large, like n < pow(2,14) in this case. (Or n < pow(2,8) in the general case)
void count2(const uint8_t *Array, size_t n, int *bit7sum, int *bit4sum) {
// assume 32 bit or wider unsigned
unsigned sum = 0;
unsigned mask1 = 0x90;
unsigned m = 1 + (1u << 11); // to move bit 7 to the bit 18 place
unsigned mask2 = (1u << 18) | (1u << 4);
while (n > 0) {
n--;
sum += ((Array[n] & mask1)*m) & mask2;
}
*bit7sum = sum >> 18;
*bit4sum = ((1u << 18) - 1) & sum) >> 4);
}
Algorithm: code is using a mask, multiply, mask to separate the 2 bits. The lower bit remains in it low position while the upper bit is shifted to the upper bits. Then a parallel add occurs.
The loop avoids any branching aside from the loop itself. This can make for fast code. YMMV.
With even larger n, break it down into multiple calls to count2()

Extracting a particular range of bits and find number of zeros between them in C

I want to extract a particular range of bits in an integer variable.
For example: 0xA5 (10100101)
I want to extract from bit2 to bit5. i.e 1001 to a variable and count number of zeros between them.
I have another variable which give the starting point, which means in this case the value of the variable is 2. So the starting point can be find by 0xA5 >> 2.
5th bit position is a random position here..means it can be 6 or 7. The main idea is whichever bit is set to 1 after 2nd bit. I have to extract that..
How can I do rest of the part ?
Assuming you are dealing with unsigned int for your variable.
You will have to construct the appropriate mask.
Suppose you want the bits from position x to position y, there need to be y - x + 1 1s in the mask.
You can get this by -
int digits = y - x + 1;
unsigned int mask = 1u << digits - 1;
Now you need to remove the lower x bits from the initial number, which be done by -
unsigned int result = number >> x;
Finally apply the mask to remove the upper bits -
result = result & mask;
In this example we put 0 or 1 values into array. After that you can treat array as you like.
#include <stdio.h>
#include <stdint.h>
int main(int argc, char **argv) {
uint8_t value = 0xA5;
unsigned char bytes[8];
unsigned char i;
for (i = 0; i < 8; i++) {
bytes[i] = (value & (1 << i)) != 0 ? 1 : 0;
}
for (i = 0; i < 8; i++) {
printf("%d", bytes[i]);
}
return 0;
}
You could use a mask and the "&" (AND) operation:
a = 0xA5;
a = a >> OFFSET; //OFFSET
mask = 0x0F; // equals 00001111
a = a & mask;
In your example a = 0xA5 (10100101), and the offset is 2.
a >> 2 a now equals to 0x29 (00101001)
a & 0x0F (00101001 AND
00001111) = 00001001 = 0x09
If you want bits from the offset X then shift right by X.
If you want Y bits, then then mask (after the shift) will be 2 to the power of Y minus one (for your example with four bits, 2 to the power of 4 is 16, minus one is 15 which is 1111 binary). This can be dome by using left-shifting by Y bits and subtracting 1.
However, the masking isn't needed if you want to count the number of zeros in the wanted bits, only the right shift. Loop Y times, each time shifting a 1 left one step, and check using bitwise and if the value is zero. If it is then increment a counter. At the end of the loop the counter is the number of zeros.
To put it all in code:
// Count the number of zeros in a specific amount of bits starting at a specific offset
// value is the original value
// offset is the offset in bits
// bits is the number of bits to check
unsigned int count_zeros(unsigned int value, unsigned int offset, unsigned int bits)
{
// Get the bits we're interested in the rightmost position
value >>= offset;
unsigned int counter = 0; // Zero-counter
for (unsigned int i = 0; i < bits; ++i)
{
if ((value & (1 << i)) == 0)
{
++counter; // Bit is a zero
}
}
return counter;
}
To use with the example data you have:
count_zeros(0xa5, 2, 4);
The result should be 2. Which it is if you see this live program.
int32_t do_test(int32_t value, int32_t offset)
{
int32_t _zeros = 1;
value >>= offset;
int i = 1;
while(1) {
if((value >> i) % 2 == 0) {
_zeros += 1;
i++;
} else {
break;
}
}
}
int result = (0xA5 >> 2) & 0x0F;
Truth table for the & operator
| INPUTS | OUTPUT |
-----------------------
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
-----------------------

how to make a bit-set/byte-array conversion in c

Given an array,
unsigned char q[32]="1100111...",
how can I generate a 4-bytes bit-set, unsigned char p[4], such that, the bit of this bit-set, equals to value inside the array, e.g., the first byte p[0]= "q[0] ... q[7]"; 2nd byte p[1]="q[8] ... q[15]", etc.
and also how to do it in opposite, i.e., given bit-set, generate the array?
my own trial out for the first part.
unsigned char p[4]={0};
for (int j=0; j<N; j++)
{
if (q[j] == '1')
{
p [j / 8] |= 1 << (7-(j % 8));
}
}
Is the above right? any conditions to check? Is there any better way?
EDIT - 1
I wonder if above is efficient way? As the array size could be upto 4096 or even more.
First, Use strtoul to get a 32-bit value. Then convert the byte order to big-endian with htonl. Finally, store the result in your array:
#include <arpa/inet.h>
#include <stdlib.h>
/* ... */
unsigned char q[32] = "1100111...";
unsigned char result[4] = {0};
*(unsigned long*)result = htonl(strtoul(q, NULL, 2));
There are other ways as well.
But I lack <arpa/inet.h>!
Then you need to know what byte order your platform is. If it's big endian, then htonl does nothing and can be omitted. If it's little-endian, then htonl is just:
unsigned long htonl(unsigned long x)
{
x = (x & 0xFF00FF00) >> 8) | (x & 0x00FF00FF) << 8);
x = (x & 0xFFFF0000) >> 16) | (x & 0x0000FFFF) << 16);
return x;
}
If you're lucky, your optimizer might see what you're doing and make it into efficient code. If not, well, at least it's all implementable in registers and O(log N).
If you don't know what byte order your platform is, then you need to detect it:
typedef union {
char c[sizeof(int) / sizeof(char)];
int i;
} OrderTest;
unsigned long htonl(unsigned long x)
{
OrderTest test;
test.i = 1;
if(!test.c[0])
return x;
x = (x & 0xFF00FF00) >> 8) | (x & 0x00FF00FF) << 8);
x = (x & 0xFFFF0000) >> 16) | (x & 0x0000FFFF) << 16);
return x;
}
Maybe long is 8 bytes!
Well, the OP implied 4-byte inputs with their array size, but 8-byte long is doable:
#define kCharsPerLong (sizeof(long) / sizeof(char))
unsigned char q[8 * kCharsPerLong] = "1100111...";
unsigned char result[kCharsPerLong] = {0};
*(unsigned long*)result = htonl(strtoul(q, NULL, 2));
unsigned long htonl(unsigned long x)
{
#if kCharsPerLong == 4
x = (x & 0xFF00FF00UL) >> 8) | (x & 0x00FF00FFUL) << 8);
x = (x & 0xFFFF0000UL) >> 16) | (x & 0x0000FFFFUL) << 16);
#elif kCharsPerLong == 8
x = (x & 0xFF00FF00FF00FF00UL) >> 8) | (x & 0x00FF00FF00FF00FFUL) << 8);
x = (x & 0xFFFF0000FFFF0000UL) >> 16) | (x & 0x0000FFFF0000FFFFUL) << 16);
x = (x & 0xFFFFFFFF00000000UL) >> 32) | (x & 0x00000000FFFFFFFFUL) << 32);
#else
#error Unsupported word size.
#endif
return x;
}
For char that isn't 8 bits (DSPs like to do this), you're on your own. (This is why it was a Big Deal when the SHARC series of DSPs had 8-bit bytes; it made it a LOT easier to port existing code because, face it, C does a horrible job of portability support.)
What about arbitrary length buffers? No funny pointer typecasts, please.
The main thing that can be improved with the OP's version is to rethink the loop's internals. Instead of thinking of the output bytes as a fixed data register, think of it as a shift register, where each successive bit is shifted into the right (LSB) end. This will save you from all those divisions and mods (which, hopefully, are optimized away to bit shifts).
For sanity, I'm ditching unsigned char for uint8_t.
#include <stdint.h>
unsigned StringToBits(const char* inChars, uint8_t* outBytes, size_t numBytes,
size_t* bytesRead)
/* Converts the string of '1' and '0' characters in `inChars` to a buffer of
* bytes in `outBytes`. `numBytes` is the number of available bytes in the
* `outBytes` buffer. On exit, if `bytesRead` is not NULL, the value it points
* to is set to the number of bytes read (rounding up to the nearest full
* byte). If a multiple of 8 bits is not read, the last byte written will be
* padded with 0 bits to reach a multiple of 8 bits. This function returns the
* number of padding bits that were added. For example, an input of 11 bits
* will result `bytesRead` being set to 2 and the function will return 5. This
* means that if a nonzero value is returned, then a partial byte was read,
* which may be an error.
*/
{ size_t bytes = 0;
unsigned bits = 0;
uint8_t x = 0;
while(bytes < numBytes)
{ /* Parse a character. */
switch(*inChars++)
{ '0': x <<= 1; ++bits; break;
'1': x = (x << 1) | 1; ++bits; break;
default: numBytes = 0;
}
/* See if we filled a byte. */
if(bits == 8)
{ outBytes[bytes++] = x;
x = 0;
bits = 0;
}
}
/* Padding, if needed. */
if(bits)
{ bits = 8 - bits;
outBytes[bytes++] = x << bits;
}
/* Finish up. */
if(bytesRead)
*bytesRead = bytes;
return bits;
}
It's your responsibility to make sure inChars is null-terminated. The function will return on the first non-'0' or '1' character it sees or if it runs out of output buffer. Some example usage:
unsigned char q[32] = "1100111...";
uint8_t buf[4];
size_t bytesRead = 5;
if(StringToBits(q, buf, 4, &bytesRead) || bytesRead != 4)
{
/* Partial read; handle error here. */
}
This just reads 4 bytes, and traps the error if it can't.
unsigned char q[4096] = "1100111...";
uint8_t buf[512];
StringToBits(q, buf, 512, NULL);
This just converts what it can and sets the rest to 0 bits.
This function could be done better if C had the ability to break out of more than one level of loop or switch; as it stands, I'd have to add a flag value to get the same effect, which is clutter, or I'd have to add a goto, which I simply refuse.
I don't think that will quite work. You are comparing each "bit" to 1 when it should really be '1'. You can also make it a bit more efficient by getting rid of the if:
unsigned char p[4]={0};
for (int j=0; j<32; j++)
{
p [j / 8] |= (q[j] == `1`) << (7-(j % 8));
}
Going in reverse is pretty simple too. Just mask for each "bit" that you set earlier.
unsigned char q[32]={0};
for (int j=0; j<32; j++) {
q[j] = p[j / 8] & ( 1 << (7-(j % 8)) ) + '0';
}
You'll notice the creative use of (boolean) + '0' to convert between 1/0 and '1'/'0'.
According to your example it does not look like you are going for readability, and after a (late) refresh my solution looks very similar to Chriszuma except for the lack of parenthesis due to order of operations and the addition of the !! to enforce a 0 or 1.
const size_t N = 32; //N must be a multiple of 8
unsigned char q[N+1] = "11011101001001101001111110000111";
unsigned char p[N/8] = {0};
unsigned char r[N+1] = {0}; //reversed
for(size_t i = 0; i < N; ++i)
p[i / 8] |= (q[i] == '1') << 7 - i % 8;
for(size_t i = 0; i < N; ++i)
r[i] = '0' + !!(p[i / 8] & 1 << 7 - i % 8);
printf("%x %x %x %x\n", p[0], p[1], p[2], p[3]);
printf("%s\n%s\n", q,r);
If you are looking for extreme efficiency, try to use the following techniques:
Replace if by subtraction of '0' (seems like you can assume your input symbols can be only 0 or 1).
Also process the input from lower indices to higher ones.
for (int c = 0; c < N; c += 8)
{
int y = 0;
for (int b = 0; b < 8; ++b)
y = y * 2 + q[c + b] - '0';
p[c / 8] = y;
}
Replace array indices by auto-incrementing pointers:
const char* qptr = q;
unsigned char* pptr = p;
for (int c = 0; c < N; c += 8)
{
int y = 0;
for (int b = 0; b < 8; ++b)
y = y * 2 + *qptr++ - '0';
*pptr++ = y;
}
Unroll the inner loop:
const char* qptr = q;
unsigned char* pptr = p;
for (int c = 0; c < N; c += 8)
{
*pptr++ =
qptr[0] - '0' << 7 |
qptr[1] - '0' << 6 |
qptr[2] - '0' << 5 |
qptr[3] - '0' << 4 |
qptr[4] - '0' << 3 |
qptr[5] - '0' << 2 |
qptr[6] - '0' << 1 |
qptr[7] - '0' << 0;
qptr += 8;
}
Process several input characters simultaneously (using bit twiddling hacks or MMX instructions) - this has great speedup potential!

Resources