tags:

views:

135

answers:

3

I want to create a large bit field in JavaScript that will effectively represent a multi-dimensional array of markers (uses indexing to jump to various dimensions in the physical "1D" structure).

Rather than a bunch of numbers, I'm considering how I might use a string as bits, so I can allocate a string of the appropriate length first. Considerations such as data types, Unicode and conversions come into play (also no Unicode support before JavaScript 1.3).

However I'm open about other suggestions how to use JavaScript to achieve a large bit field.

Update:
Just for informational purposes: On average I might be using ~2187 bits/markers (274 bytes), but would like a generic answer than can accommodate many more bits.

A: 

In chrome, I get about 10,000 bits.

var bitfield = 0;
var flag1 = 2 << 1;
var flag2 = 2 << 2;
var flagmax = 2 << 10000;
bitfield |= flagmax
if (bitfield & flagmax) {
    doSomething();
}
Matt Williamson
I see. You just blew away my assumption that number size remains static when bit shifting is employed. Good stuff.
John K
Bitwise operators in JavaScript only work with 32 bits, so `2 << 10000` overflows, and is equivalent to `2 << 16`.
Matthew Crumley
@Matthew C. Good to know - I didn't stop to think the above might be an untested attempt.
John K
My bad guys. You're right.
Matt Williamson
+2  A: 

One problem with strings is that they are immutable, so if you want to change anything, you would need to rebuild the string.

I would just stick to using numbers. Using the bitwise operators, you can fit 32 bits in each number.

You could fit up to 53 bits, since JavaScript numbers are double-precision floating point, but the bitwise operators convert their operands to 32-bit integers, so you wouldn't be able to use them to get at the individual bits (if you wanted to, you could accomplish the same thing with combinations of division, Math.pow, etc. but it would be more complicated).

Here's a basic implementation that lets you get, set, and unset individual bits:

function BitField() {
    this.values = []; // You could set the length here, but it's not necessary
}

BitField.prototype.get = function(i) {
    var index = (i / 32) | 0; // | 0 converts to an int. Math.floor works too.
    var bit = i % 32;
    return (this.values[index] & (1 << bit)) !== 0;
};

BitField.prototype.set = function(i) {
    var index = (i / 32) | 0;
    var bit = i % 32;
    this.values[index] |= 1 << bit;
};

BitField.prototype.unset = function(i) {
    var index = (i / 32) | 0;
    var bit = i % 32;
    this.values[index] &= ~(1 << bit);
};
Matthew Crumley
This works well.
John K
+1  A: 

If the browser you're targeting supports <canvas>, then you might borrow a CanvasPixelArray object (canvas.getContext("2d").createImageData(...).data; note that this need not be the same size as the canvas) to (hopefully) memory-efficiently store the data (each element is an octet). And if your data is 2D, you can get a visualization for free!

Kevin Reid
+1 I like it but cannot conform to HTML 5 yet. Thanks for the creative solution.
John K