Josh Lake
Josh Lake

Reputation: 607

Packing data into arrays as fast as possible

Im starting with an array of 100,000 bytes where only the lower 6 bits in each byte have useful data. I need to pack that data into an array of 75,000 bytes as fast as possible, preserving the order of the data.

unsigned int Joinbits(unsigned int in) {}

Upvotes: 3

Views: 942

Answers (3)

Yttrill
Yttrill

Reputation: 4921

// 00111111 00111111 00111111 00111111
//   000000   001111   111122   222222
void pack6(
  register unsigned char o, 
  register unsigned char const *i, 
  unsigned char const *end
) 
{
  while(i!=end)
  {
    *o++ =  *i          << 2u | *(i+1) >> 4u; ++i;
    *o++ = (*i & 0xfu)  << 4u | *(i+1) >> 2u; ++i;
    *o++ = (*i & 0xfcu) << 6u | *(i+1)      ; i+=2;
  }
}

Will fail if input length is not divisible by 4. Assumes high 2 bits of input are zero. Completely portable. Reads 4 input bytes 6 times, so 50% inefficiency on reads, however the processor cache and compiler optimiser may help. Attempting to use a variable to save the read may be counter-productive, only an actual measurement can tell.

Upvotes: 4

v01d
v01d

Reputation: 1566

This is C, I don't know C++. And is probably filled with bugs, and is by no means the fastest way, it probably isn't even fast. But I wanted to just have a go, because it seemed like a fun challenge to learn something, so please hit me with what I did wrong! :D

unsigned char unpacked[100000];
unsigned int packed[75000 / 4];

for (int i = 0; i < (100000 / 6); i += 6) {
    unsigned int fourBytes = unpacked[i];
    fourBytes += unpacked[i + 1] << 6;
    fourBytes += unpacked[i + 2] << 12;
    fourBytes += unpacked[i + 3] << 18;
    fourBytes += unpacked[i + 4] << 24;
    fourBytes += unpacked[i + 5] << 30;

    unsigned short twoBytes = unpacked[i + 5] >> 2;
    twoBytes += unpacked[i + 6] << 4
    twoBytes += unpacked[i + 7] << 10;

    packed[i] = fourBytes;
    packed[i + 4] = twoBytes;
}

Upvotes: 0

Eugene Smith
Eugene Smith

Reputation: 9378

for(int pos=0; pos<100000; pos+=4)
{
   *(int*)out = (in[0] & 0x3F) | ((in[1] & 0x3F)<<6) | ((in[2] & 0x3F)<<12) | ((in[3] & 0x3F)<<18);
   in += 4;
   out += 3;
}

Upvotes: 0

Related Questions