Search code examples
c++bit-manipulationbitset

How to read bits from std::bitset in a sliding window fashion and convert them to int?


I have std::bitset, where first n bits are set to some values. For each index in std::bitset, I want to read m bits (m < n) and convert them to int. When (index + m) > n, I want to wrap around.

For example, for n = 6 and m = 2:

std::bitset<8> my_bits {0b00101101}; // out of 8 bits, first 6 are set
// bit indexes            76543210

For each bit index in my_bits I want to take 2 bits at a time and convert them to int:

ind 0: 10 -> 1
ind 1: 01 -> 2
ind 2: 11 -> 3
ind 3: 10 -> 1
ind 4: 01 -> 2
ind 5: 11 -> 3 (wrapped around)

Right now I have the following code, which seems to work (run it here). I am looking for something more elegant.

#include <iostream>
#include <bitset>
#include <cmath>
int main() {
    const std::bitset <8> my_bits {0b00101101};
    int n = 6;
    int m = 2;

    for (int n_ind = 0; n_ind < n; ++n_ind) {

        std::cout << "ind " << n_ind << " -> ";

        int exp_2 = 0;
        int res = 0;
        for (int m_i = 0; m_i < m; ++m_i) {
            int curr_ind = (n_ind + m_i) % n; // % n is for wrap-around
            res += my_bits[curr_ind] * std::pow(2, exp_2);
            exp_2++;
        }

        std::cout << "res: " << res << std::endl;
    }

    return 0;
}

EDIT: I tried to write what Sam Varshavchik suggested, but it doesn't seem to produce the result I want, what am I doing wrong? Also, I don't know how to implement the "wrap around" in this case.

#include <iostream>
#include <bitset>
#include <cmath>

int main() {
    const std::bitset <8> my_bits {0b00101101};
    int n = 6;
    int m = 2;

    unsigned int mask = 0;
    for (int i = 0; i < m; ++i) {
        mask = (mask << 1) + 1;
    }

    int res = 0;
    for (int n_ind = 0; n_ind < n; ++n_ind) {

        int ind_t = n_ind % n;

        res <<= 1;
        res += my_bits[ind_t];
        res &= mask;

        std::cout << "ind " << ind_t << " -> ";
        std::cout << "res: " << res << std::endl;
        std::cout << "res after mask: " << std::bitset<32>(res) << std::endl; 
    }

    return 0;
}

Solution

  • Write a function. Encapsulate the algorithm. Accumulate results in a entity you would return. And use bitshifts instead of std::pow.

    #include <iostream>
    #include <bitset>
    #include <vector>
    
    template<size_t N>
    std::vector<int> convert_bitset_to_ints(const std::bitset<N>& bs, unsigned n, unsigned m) {
        std::vector<int> ret(n);
    
        for(size_t i = 0; i < n; ++i) {
            for (size_t j = 0; j < m; ++j) {
                ret[i] <<= 1;
                ret[i] |= bs[(i + j) % n];
            }
        }
    
        return ret;
    }
    
    int main() {
        const std::bitset <8> my_bits {0b00101101};
        auto v = convert_bitset_to_ints(my_bits, 6, 2);
    
        for (auto&& i : v) {
            std::cout << "res=" << i << " mask=" << std::bitset<2>(i) << "\n"; 
        }
    
        return 0;
    }