crossfilter2
Version:
Fast multidimensional filtering for coordinated views.
192 lines (168 loc) • 4.66 kB
JavaScript
let array8 = arrayUntyped,
array16 = arrayUntyped,
array32 = arrayUntyped,
arrayLengthen = arrayLengthenUntyped,
arrayWiden = arrayWidenUntyped;
if (typeof Uint8Array !== "undefined") {
array8 = function(n) { return new Uint8Array(n); };
array16 = function(n) { return new Uint16Array(n); };
array32 = function(n) { return new Uint32Array(n); };
arrayLengthen = function(array, length) {
if (array.length >= length) return array;
var copy = new array.constructor(length);
copy.set(array);
return copy;
};
arrayWiden = function(array, width) {
var copy;
switch (width) {
case 16: copy = array16(array.length); break;
case 32: copy = array32(array.length); break;
default: throw new Error("invalid array width!");
}
copy.set(array);
return copy;
};
}
function arrayUntyped(n) {
var array = new Array(n), i = -1;
while (++i < n) array[i] = 0;
return array;
}
function arrayLengthenUntyped(array, length) {
var n = array.length;
while (n < length) array[n++] = 0;
return array;
}
function arrayWidenUntyped(array, width) {
if (width > 32) throw new Error("invalid array width!");
return array;
}
// An arbitrarily-wide array of bitmasks
function bitarray(n) {
this.length = n;
this.subarrays = 1;
this.width = 8;
this.masks = {
0: 0
}
this[0] = array8(n);
}
bitarray.prototype.lengthen = function(n) {
var i, len;
for (i = 0, len = this.subarrays; i < len; ++i) {
this[i] = arrayLengthen(this[i], n);
}
this.length = n;
};
// Reserve a new bit index in the array, returns {offset, one}
bitarray.prototype.add = function() {
var m, w, one, i, len;
for (i = 0, len = this.subarrays; i < len; ++i) {
m = this.masks[i];
w = this.width - (32 * i);
// isolate the rightmost zero bit and return it as an unsigned int of 32 bits, if NaN or -1, return a 0
one = (~m & (m + 1)) >>> 0;
if (w >= 32 && !one) {
continue;
}
if (w < 32 && (one & (1 << w))) {
// widen this subarray
this[i] = arrayWiden(this[i], w <<= 1);
this.width = 32 * i + w;
}
this.masks[i] |= one;
return {
offset: i,
one: one
};
}
// add a new subarray
this[this.subarrays] = array8(this.length);
this.masks[this.subarrays] = 1;
this.width += 8;
return {
offset: this.subarrays++,
one: 1
};
};
// Copy record from index src to index dest
bitarray.prototype.copy = function(dest, src) {
var i, len;
for (i = 0, len = this.subarrays; i < len; ++i) {
this[i][dest] = this[i][src];
}
};
// Truncate the array to the given length
bitarray.prototype.truncate = function(n) {
var i, len;
for (i = 0, len = this.subarrays; i < len; ++i) {
for (var j = this.length - 1; j >= n; j--) {
this[i][j] = 0;
}
}
this.length = n;
};
// Checks that all bits for the given index are 0
bitarray.prototype.zero = function(n) {
var i, len;
for (i = 0, len = this.subarrays; i < len; ++i) {
if (this[i][n]) {
return false;
}
}
return true;
};
// Checks that all bits for the given index are 0 except for possibly one
bitarray.prototype.zeroExcept = function(n, offset, zero) {
var i, len;
for (i = 0, len = this.subarrays; i < len; ++i) {
if (i === offset ? this[i][n] & zero : this[i][n]) {
return false;
}
}
return true;
};
// Checks that all bits for the given index are 0 except for the specified mask.
// The mask should be an array of the same size as the filter subarrays width.
bitarray.prototype.zeroExceptMask = function(n, mask) {
var i, len;
for (i = 0, len = this.subarrays; i < len; ++i) {
if (this[i][n] & mask[i]) {
return false;
}
}
return true;
}
// Checks that only the specified bit is set for the given index
bitarray.prototype.only = function(n, offset, one) {
var i, len;
for (i = 0, len = this.subarrays; i < len; ++i) {
if (this[i][n] != (i === offset ? one : 0)) {
return false;
}
}
return true;
};
// Checks that only the specified bit is set for the given index except for possibly one other
bitarray.prototype.onlyExcept = function(n, offset, zero, onlyOffset, onlyOne) {
var mask;
var i, len;
for (i = 0, len = this.subarrays; i < len; ++i) {
mask = this[i][n];
if (i === offset)
mask = (mask & zero) >>> 0;
if (mask != (i === onlyOffset ? onlyOne : 0)) {
return false;
}
}
return true;
};
export default {
array8: arrayUntyped,
array16: arrayUntyped,
array32: arrayUntyped,
arrayLengthen: arrayLengthenUntyped,
arrayWiden: arrayWidenUntyped,
bitarray: bitarray
};