SacrificerXY
SacrificerXY

Reputation: 334

How to extract a subset of a bitset larger than unsigned long long without using to_string or extracting bits one-by-one?

I want to extract a subset from a given bitset, where:

  1. both G(given bitset size) and S(subset size) are known at compile-time

  2. G > sizeof(unsigned long long) * 8

  3. S <= sizeof(int) * 8

  4. The subset may start anywhere in the given bitset

  5. The resulting subset should be a bitset of the correct size, S


I can isolate the subset using bitwise math but then bitset.to_ullong does not work because of overflow error.

I know I can use bitset.to_string and do string manipulations/conversion. What I'm currently doing is extracting bits one-by-one manually (this is enough for my use case).

I'm just interested to know if there are other ways of doing this.

Upvotes: 1

Views: 924

Answers (1)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 123070

std::bitset has bitshift operators, so for example you can write a function to place bits (begin,end] at the front:

template <size_t size>
std::bitset<size> extract_bits(std::bitset<size> x,int begin, int end) {
    (x >>= (size-end)) <<= (size-end);
    x <<= begin;
    return x;
}

For example to get the bits 1 and 2:

int main()
{
    std::bitset<6> x{12};
    std::cout << x << "\n";

    std::cout << extract_bits(x,1,3);
}

Output:

001100
010000

If you know begin and end at compile-time you can get a std::bitset containing only the desired bits:

template <size_t begin,size_t end,size_t in>
std::bitset<end-begin> crop(const std::bitset<in>& x) {
    return std::bitset<end-begin>{ x.to_string().substr(begin,end-begin) };
};

auto c = crop<1,3>(x);
std::cout << c;        // 01

If the bitset is too large to fit in a unsigned long long I don't know another way that does not use to_string() or loops for individual bits.

Upvotes: 2

Related Questions