Let the numbers be packed in the same order like in the referenced answer, from right to left starting with v1
:
v3 <- v2 <- v1
We already have a solution from the referenced answer, but it only works for specific case (source data):
// packing:
packed = (v3 << 8) | (v2 << 7) | v1;
// unpacking:
v1 = packed & 0x7F;
v2 = (packed >> 7) & 1;
v3 = (packed >> 8);
The code above uses the following magic constants:
7
(size1
) - size in bits to allocate the 1st number (v1
).
1
(size2
) - ...(similarly) for the 2st number (v2
). Note that this constant is used above implicitly: 8 = 7 + 1
.
0x7F
(sample1
) - sample value to be used in bitwise comparison to unpack the 1st number (v1
).
1
(sample2
) - ...(similarly) for the 2st number (v2
).
In order to get a general solution it's enough to generalize the above constants. Let's name them size1
, size2
, sample1
and sample2
respectively. Below are their general definitions:
size1 = Math.floor(Math.log(max1) / Math.log(2)) + 1;
size2 = Math.floor(Math.log(max2) / Math.log(2)) + 1;
sample1 = Math.pow(2, size1 + 1) - 1;
sample2 = Math.pow(2, size2 + 1) - 1;
So with these constants the general solution should look like this:
// packing:
packed = v3 << (size1 + size2) | v2 << size1 | v1;
// unpacking:
v1 = packed & sample1;
v2 = (packed >> size1) & sample2;
v3 = packed >> (size1 + size2);