2

I have 2 4-bit numbers (X0X1X2X3 and Y0Y1Y2Y3) and I want to combine them so that I would create an 8-bit number like that:

X0X1X2X3 
Y0Y1Y2Y3  => X0Y0X1Y1X2Y2X3Y3

I know how to concatenate them in order to create the X0X1X1X3Y0Y1Y2Y3 but I am stuck on how to compose them in the pattern explained above.

Any hints?

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
DimSarak
  • 452
  • 2
  • 5
  • 11

3 Answers3

3

A very quick way of interleaving four-bit numbers is with a look-up table:

unsigned int spread[] = {
    0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, 
    0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55
};

You can use spread[] array, which "spreads" bits of the original, to construct your output as follows:

unsigned int res = (spread[x] << 1) | spread[y];

The trick is in the construction of the look-up table. Its values are selected in such a way that the bits of the index are interleaved with zeros. For example, 0x07, or 01112, becomes 0x15, or 000101012.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Of course, this is feasible only if the number is small. If you have too many bits this `spread` array may be too big to be worthwhile. – Nathan Fellman Jul 12 '16 at 12:32
  • 1
    @NathanFellman A table with 256 entries would be sufficient to deal with most numbers one byte at a time, rather than one bit at a time. Since OP specifically asks for four-bit numbers, it shouldn't be an issue for him. – Sergey Kalinichenko Jul 12 '16 at 12:39
3

Here's a fairly direct way of performing this transformation:

uint8_t result;
result |= (x & 8) << 4;
result |= (y & 8) << 3;
result |= (x & 4) << 3;
result |= (y & 4) << 2;
result |= (x & 2) << 2;
result |= (y & 2) << 1;
result |= (x & 1) << 1;
result |= (y & 1) << 0;
dbush
  • 205,898
  • 23
  • 218
  • 273
0

You can also do this in one line.

 uint8_t result =  (varX << 4) | (varY);
alkman
  • 1
  • 1