BitArray
Written by Redu, with contributions by Atriace due to the question of “How do I create a bit array in JavaScript”.
The BitArray class, starting with version 2.0, is implemented in TypeScript and built using AssemblyScript. However it’s JS compiled version is also available for the web.
BitArray utilizes bit masks to access the bits stored in groups of 8 bytes, known as <u64>, within an ArrayBufferView structure. In addition, this class offers convenient standard boolean operations, as described on Wikipedia.
Benefits of BitArray
BitArrayis developed with a focus on performance, and thanks to AssemblyScript WASM, it’s very fast. See the benchmarks below for more information.BitArrayhas a much smaller memory footprint compared to other types of arrays that hold the same number of boolean elements.
Constructor: BitArray(length)
length: A positive integerNumber. To ensure optimal performance, most properties and methods inBitArray, such as.popcnt(),.all(),.wipe(number), and.and(), use 64-bit access to the underlyingArrayBuffer. As a result, the buffer is always set to the minimum multiple of 8 bytes (64 bits) that is equal to or greater than the requested integer size. In theory,BitArrayshould support sizes up to 34,359,738,336 (0x07ffffffe0).
Installation
With Deno you can directly import the BitArray package from the Third Party Modules like
import { BA } from "https://deno.land/x/bit_array@v2.0.3/mod.ts"For JS environments like Web browsers you can directly import the JS compiled version from the Third Party Modules like
import { BA } from "https://deno.land/x/bit_array@v2.0.3/mod.js"Working with Node or Bun you can clone the BitArray Repo in your project folder and do like
import { BA } from "./JSBitArray/mod.ts"Syntax
new BA(length : number);Examples
Starting with something simple…
var a = new BA(10);
a.set(0);
a.set(3);
console.log(`${a}`); // 1001000000
a.length; // 10
a.popcnt(); // 2Properties
length : number: An immutable property returning the actual length of theBitArray.dataView : DataView: ThedataViewproperty ofBitArrayis an instance of a class that extends the standardDataViewobject. However, for safety reasons, this class does not expose the underlyingArrayBufferthrough thebufferproperty. Despite this, it is fully suitable for accessing and manipulating theBitArrayusingDataViewprototype methods such assetUint8(),getInt32(), etc.
Methods
Tests
.all() : boolean: Returnstrueif all bits in theBitArrayare set.
var a = new BA(10);
a.wipe(1); // 1111111111
a.all(); // true
a.reset(7);// 1111111011
a.all(); // false .any() : boolean: Returnstrueif any of the bits in theBitArrayare set. If returnsfalsethen all bits are 0.
var a = new BA(10);
a.any(); // false
a.set(7); // 0000000100
a.any(); // true .isEqual() : boolean: Returnstrueif testedBitArrays have the same bits set.
var a = new BA(10),
b;
a.wipe(2); // 1000111100 (randomly set bits)
b = a.slice(); // 1000111100
a.isEqual(b); // true Logical Operators
.and(bar : BitArray): And ofthisandbar. Example: 1100 & 1001 = 1000 returned as a newBitArray.
var a = new BA(10),
b = new BA(37),
c;
a.length; // 10
b.length; // 37
a.set(7); // 0000000100
a.set(8); // 0000000110
b.set(8); // 0000000010000000000000000000000000000
a.and(b); // 0000000010
b.and(a); // 0000000010.not() : BitArray: Returns a newBitArraywith all bits flipped. Example: 1100 = 0011..or(bar : BitArray) : BitArray: Or of this and bar. Example: 1100 & 1001 = 1101 returned as a newBitArray..xor(bar : BitArray) : BitArray: Xor of this and bar. Example: 1100 & 1001 = 0101 returned as a newBitArray.
In Place Modifiers
.reset(i : number) : BitArray: Resets the value at given indexi..set(i : number) : BitArray: Sets the value at given indexi..toggle(i : number) : BitArray: Flips the value at given indexi..wipe(n : number = 0) : BitArray:.wipe()or.wipe(0)fills theBitArraywith 0..wipe(1)fills theBitArraywith 1..wipe(2+)fills theBitArraywith random bits.
Others
.slice(a = 0, b = this.length) : BitArray: SlicesBitArrayand returns a newBitArray. When invoked with no arguments, the default argument values instantiate a clone. No negative values are allowed..toString() : string: Returns the string representation of theBitArray.
Benchmarks
We demonstrate a meaningful use case for the BitArray class in an optimized segmented Sieve of Sundaram algorithm for finding the number of prime numbers up to a given number n. While this single threaded PI function is still in pure JS it is tested against using 4 different array structures for n values ranging from 0 to 1000000 (1e6). Array, BitArray (without WASM), BitArrayWASM, and Uint8Array. The benchmarking was performed using Deno’s built-in benchmarking tool.
So just run
/path-to-project$ deno bench --unstable
at the root of the project to see it for yourself that this BitArray WASM implementation is around 20% faster by using only 12.5% of the memory footprint compared to native JS array structures.
| Benchmark | Time (avg) | (min … max) | p75 | p99 | p995 |
|---|---|---|---|---|---|
| Array : 0-1000000 | 6.67 ms/iter | (6.51 ms … 6.98 ms) | 6.71 ms | 6.98 ms | 6.98 ms |
| BitArray : 0-1000000 | 6.63 ms/iter | (6.4 ms … 7.48 ms) | 6.69 ms | 7.48 ms | 7.48 ms |
| BitArrayWASM : 0-1000000 | 4.93 ms/iter | (4.79 ms … 5.22 ms) | 5.01 ms | 5.12 ms | 5.22 ms |
| Uint8Array : 0-1000000 | 6.06 ms/iter | (5.86 ms … 7.62 ms) | 6.07 ms | 7.62 ms | 7.62 ms |