Bit Compressed Structure

I am currently working on a project where I need to store a fairly large number (~ units of billions) of structures in a vector. I also need to loop through this vector in a linear fashion, so the less data I have to go through, the better.

Therefore, I naturally began to optimize the size of a single structure. If, for example, I have several bool values, I can save the true / false value in one bit and compress all the bool values ​​into one char / 16-bit, regardless of what is of sufficient size. For some entries, I only need a 20-bit unsigned integer. Therefore, I can compress these values ​​again.

Then I get something like this (note that this is just a simplified example):

class Foo {
private:
    uint32_t m_time;
    uint32_t m_comb;

public:
    Foo(uint32_t t, uint32_t big, uint16_t small, bool is_blue, bool is_nice)
        : m_time(t), m_comb((big << 12) | (small << 2) | (is_blue << 1) | is_nice)
    { }

    uint32_t get_time()  const { return m_time; }
    uint32_t get_big()   const { return m_comb >> 12; }
    uint16_t get_small() const { return m_comb & 0b11111111100; }
    uint16_t is_blue()   const { return m_comb & 0b10; }
    uint16_t is_nice()   const { return m_comb & 0b1; }
};

, - ? , , , get<i>(), i- . , , . , .

+4
2

.

class Foo {
private:
    uint32_t m_time;
    uint32_t m_big : 20;
    uint32_t m_small : 10;
    uint32_t m_isblue : 1;
    uint32_t m_isnice : 1;
public:
    Foo(uint32_t t, uint32_t big, uint16_t small, bool is_blue, bool is_nice)
        : m_time(t), m_big(big), m_small(small), m_isblue(is_blue), m_isnice(is_nice)
    { }

    uint32_t get_time()  const { return m_time; }
    uint32_t get_big()   const { return m_big; }
    uint16_t get_small() const { return m_small; }
    uint16_t is_blue()   const { return m_isblue; }
    uint16_t is_nice()   const { return m_isnice; }
};

-, .

:

, , , :

9.6/1 (...) - . . - . [. - , . - , . -end note]

, , , . , , , , , , . , -.

+2

implementation-defined, / . , ( -) .

.

#include <iostream>

bool GetBit(uint32_t num, uint8_t pos)
{
    //check pos < sizeof(num)*8
    return (num >> pos) & 0x1;
}

uint8_t GetByte(uint32_t num, uint8_t pos)
{
    //check pos < sizeof(num)*8
    return (num >> pos) & 0xFF;    
}

uint16_t GetShort(uint32_t num, uint8_t pos)
{
    //check pos < sizeof(num)*8
    return (num >> pos) & 0xFFFF;    
}

uint32_t SetBit(bool val, uint32_t &dest, uint8_t pos)
{
    dest ^= (-val ^ dest) & (1 << pos);
    return dest;
}

uint32_t SetByte(uint8_t val, uint32_t &dest, uint8_t pos)
{
    dest &= ~(0xFF<<pos); //clean
    dest |= val<<pos; //set
    return dest;
}

uint32_t SetShort(uint16_t val, uint32_t &dest, uint8_t pos)
{
    dest &= ~(0xFFFF<<pos); //clean
    dest |= val<<pos; //set
    return dest;
}

void PrintBin(uint32_t s, const char* pszComment)
{
    std::cout << pszComment << ": " << std::endl;
    for (size_t n = 0; n < sizeof(s) * 8; n++)
        std::cout << GetBit(s, n) << ' ';
    std::cout << std::endl;
}

int main()
{
    uint32_t s = 4294967295; //all bits
    PrintBin(s, "Start");

    SetBit(false, s, 2); 
    PrintBin(s, "Set bit 2 to FALSE");

    SetByte(0, s, 22);
    PrintBin(s, "Set byte 22 to val 0");

    SetByte(30, s, 22);
    PrintBin(s, "Set byte 22 to val 30");

    SetShort(0, s, 4);
    PrintBin(s, "Set short 4 to val 0");

    SetShort(65000, s, 4);
    PrintBin(s, "Set short 4 to val 65000");

    std::cout << "byte at 22 = " << (int)GetByte(s, 22) << std::endl;
    std::cout << "short at 4 = " << (int)GetShort(s, 4) << std::endl;    
}

:

Start: 
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
Set bit 2 to FALSE: 
1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
Set byte 22 to val 0: 
1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 
Set byte 22 to val 30: 
1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 1 1 
Set short 4 to val 0: 
1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 0 0 0 1 1 
Set short 4 to val 65000: 
1 1 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 1 1 
byte at 22 = 30
short at 4 = 65000

#DEFINE .

0

All Articles