Search code examples
javascripttypescriptbit-manipulation

Unpacking number is resulting in out of order


I have the following variable:

const input = [0x0001000200030004]

And I have a function to unpack four numbers from 1 (it cames from a C++ code, where I have four int16_t that are packed into a single uint64_t)

export function unpack(input: number[]) {
  const output: number[] = []

  for (const packed of input) {
    for (let i = 0; i < 4; i++) {
      const num = (packed >> (i * 16)) & 0xffff

      const signedNum = num < 0x8000 ? num : -(0x10000 - num)

      output.push(signedNum)
    }
  }

  return output
}

The function kind works; however, it is out of order.

Instead of the output being [1, 2, 3, 4], it is [1, 2, 4, 3].

What I'm doing wrong?


Solution

  • The issue has already been identified in the comments and in @Unmitigated's answer (namely that bitwise operators work on 32 bit numbers in JS, which cannot represent your uint64), but a better solution is to use a BigUint64Array and a Int16Array as views on the same buffer for the conversion:

    function unpack(input) {
      const buffer = new BigUint64Array(input).buffer;
      return Array.from(new Int16Array(buffer));
    }
    
    console.log(unpack([0x0001000200030004n]))

    However, you might need a DataView to control endianness, which might be different than the one of the platform where your C++ code is executed.