skip to Main Content

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?

2

Answers


  1. The issue is that bitwise operators convert their operands to 32-bit integers first (unless working with BigInts). But 0x0001000200030004 cannot be represented using 32 bits, so the code does not work properly. The solution is to simply use BigInts for all operations instead.

    You would also need to reverse the order of iteration or reverse the output at the end to get the most significant digits first.

    function unpack(input) {
      const output = [];
      for (const packed of input) {
        for (let i = 3n; i >= 0n; i--) {
          const num = (packed >> (i * 16n)) & 0xffffn;
          const signedNum = num < 0x8000n ? num : -(0x10000n - num);
          output.push(signedNum);
        }
      }
      return output;
    }
    console.log(unpack([0x0001000200030004n]).map(x => x.toString()));
    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search