export default function(size, hash, equal, type, empty) { if (arguments.length === 3) { type = Array; empty = null; } var store = new type(size = 1 << Math.max(4, Math.ceil(Math.log(size) / Math.LN2))), mask = size - 1; for (var i = 0; i < size; ++i) { store[i] = empty; } function add(value) { var index = hash(value) & mask, match = store[index], collisions = 0; while (match != empty) { if (equal(match, value)) return true; if (++collisions >= size) throw new Error("full hashset"); match = store[index = (index + 1) & mask]; } store[index] = value; return true; } function has(value) { var index = hash(value) & mask, match = store[index], collisions = 0; while (match != empty) { if (equal(match, value)) return true; if (++collisions >= size) break; match = store[index = (index + 1) & mask]; } return false; } function values() { var values = []; for (var i = 0, n = store.length; i < n; ++i) { var match = store[i]; if (match != empty) values.push(match); } return values; } return { add: add, has: has, values: values }; }