Search code examples
javascriptjavabitwise-operatorsbit-packing

Bitwise packing/unpacking - generalized solution for arbitrary values


I'm trying to adapt this answer to arbitrary numeric values.

Let's say we have 3 (unsigned) numbers:

v1, v2, v3

and we know the respective max values they may have:

max1, max2, max3.

max1 * max2 * max3 < 2^32,

so the result (packed value) is to be within 32 bits.

How to pack/unpack them without "magic" hardcoding?


Solution

  • Here is a slightly different way to do it.

    int max1 = 1000;
    int max2 = 500;
    int max3 = 500;
    
    

    shift values determined based on most significant set bit of maximums.

    int size1 = 32-Integer.numberOfLeadingZeros(max1);
    int size2 = 32-Integer.numberOfLeadingZeros(max2);
    int size3 = 32-Integer.numberOfLeadingZeros(max3);
    
    

    mask values determined by complementing -1 shifted size bits.

    int mask1 = ~(-1<<size1);
    int mask2 = ~(-1<<size2);
    int mask3 = ~(-1<<size3);
    
    int v1 = 934;
    int v2 = 293;
    int v3 = 349;
    
    

    Nothing really new here. Second shift shifts both first and second values.

    int packed = (((v3<<size2)|v2)<<size1)|v1;
    

    Now reverse it

    v1 = packed&mask1;
    // this saves the shifted packed version for the next step
    v2 = (packed = packed>>>size1)&mask2;
    v3 = (packed>>>size2)&mask3;
            
    System.out.println(v1);
    System.out.println(v2);
    System.out.println(v3);
    

    Prints

    934
    293
    349