简体   繁体   中英

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?

在此处输入图片说明

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

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;
}

Let the bit position difference (eg 7 - 4 in this case) be diff .

If 2 diff > 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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM