What is the Javascript's highest value that can be safely used in a bitmask?

Viewed 74

Let's say I want to create a bitmask in Javascript. I would toggle a bit on like this:

mask |= (1 << bit);

clear a bit like this:

mask &= ~(1 << bit);

and check if a bit is set like this:

(bit & mask) != 0

My question is, what is the safest amount of bits that this works on in Javascript? I have three main guesses:

  1. 32 bits, as bit operations may be undefined past 32 bits
  2. 53 bits, as Number.MAX_SAFE_INTEGER is 2^53 - 1
  3. 64 bits, as Javascript uses 64 bits for each number

Which one is correct? Or is it something else?

2 Answers

32 bits:

Bitwise operators treat their operands as a set of 32 bits (zeros and ones) and return standard JavaScript numerical values.

Specification:

6.1.6.1.9 Number::leftShift ( x, y )

  1. Let lnum be ! ToInt32(x).
  2. Let rnum be ! ToUint32(y).
  3. Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.
  4. Return the result of left shifting lnum by shiftCount bits. The result is a signed 32-bit integer.

Note that if making use of the BigInt object then the bit mask is limited only by memory constraints, so one can manage masks well beyond 32 bits. Following generally along the lines of the question, for example, one can set a mask of 127 bits to all 1's as follows...

x = ( 1n << 128n ) - 1n

  • x: 340282366920938463463374607431768211455n
  • x.toString(2): 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

...and then, say, clear bit 16...

x &= ~( 1n << 16n )

  • x: 340282366920938463463374607431768145919n
  • x.toString(2): 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111101111111111111111

...and check if a bit, say 17, is set...

( ( 1n << 17n ) & x ) !== 0n

  • true

...or check if bit 16 is set...

( ( 1n << 16n ) & x ) !== 0n

  • false

JavaScript also has the BigUint64Array object which is a typed array of 64 bit unsigned BigInt integers in the platform byte order. This is also an option for bit mask requirements in the range of 33 bits to 64 bits...

Note that for extreme BigInt masks, it will likely be more performant to instead manage an array of Uint32's as the collective bit mask rather than using the native BigInt bit manipulation functions. So, if performance is at issue, one will need to experiment to determine if BigInt bit masks are acceptable for the use case at hand...

Related