Skip to content

Instantly share code, notes, and snippets.

@sciolist
Created May 15, 2013 09:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sciolist/5582704 to your computer and use it in GitHub Desktop.
Save sciolist/5582704 to your computer and use it in GitHub Desktop.
var index = new Index([
{ name: 'Moped', flags: ['slow', 'vehicle', 'red'] },
{ name: 'Car', flags: ['fast', 'vehicle', 'blue'] }
]);
index.facet('flags', function(m) { return m.flags });
var query = new BitField(index.items.length, true);
query.and(index.facets.flags.fast);
console.log(index.collect(query)); // [ { name: 'Car' } ... ]
query.or(index.facets.flags.red);
console.log(index.collect(query)); // [ { name: 'Moped' ... }, { name: 'Car' ...} ]
var shiftLength = 4 + 1;
function BitField(size, on) {
this.size = size;
this.array = Array((size >> shiftLength) + 1);
if(on) for(var i=0; i<this.size; ++i) this.set(i, true);
}
BitField.prototype.count = function() {
var c = 0;
for(var i=0; i<this.array.length; ++i) {
var x = this.array[i];
x = x - ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
c += ((x + (x >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}
return c;
};
BitField.prototype.set = function set(bit, value) {
var index = bit >> shiftLength;
if (value) this.array[index] |= 1 << (bit - (index << shiftLength));
else this.array[index] &= ~(1 << (bit - (index << shiftLength)));
};
BitField.prototype.isSet = function isSet(bit) {
var set = bit >> shiftLength;
return (this.array[set] & (1 << (bit - (set << shiftLength)))) != 0;
};
BitField.prototype.and = function and(bits) {
var other = bits.array;
var max = other.length > this.array.length ? this.array.length : other.length;
for (var i = 0; i < max; i++)
{
if (i > other.length)
{
this.array[i] = 0;
continue;
}
this.array[i] &= other[i];
}
};
BitField.prototype.or = function or(bits) {
var other = bits.array;
var max = other.length > this.array.length ? this.array.length : other.length;
for (var i = 0; i < max; i++) this.array[i] |= other[i];
};
BitField.prototype.all = function all() {
var debruijn = [ 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 ];
var currentValue = 0, index = -1, startingBit = 0;
var results = [];
while(index < this.array.length) {
while (currentValue == 0) {
index += 1;
if(index >= this.array.length) return results;
startingBit = index << shiftLength;
currentValue = this.array[index];
}
var lsb = currentValue & -currentValue;
currentValue ^= lsb;
results.push(startingBit + debruijn[(lsb * 0x77cb531) >> 27]);
}
return results;
}
function Index(items) {
this.items = items;
this.facets = {};
}
var index = Index.prototype;
index.facet = function(name, map) {
var facet = this.facets[name] = {};
var items = this.items;
for(var i=0, mi = items.length; i<mi; ++i) {
var values = map(items[i]);
if(!(values instanceof Array)) values = [values];
for(var j=0; j<values.length; ++j) {
var value = values[j];
if(!facet[value]) facet[value] = new BitField(items.length);
facet[value].set(i, true);
};
};
return this;
};
index.collect = function(bits) {
var arr = bits instanceof BitField ? bits.all() : bits;
var results = new Array(arr.length);
for(var i=0; i<arr.length; ++i) results[i] = this.items[arr[i]];
return results;
}
function SearchQuery(index) {
this.matches = new BitField(items.length, true);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment