commit fd8e588ac884040f8b10f03fbeb7e400d1e24452 Author: Jason Davies Date: Sun Sep 4 10:25:02 2011 +0100 Bloom filter in JavaScript using FNV hash. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a59d17e --- /dev/null +++ b/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2011, Jason Davies +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * The name Jason Davies may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL JASON DAVIES BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bloomfilter.js b/bloomfilter.js new file mode 100644 index 0000000..7cb5534 --- /dev/null +++ b/bloomfilter.js @@ -0,0 +1,62 @@ +(function(exports) { + function BloomFilter(m, k) { + this.m = m; + this.k = k; + this.buckets = []; + var n = Math.ceil(m / k), + i = -1; + while (++i < n) this.buckets[i] = 0; + } + + // See http://willwhim.wordpress.com/2011/09/03/producing-n-hash-functions-by-hashing-only-once/ + BloomFilter.prototype.locations = function(v) { + var h = fnv64(v); + a = h & 0xffffffff, + b = (h & 0xffffffff00000000) >> 32, + k = this.k, + r = [], + i = -1; + while (++i < k) r[i] = (a + b * i) % this.m; + return r; + }; + + BloomFilter.prototype.add = function(v) { + var l = this.locations(v), + i = -1, + k = this.k; + while (++i < k) this.buckets[Math.floor(l[i] / k)] |= 1 << (l[i] % k) + }; + + BloomFilter.prototype.test = function(v) { + var l = this.locations(v), + n = l.length, + i = -1, + k = this.k, + b; + while (++i < n) { + b = l[i]; + if ((this.buckets[Math.floor(b / k)] & (1 << (b % k))) === 0) { + return false; + } + } + return true; + }; + + // Fowler/Noll/Vo fast hash + function fnv64(d) { + var n = d.length, + h = 64, + i = -1, + c; + while (++i < n) { + c = d.charCodeAt(i); + h *= 1099511628211; + h ^= (c & 0xff00) >> 8; + h *= 1099511628211; + h ^= c & 0xff; + } + return h; + } + + exports.BloomFilter = BloomFilter; +})(typeof exports !== "undefined" ? exports : window); diff --git a/test.js b/test.js new file mode 100644 index 0000000..6990df7 --- /dev/null +++ b/test.js @@ -0,0 +1,10 @@ +var BloomFilter = require("./bloomfilter").BloomFilter; + +var f = new BloomFilter(100, 16); +f.add("foo"); + +var puts = require("util").puts; + +puts(f.test("foo")); +puts(f.test("foop")); +puts(f.test("bar"));