UNPKG

node-hll

Version:
92 lines (77 loc) 2.43 kB
const HLL = require('./build/Release/node-hll.node').HLL; module.exports = class { constructor(arg) { if (Buffer.isBuffer(arg)) { const bits = Math.log2(arg.length); if (bits === Math.round(bits) && 4 <= bits && bits <= 20) { this._bits = bits; this._hll = new HLL(arg); } else { throw new Error('[HLL ctor] Invalid args.'); } } else if (4 <= arg && arg <= 20) { this._bits = arg; this._hll = new HLL(arg); } else { throw new Error('[HLL ctor] Invalid args.'); } } get bits() { return this._bits; } toBuffer() { return this._hll.toBuffer(); } add(item) { if (typeof item === 'string' || Buffer.isBuffer(item)) { this._hll.add(item); } else { throw new Error('[HLL add] Invalid args.'); } return this; } count() { return this._hll.count(); } /* * In place merge. */ merge(hll) { if (hll instanceof module.exports) { if (hll.bits !== this.bits) { throw new Error('[HLL merge] Hlls should have same bits.'); } this._hll.merge(hll._hll); } else { throw new Error('[HLL merge] Invalid args.'); } return this; } clone() { const r = new module.exports(this.bits); return r.merge(this); } /* * Returns a new hll that is h1 u h2. */ static merge(h1, h2) { return h1.clone().merge(h2); } /* * |A n B| = |A| + |B| - |A u B| * in the below, we set A = head, and B = tail. * then note that A u (B0 n B1 n ...) = (B0 u A) n (B1 u A) n ... * the latter we can compute with tail.map { _ + A } using the HLLInstance + * since + on HLLInstance creates the instance for the union. */ static intersectionSize(hlls) { if (hlls.length === 0) throw new Error('[HLL intersectionSize] Invalid args.'); if (hlls.length === 1) return hlls[0].count(); const head = hlls[0]; const tail = hlls.slice(1); const ret = head.count() + module.exports.intersectionSize(tail) - module.exports.intersectionSize(tail.map(h => h.clone().merge(head))); return Math.max(ret, 0); } };