snowfrogdev
snowfrogdev

Reputation: 6873

How to efficiently add two JS numbers that are bit representation of several numbers stored as two's complements

I am storing four numbers, where 20 <= n >= -20, as 4 x 6-bit two's complements, in one JS primitive number by doing this:

function convertToBits(a: number, b: number, c: number, d: number) {
    const mask = 0b111111;
    return ((d & mask) << 18) | ((c & mask) << 12) | ((b & mask) << 6) | (a & mask);
}

convertToBits(-7, 31, 12, -32); // => 0b100000_001100_011111_111001

Given:

let a = convertToBits(-7, 31, 12, -31); // => 0b100001_001100_011111_111001
let b = convertToBits(7, -31, -12, 31); // => 0b011111_110100_100001_000111

I'm looking for an efficient way to add each of the four components of a with its corresponding component in b such that, given the inputs above:

function addBits(a: number, b: number) {
  // Missing implementation
}

addBits(a, b); // => 0b0;

Upvotes: 0

Views: 45

Answers (2)

Falk H&#252;ffner
Falk H&#252;ffner

Reputation: 5040

You can use the fact that for a single bit, the result of '+' (ignoring carry) is given by XOR. You can then calculate first the sum without the sign bits, possibly generating a carry in the sign bits, but not interfering with the next 6-bit group, and then factor in the sum of the sign bits. Untested code:

function addBits(x: number, y: number) {
    const signmask = 0b100000_100000_100000_100000;
    let sum_without_sign_bits = ((x & ~signmask) + (y & ~signmask));
    let sum_of_sign_bits = (x ^ y) & signmask;
    return sum_without_sign_bits ^ sum_of_sign_bits;
}

Upvotes: 1

snowfrogdev
snowfrogdev

Reputation: 6873

So I've come up with a way to get the result I'm looking for but I can't help but think there might be a more efficient way to do this. Nevertheless, it provides the correct output.

function addBits(a: number, b: number) {
  const mask = 0b111111;
  const m = ((a & mask) + (b & mask)) & mask;
  const n = (((a >> 6) & mask) + ((b >> 6) & mask)) & mask;
  const o = (((a >> 12) & mask) + ((b >> 12) & mask)) & mask;
  const p = ((a >> 18) & mask) + ((b >> 18) & (mask)) & mask;

  return m | (n << 6) | (o << 12) | (p << 18);
}

Upvotes: 0

Related Questions